2 /*--------------------------------------------------------------------*/
3 /*--- begin guest_arm_toIR.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2004-2017 OpenWorks LLP
14 Copyright (C) 2010-2017 Samsung Electronics
15 contributed by Dmitry Zhurikhin <zhur@ispras.ru>
16 and Kirill Batuzov <batuzovk@ispras.ru>
18 This program is free software; you can redistribute it and/or
19 modify it under the terms of the GNU General Public License as
20 published by the Free Software Foundation; either version 2 of the
21 License, or (at your option) any later version.
23 This program is distributed in the hope that it will be useful, but
24 WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 The GNU General Public License is contained in the file COPYING.
36 /* XXXX thumb to check:
37 that all cases where putIRegT writes r15, we generate a jump.
39 All uses of newTemp assign to an IRTemp and not a UInt
41 For all thumb loads and stores, including VFP ones, new-ITSTATE is
42 backed out before the memory op, and restored afterwards. This
43 needs to happen even after we go uncond. (and for sure it doesn't
44 happen for VFP loads/stores right now).
46 VFP on thumb: check that we exclude all r13/r15 cases that we
49 XXXX thumb to do: improve the ITSTATE-zeroing optimisation by
50 taking into account the number of insns guarded by an IT.
52 remove the nasty hack, in the spechelper, of looking for Or32(...,
53 0xE0) in as the first arg to armg_calculate_condition, and instead
54 use Slice44 as specified in comments in the spechelper.
56 add specialisations for armg_calculate_flag_c and _v, as they
57 are moderately often needed in Thumb code.
59 Correctness: ITSTATE handling in Thumb SVCs is wrong.
61 Correctness (obscure): in m_transtab, when invalidating code
62 address ranges, invalidate up to 18 bytes after the end of the
63 range. This is because the ITSTATE optimisation at the top of
64 _THUMB_WRK below analyses up to 18 bytes before the start of any
65 given instruction, and so might depend on the invalidated area.
70 - pretty dodgy exception semantics for {LD,ST}Mxx and {LD,ST}RD.
71 These instructions are non-restartable in the case where the
74 - SWP: the restart jump back is Ijk_Boring; it should be
75 Ijk_NoRedir but that's expensive. See comments on casLE() in
79 /* "Special" instructions.
81 This instruction decoder can decode four special instructions
82 which mean nothing natively (are no-ops as far as regs/mem are
83 concerned) but have meaning for supporting Valgrind. A special
84 instruction is flagged by a 16-byte preamble:
86 E1A0C1EC E1A0C6EC E1A0CEEC E1A0C9EC
87 (mov r12, r12, ROR #3; mov r12, r12, ROR #13;
88 mov r12, r12, ROR #29; mov r12, r12, ROR #19)
90 Following that, one of the following 3 are allowed
91 (standard interpretation in parentheses):
93 E18AA00A (orr r10,r10,r10) R3 = client_request ( R4 )
94 E18BB00B (orr r11,r11,r11) R3 = guest_NRADDR
95 E18CC00C (orr r12,r12,r12) branch-and-link-to-noredir R4
96 E1899009 (orr r9,r9,r9) IR injection
98 Any other bytes following the 16-byte preamble are illegal and
99 constitute a failure in instruction decoding. This all assumes
100 that the preamble will never occur except in specific code
101 fragments designed for Valgrind to catch.
104 /* Translates ARM(v5) code to IR. */
106 #include "libvex_basictypes.h"
107 #include "libvex_ir.h"
109 #include "libvex_guest_arm.h"
111 #include "main_util.h"
112 #include "main_globals.h"
113 #include "guest_generic_bb_to_IR.h"
114 #include "guest_arm_defs.h"
117 /*------------------------------------------------------------*/
119 /*------------------------------------------------------------*/
121 /* These are set at the start of the translation of a instruction, so
122 that we don't have to pass them around endlessly. CONST means does
123 not change during translation of the instruction.
126 /* CONST: what is the host's endianness? This has to do with float vs
127 double register accesses on VFP, but it's complex and not properly
129 static VexEndness host_endness
;
131 /* CONST: The guest address for the instruction currently being
132 translated. This is the real, "decoded" address (not subject
133 to the CPSR.T kludge). */
134 static Addr32 guest_R15_curr_instr_notENC
;
136 /* CONST, FOR ASSERTIONS ONLY. Indicates whether currently processed
137 insn is Thumb (True) or ARM (False). */
138 static Bool __curr_is_Thumb
;
140 /* MOD: The IRSB* into which we're generating code. */
143 /* These are to do with handling writes to r15. They are initially
144 set at the start of disInstr_ARM_WRK to indicate no update,
145 possibly updated during the routine, and examined again at the end.
146 If they have been set to indicate a r15 update then a jump is
147 generated. Note, "explicit" jumps (b, bx, etc) are generated
148 directly, not using this mechanism -- this is intended to handle
149 the implicit-style jumps resulting from (eg) assigning to r15 as
150 the result of insns we wouldn't normally consider branchy. */
152 /* MOD. Initially False; set to True iff abovementioned handling is
154 static Bool r15written
;
156 /* MOD. Initially IRTemp_INVALID. If the r15 branch to be generated
157 is conditional, this holds the gating IRTemp :: Ity_I32. If the
158 branch to be generated is unconditional, this remains
160 static IRTemp r15guard
; /* :: Ity_I32, 0 or 1 */
162 /* MOD. Initially Ijk_Boring. If an r15 branch is to be generated,
163 this holds the jump kind. */
164 static IRTemp r15kind
;
167 /*------------------------------------------------------------*/
168 /*--- Debugging output ---*/
169 /*------------------------------------------------------------*/
171 #define DIP(format, args...) \
172 if (vex_traceflags & VEX_TRACE_FE) \
173 vex_printf(format, ## args)
175 #define DIS(buf, format, args...) \
176 if (vex_traceflags & VEX_TRACE_FE) \
177 vex_sprintf(buf, format, ## args)
179 #define ASSERT_IS_THUMB \
180 do { vassert(__curr_is_Thumb); } while (0)
182 #define ASSERT_IS_ARM \
183 do { vassert(! __curr_is_Thumb); } while (0)
186 /*------------------------------------------------------------*/
187 /*--- Helper bits and pieces for deconstructing the ---*/
188 /*--- arm insn stream. ---*/
189 /*------------------------------------------------------------*/
191 /* Do a little-endian load of a 32-bit word, regardless of the
192 endianness of the underlying host. */
193 static inline UInt
getUIntLittleEndianly ( const UChar
* p
)
203 /* Do a little-endian load of a 16-bit word, regardless of the
204 endianness of the underlying host. */
205 static inline UShort
getUShortLittleEndianly ( const UChar
* p
)
213 static UInt
ROR32 ( UInt x
, UInt sh
) {
214 vassert(sh
>= 0 && sh
< 32);
218 return (x
<< (32-sh
)) | (x
>> sh
);
221 static Int
popcount32 ( UInt x
)
224 for (i
= 0; i
< 32; i
++) {
231 static UInt
setbit32 ( UInt x
, Int ix
, UInt b
)
235 x
|= ((b
<< ix
) & mask
);
239 #define BITS2(_b1,_b0) \
240 (((_b1) << 1) | (_b0))
242 #define BITS3(_b2,_b1,_b0) \
243 (((_b2) << 2) | ((_b1) << 1) | (_b0))
245 #define BITS4(_b3,_b2,_b1,_b0) \
246 (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
248 #define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
249 ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
250 | BITS4((_b3),(_b2),(_b1),(_b0)))
252 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
253 (BITS8(0,0,0,(_b4),(_b3),(_b2),(_b1),(_b0)))
254 #define BITS6(_b5,_b4,_b3,_b2,_b1,_b0) \
255 (BITS8(0,0,(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
256 #define BITS7(_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
257 (BITS8(0,(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
259 #define BITS9(_b8,_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
261 | BITS8((_b7),(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
263 #define BITS10(_b9,_b8,_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
264 (((_b9) << 9) | ((_b8) << 8) \
265 | BITS8((_b7),(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
267 #define BITS11(_b10,_b9,_b8,_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
268 ( ((_b10) << 10) | ((_b9) << 9) | ((_b8) << 8) \
269 | BITS8((_b7),(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
271 #define BITS12(_b11,_b10,_b9,_b8,_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
272 ( ((_b11) << 11) | ((_b10) << 10) | ((_b9) << 9) | ((_b8) << 8) \
273 | BITS8((_b7),(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
275 /* produces _uint[_bMax:_bMin] */
276 #define SLICE_UInt(_uint,_bMax,_bMin) \
277 (( ((UInt)(_uint)) >> (_bMin)) \
278 & (UInt)((1ULL << ((_bMax) - (_bMin) + 1)) - 1ULL))
281 /*------------------------------------------------------------*/
282 /*--- Helper bits and pieces for creating IR fragments. ---*/
283 /*------------------------------------------------------------*/
285 static IRExpr
* mkU64 ( ULong i
)
287 return IRExpr_Const(IRConst_U64(i
));
290 static IRExpr
* mkU32 ( UInt i
)
292 return IRExpr_Const(IRConst_U32(i
));
295 static IRExpr
* mkU8 ( UInt i
)
298 return IRExpr_Const(IRConst_U8( (UChar
)i
));
301 static IRExpr
* mkexpr ( IRTemp tmp
)
303 return IRExpr_RdTmp(tmp
);
306 static IRExpr
* unop ( IROp op
, IRExpr
* a
)
308 return IRExpr_Unop(op
, a
);
311 static IRExpr
* binop ( IROp op
, IRExpr
* a1
, IRExpr
* a2
)
313 return IRExpr_Binop(op
, a1
, a2
);
316 static IRExpr
* triop ( IROp op
, IRExpr
* a1
, IRExpr
* a2
, IRExpr
* a3
)
318 return IRExpr_Triop(op
, a1
, a2
, a3
);
321 static IRExpr
* loadLE ( IRType ty
, IRExpr
* addr
)
323 return IRExpr_Load(Iend_LE
, ty
, addr
);
326 /* Add a statement to the list held by "irbb". */
327 static void stmt ( IRStmt
* st
)
329 addStmtToIRSB( irsb
, st
);
332 static void assign ( IRTemp dst
, IRExpr
* e
)
334 stmt( IRStmt_WrTmp(dst
, e
) );
337 static void storeLE ( IRExpr
* addr
, IRExpr
* data
)
339 stmt( IRStmt_Store(Iend_LE
, addr
, data
) );
342 static void storeGuardedLE ( IRExpr
* addr
, IRExpr
* data
, IRTemp guardT
)
344 if (guardT
== IRTemp_INVALID
) {
348 stmt( IRStmt_StoreG(Iend_LE
, addr
, data
,
349 binop(Iop_CmpNE32
, mkexpr(guardT
), mkU32(0))) );
353 static void loadGuardedLE ( IRTemp dst
, IRLoadGOp cvt
,
354 IRExpr
* addr
, IRExpr
* alt
,
355 IRTemp guardT
/* :: Ity_I32, 0 or 1 */ )
357 if (guardT
== IRTemp_INVALID
) {
359 IRExpr
* loaded
= NULL
;
362 loaded
= loadLE(Ity_I32
, addr
); break;
364 loaded
= unop(Iop_8Uto32
, loadLE(Ity_I8
, addr
)); break;
366 loaded
= unop(Iop_8Sto32
, loadLE(Ity_I8
, addr
)); break;
368 loaded
= unop(Iop_16Uto32
, loadLE(Ity_I16
, addr
)); break;
370 loaded
= unop(Iop_16Sto32
, loadLE(Ity_I16
, addr
)); break;
374 vassert(loaded
!= NULL
);
377 /* Generate a guarded load into 'dst', but apply 'cvt' to the
378 loaded data before putting the data in 'dst'. If the load
379 does not take place, 'alt' is placed directly in 'dst'. */
380 stmt( IRStmt_LoadG(Iend_LE
, cvt
, dst
, addr
, alt
,
381 binop(Iop_CmpNE32
, mkexpr(guardT
), mkU32(0))) );
385 /* Generate a new temporary of the given type. */
386 static IRTemp
newTemp ( IRType ty
)
388 vassert(isPlausibleIRType(ty
));
389 return newIRTemp( irsb
->tyenv
, ty
);
392 /* Produces a value in 0 .. 3, which is encoded as per the type
394 static IRExpr
* /* :: Ity_I32 */ get_FAKE_roundingmode ( void )
396 return mkU32(Irrm_NEAREST
);
399 /* Generate an expression for SRC rotated right by ROT. */
400 static IRExpr
* genROR32( IRTemp src
, Int rot
)
402 vassert(rot
>= 0 && rot
< 32);
407 binop(Iop_Shl32
, mkexpr(src
), mkU8(32 - rot
)),
408 binop(Iop_Shr32
, mkexpr(src
), mkU8(rot
)));
411 static IRExpr
* mkU128 ( ULong i
)
413 return binop(Iop_64HLtoV128
, mkU64(i
), mkU64(i
));
416 /* Generate a 4-aligned version of the given expression if
417 the given condition is true. Else return it unchanged. */
418 static IRExpr
* align4if ( IRExpr
* e
, Bool b
)
421 return binop(Iop_And32
, e
, mkU32(~3));
427 /*------------------------------------------------------------*/
428 /*--- Helpers for accessing guest registers. ---*/
429 /*------------------------------------------------------------*/
431 #define OFFB_R0 offsetof(VexGuestARMState,guest_R0)
432 #define OFFB_R1 offsetof(VexGuestARMState,guest_R1)
433 #define OFFB_R2 offsetof(VexGuestARMState,guest_R2)
434 #define OFFB_R3 offsetof(VexGuestARMState,guest_R3)
435 #define OFFB_R4 offsetof(VexGuestARMState,guest_R4)
436 #define OFFB_R5 offsetof(VexGuestARMState,guest_R5)
437 #define OFFB_R6 offsetof(VexGuestARMState,guest_R6)
438 #define OFFB_R7 offsetof(VexGuestARMState,guest_R7)
439 #define OFFB_R8 offsetof(VexGuestARMState,guest_R8)
440 #define OFFB_R9 offsetof(VexGuestARMState,guest_R9)
441 #define OFFB_R10 offsetof(VexGuestARMState,guest_R10)
442 #define OFFB_R11 offsetof(VexGuestARMState,guest_R11)
443 #define OFFB_R12 offsetof(VexGuestARMState,guest_R12)
444 #define OFFB_R13 offsetof(VexGuestARMState,guest_R13)
445 #define OFFB_R14 offsetof(VexGuestARMState,guest_R14)
446 #define OFFB_R15T offsetof(VexGuestARMState,guest_R15T)
448 #define OFFB_CC_OP offsetof(VexGuestARMState,guest_CC_OP)
449 #define OFFB_CC_DEP1 offsetof(VexGuestARMState,guest_CC_DEP1)
450 #define OFFB_CC_DEP2 offsetof(VexGuestARMState,guest_CC_DEP2)
451 #define OFFB_CC_NDEP offsetof(VexGuestARMState,guest_CC_NDEP)
452 #define OFFB_NRADDR offsetof(VexGuestARMState,guest_NRADDR)
454 #define OFFB_D0 offsetof(VexGuestARMState,guest_D0)
455 #define OFFB_D1 offsetof(VexGuestARMState,guest_D1)
456 #define OFFB_D2 offsetof(VexGuestARMState,guest_D2)
457 #define OFFB_D3 offsetof(VexGuestARMState,guest_D3)
458 #define OFFB_D4 offsetof(VexGuestARMState,guest_D4)
459 #define OFFB_D5 offsetof(VexGuestARMState,guest_D5)
460 #define OFFB_D6 offsetof(VexGuestARMState,guest_D6)
461 #define OFFB_D7 offsetof(VexGuestARMState,guest_D7)
462 #define OFFB_D8 offsetof(VexGuestARMState,guest_D8)
463 #define OFFB_D9 offsetof(VexGuestARMState,guest_D9)
464 #define OFFB_D10 offsetof(VexGuestARMState,guest_D10)
465 #define OFFB_D11 offsetof(VexGuestARMState,guest_D11)
466 #define OFFB_D12 offsetof(VexGuestARMState,guest_D12)
467 #define OFFB_D13 offsetof(VexGuestARMState,guest_D13)
468 #define OFFB_D14 offsetof(VexGuestARMState,guest_D14)
469 #define OFFB_D15 offsetof(VexGuestARMState,guest_D15)
470 #define OFFB_D16 offsetof(VexGuestARMState,guest_D16)
471 #define OFFB_D17 offsetof(VexGuestARMState,guest_D17)
472 #define OFFB_D18 offsetof(VexGuestARMState,guest_D18)
473 #define OFFB_D19 offsetof(VexGuestARMState,guest_D19)
474 #define OFFB_D20 offsetof(VexGuestARMState,guest_D20)
475 #define OFFB_D21 offsetof(VexGuestARMState,guest_D21)
476 #define OFFB_D22 offsetof(VexGuestARMState,guest_D22)
477 #define OFFB_D23 offsetof(VexGuestARMState,guest_D23)
478 #define OFFB_D24 offsetof(VexGuestARMState,guest_D24)
479 #define OFFB_D25 offsetof(VexGuestARMState,guest_D25)
480 #define OFFB_D26 offsetof(VexGuestARMState,guest_D26)
481 #define OFFB_D27 offsetof(VexGuestARMState,guest_D27)
482 #define OFFB_D28 offsetof(VexGuestARMState,guest_D28)
483 #define OFFB_D29 offsetof(VexGuestARMState,guest_D29)
484 #define OFFB_D30 offsetof(VexGuestARMState,guest_D30)
485 #define OFFB_D31 offsetof(VexGuestARMState,guest_D31)
487 #define OFFB_FPSCR offsetof(VexGuestARMState,guest_FPSCR)
488 #define OFFB_TPIDRURO offsetof(VexGuestARMState,guest_TPIDRURO)
489 #define OFFB_TPIDRURW offsetof(VexGuestARMState,guest_TPIDRURW)
490 #define OFFB_ITSTATE offsetof(VexGuestARMState,guest_ITSTATE)
491 #define OFFB_QFLAG32 offsetof(VexGuestARMState,guest_QFLAG32)
492 #define OFFB_GEFLAG0 offsetof(VexGuestARMState,guest_GEFLAG0)
493 #define OFFB_GEFLAG1 offsetof(VexGuestARMState,guest_GEFLAG1)
494 #define OFFB_GEFLAG2 offsetof(VexGuestARMState,guest_GEFLAG2)
495 #define OFFB_GEFLAG3 offsetof(VexGuestARMState,guest_GEFLAG3)
497 #define OFFB_CMSTART offsetof(VexGuestARMState,guest_CMSTART)
498 #define OFFB_CMLEN offsetof(VexGuestARMState,guest_CMLEN)
501 /* ---------------- Integer registers ---------------- */
503 static Int
integerGuestRegOffset ( UInt iregNo
)
505 /* Do we care about endianness here? We do if sub-parts of integer
506 registers are accessed, but I don't think that ever happens on
509 case 0: return OFFB_R0
;
510 case 1: return OFFB_R1
;
511 case 2: return OFFB_R2
;
512 case 3: return OFFB_R3
;
513 case 4: return OFFB_R4
;
514 case 5: return OFFB_R5
;
515 case 6: return OFFB_R6
;
516 case 7: return OFFB_R7
;
517 case 8: return OFFB_R8
;
518 case 9: return OFFB_R9
;
519 case 10: return OFFB_R10
;
520 case 11: return OFFB_R11
;
521 case 12: return OFFB_R12
;
522 case 13: return OFFB_R13
;
523 case 14: return OFFB_R14
;
524 case 15: return OFFB_R15T
;
529 /* Plain ("low level") read from a reg; no +8 offset magic for r15. */
530 static IRExpr
* llGetIReg ( UInt iregNo
)
532 vassert(iregNo
< 16);
533 return IRExpr_Get( integerGuestRegOffset(iregNo
), Ity_I32
);
536 /* Architected read from a reg in ARM mode. This automagically adds 8
537 to all reads of r15. */
538 static IRExpr
* getIRegA ( UInt iregNo
)
542 vassert(iregNo
< 16);
544 /* If asked for r15, don't read the guest state value, as that
545 may not be up to date in the case where loop unrolling has
546 happened, because the first insn's write to the block is
547 omitted; hence in the 2nd and subsequent unrollings we don't
548 have a correct value in guest r15. Instead produce the
549 constant that we know would be produced at this point. */
550 vassert(0 == (guest_R15_curr_instr_notENC
& 3));
551 e
= mkU32(guest_R15_curr_instr_notENC
+ 8);
553 e
= IRExpr_Get( integerGuestRegOffset(iregNo
), Ity_I32
);
558 /* Architected read from a reg in Thumb mode. This automagically adds
559 4 to all reads of r15. */
560 static IRExpr
* getIRegT ( UInt iregNo
)
564 vassert(iregNo
< 16);
566 /* Ditto comment in getIReg. */
567 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
568 e
= mkU32(guest_R15_curr_instr_notENC
+ 4);
570 e
= IRExpr_Get( integerGuestRegOffset(iregNo
), Ity_I32
);
575 /* Plain ("low level") write to a reg; no jump or alignment magic for
577 static void llPutIReg ( UInt iregNo
, IRExpr
* e
)
579 vassert(iregNo
< 16);
580 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I32
);
581 stmt( IRStmt_Put(integerGuestRegOffset(iregNo
), e
) );
584 /* Architected write to an integer register in ARM mode. If it is to
585 r15, record info so at the end of this insn's translation, a branch
586 to it can be made. Also handles conditional writes to the
587 register: if guardT == IRTemp_INVALID then the write is
588 unconditional. If writing r15, also 4-align it. */
589 static void putIRegA ( UInt iregNo
,
591 IRTemp guardT
/* :: Ity_I32, 0 or 1 */,
592 IRJumpKind jk
/* if a jump is generated */ )
594 /* if writing r15, force e to be 4-aligned. */
595 // INTERWORKING FIXME. this needs to be relaxed so that
596 // puts caused by LDMxx which load r15 interwork right.
597 // but is no aligned too relaxed?
599 // e = binop(Iop_And32, e, mkU32(~3));
601 /* So, generate either an unconditional or a conditional write to
603 if (guardT
== IRTemp_INVALID
) {
604 /* unconditional write */
605 llPutIReg( iregNo
, e
);
608 IRExpr_ITE( binop(Iop_CmpNE32
, mkexpr(guardT
), mkU32(0)),
609 e
, llGetIReg(iregNo
) ));
612 // assert against competing r15 updates. Shouldn't
613 // happen; should be ruled out by the instr matching
615 vassert(r15written
== False
);
616 vassert(r15guard
== IRTemp_INVALID
);
617 vassert(r15kind
== Ijk_Boring
);
625 /* Architected write to an integer register in Thumb mode. Writes to
626 r15 are not allowed. Handles conditional writes to the register:
627 if guardT == IRTemp_INVALID then the write is unconditional. */
628 static void putIRegT ( UInt iregNo
,
630 IRTemp guardT
/* :: Ity_I32, 0 or 1 */ )
632 /* So, generate either an unconditional or a conditional write to
635 vassert(iregNo
>= 0 && iregNo
<= 14);
636 if (guardT
== IRTemp_INVALID
) {
637 /* unconditional write */
638 llPutIReg( iregNo
, e
);
641 IRExpr_ITE( binop(Iop_CmpNE32
, mkexpr(guardT
), mkU32(0)),
642 e
, llGetIReg(iregNo
) ));
647 /* Thumb16 and Thumb32 only.
648 Returns true if reg is 13 or 15. Implements the BadReg
649 predicate in the ARM ARM. */
650 static Bool
isBadRegT ( UInt r
)
654 return r
== 13 || r
== 15;
658 /* ---------------- Double registers ---------------- */
660 static Int
doubleGuestRegOffset ( UInt dregNo
)
662 /* Do we care about endianness here? Probably do if we ever get
663 into the situation of dealing with the single-precision VFP
666 case 0: return OFFB_D0
;
667 case 1: return OFFB_D1
;
668 case 2: return OFFB_D2
;
669 case 3: return OFFB_D3
;
670 case 4: return OFFB_D4
;
671 case 5: return OFFB_D5
;
672 case 6: return OFFB_D6
;
673 case 7: return OFFB_D7
;
674 case 8: return OFFB_D8
;
675 case 9: return OFFB_D9
;
676 case 10: return OFFB_D10
;
677 case 11: return OFFB_D11
;
678 case 12: return OFFB_D12
;
679 case 13: return OFFB_D13
;
680 case 14: return OFFB_D14
;
681 case 15: return OFFB_D15
;
682 case 16: return OFFB_D16
;
683 case 17: return OFFB_D17
;
684 case 18: return OFFB_D18
;
685 case 19: return OFFB_D19
;
686 case 20: return OFFB_D20
;
687 case 21: return OFFB_D21
;
688 case 22: return OFFB_D22
;
689 case 23: return OFFB_D23
;
690 case 24: return OFFB_D24
;
691 case 25: return OFFB_D25
;
692 case 26: return OFFB_D26
;
693 case 27: return OFFB_D27
;
694 case 28: return OFFB_D28
;
695 case 29: return OFFB_D29
;
696 case 30: return OFFB_D30
;
697 case 31: return OFFB_D31
;
702 /* Plain ("low level") read from a VFP Dreg. */
703 static IRExpr
* llGetDReg ( UInt dregNo
)
705 vassert(dregNo
< 32);
706 return IRExpr_Get( doubleGuestRegOffset(dregNo
), Ity_F64
);
709 /* Architected read from a VFP Dreg. */
710 static IRExpr
* getDReg ( UInt dregNo
) {
711 return llGetDReg( dregNo
);
714 /* Plain ("low level") write to a VFP Dreg. */
715 static void llPutDReg ( UInt dregNo
, IRExpr
* e
)
717 vassert(dregNo
< 32);
718 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_F64
);
719 stmt( IRStmt_Put(doubleGuestRegOffset(dregNo
), e
) );
722 /* Architected write to a VFP Dreg. Handles conditional writes to the
723 register: if guardT == IRTemp_INVALID then the write is
725 static void putDReg ( UInt dregNo
,
727 IRTemp guardT
/* :: Ity_I32, 0 or 1 */)
729 /* So, generate either an unconditional or a conditional write to
731 if (guardT
== IRTemp_INVALID
) {
732 /* unconditional write */
733 llPutDReg( dregNo
, e
);
736 IRExpr_ITE( binop(Iop_CmpNE32
, mkexpr(guardT
), mkU32(0)),
737 e
, llGetDReg(dregNo
) ));
741 /* And now exactly the same stuff all over again, but this time
742 taking/returning I64 rather than F64, to support 64-bit Neon
745 /* Plain ("low level") read from a Neon Integer Dreg. */
746 static IRExpr
* llGetDRegI64 ( UInt dregNo
)
748 vassert(dregNo
< 32);
749 return IRExpr_Get( doubleGuestRegOffset(dregNo
), Ity_I64
);
752 /* Architected read from a Neon Integer Dreg. */
753 static IRExpr
* getDRegI64 ( UInt dregNo
) {
754 return llGetDRegI64( dregNo
);
757 /* Plain ("low level") write to a Neon Integer Dreg. */
758 static void llPutDRegI64 ( UInt dregNo
, IRExpr
* e
)
760 vassert(dregNo
< 32);
761 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I64
);
762 stmt( IRStmt_Put(doubleGuestRegOffset(dregNo
), e
) );
765 /* Architected write to a Neon Integer Dreg. Handles conditional
766 writes to the register: if guardT == IRTemp_INVALID then the write
768 static void putDRegI64 ( UInt dregNo
,
770 IRTemp guardT
/* :: Ity_I32, 0 or 1 */)
772 /* So, generate either an unconditional or a conditional write to
774 if (guardT
== IRTemp_INVALID
) {
775 /* unconditional write */
776 llPutDRegI64( dregNo
, e
);
778 llPutDRegI64( dregNo
,
779 IRExpr_ITE( binop(Iop_CmpNE32
, mkexpr(guardT
), mkU32(0)),
780 e
, llGetDRegI64(dregNo
) ));
784 /* ---------------- Quad registers ---------------- */
786 static Int
quadGuestRegOffset ( UInt qregNo
)
788 /* Do we care about endianness here? Probably do if we ever get
789 into the situation of dealing with the 64 bit Neon registers. */
791 case 0: return OFFB_D0
;
792 case 1: return OFFB_D2
;
793 case 2: return OFFB_D4
;
794 case 3: return OFFB_D6
;
795 case 4: return OFFB_D8
;
796 case 5: return OFFB_D10
;
797 case 6: return OFFB_D12
;
798 case 7: return OFFB_D14
;
799 case 8: return OFFB_D16
;
800 case 9: return OFFB_D18
;
801 case 10: return OFFB_D20
;
802 case 11: return OFFB_D22
;
803 case 12: return OFFB_D24
;
804 case 13: return OFFB_D26
;
805 case 14: return OFFB_D28
;
806 case 15: return OFFB_D30
;
811 /* Plain ("low level") read from a Neon Qreg. */
812 static IRExpr
* llGetQReg ( UInt qregNo
)
814 vassert(qregNo
< 16);
815 return IRExpr_Get( quadGuestRegOffset(qregNo
), Ity_V128
);
818 /* Architected read from a Neon Qreg. */
819 static IRExpr
* getQReg ( UInt qregNo
) {
820 return llGetQReg( qregNo
);
823 /* Plain ("low level") write to a Neon Qreg. */
824 static void llPutQReg ( UInt qregNo
, IRExpr
* e
)
826 vassert(qregNo
< 16);
827 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_V128
);
828 stmt( IRStmt_Put(quadGuestRegOffset(qregNo
), e
) );
831 /* Architected write to a Neon Qreg. Handles conditional writes to the
832 register: if guardT == IRTemp_INVALID then the write is
834 static void putQReg ( UInt qregNo
,
836 IRTemp guardT
/* :: Ity_I32, 0 or 1 */)
838 /* So, generate either an unconditional or a conditional write to
840 if (guardT
== IRTemp_INVALID
) {
841 /* unconditional write */
842 llPutQReg( qregNo
, e
);
845 IRExpr_ITE( binop(Iop_CmpNE32
, mkexpr(guardT
), mkU32(0)),
846 e
, llGetQReg(qregNo
) ));
851 /* ---------------- Float registers ---------------- */
853 static Int
floatGuestRegOffset ( UInt fregNo
)
855 /* Start with the offset of the containing double, and then correct
856 for endianness. Actually this is completely bogus and needs
859 /* NB! Limit is 64, not 32, because we might be pulling F32 bits
860 out of SIMD registers, and there are 16 SIMD registers each of
861 128 bits (4 x F32). */
862 vassert(fregNo
< 64);
863 off
= doubleGuestRegOffset(fregNo
>> 1);
864 if (host_endness
== VexEndnessLE
) {
873 /* Plain ("low level") read from a VFP Freg. */
874 static IRExpr
* llGetFReg ( UInt fregNo
)
876 vassert(fregNo
< 32);
877 return IRExpr_Get( floatGuestRegOffset(fregNo
), Ity_F32
);
880 static IRExpr
* llGetFReg_up_to_64 ( UInt fregNo
)
882 vassert(fregNo
< 64);
883 return IRExpr_Get( floatGuestRegOffset(fregNo
), Ity_F32
);
886 /* Architected read from a VFP Freg. */
887 static IRExpr
* getFReg ( UInt fregNo
) {
888 return llGetFReg( fregNo
);
891 /* Plain ("low level") write to a VFP Freg. */
892 static void llPutFReg ( UInt fregNo
, IRExpr
* e
)
894 vassert(fregNo
< 32);
895 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_F32
);
896 stmt( IRStmt_Put(floatGuestRegOffset(fregNo
), e
) );
899 static void llPutFReg_up_to_64 ( UInt fregNo
, IRExpr
* e
)
901 vassert(fregNo
< 64);
902 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_F32
);
903 stmt( IRStmt_Put(floatGuestRegOffset(fregNo
), e
) );
906 /* Architected write to a VFP Freg. Handles conditional writes to the
907 register: if guardT == IRTemp_INVALID then the write is
909 static void putFReg ( UInt fregNo
,
911 IRTemp guardT
/* :: Ity_I32, 0 or 1 */)
913 /* So, generate either an unconditional or a conditional write to
915 if (guardT
== IRTemp_INVALID
) {
916 /* unconditional write */
917 llPutFReg( fregNo
, e
);
920 IRExpr_ITE( binop(Iop_CmpNE32
, mkexpr(guardT
), mkU32(0)),
921 e
, llGetFReg(fregNo
) ));
926 /* ---------------- Misc registers ---------------- */
928 static void putMiscReg32 ( UInt gsoffset
,
929 IRExpr
* e
, /* :: Ity_I32 */
930 IRTemp guardT
/* :: Ity_I32, 0 or 1 */)
933 case OFFB_FPSCR
: break;
934 case OFFB_QFLAG32
: break;
935 case OFFB_GEFLAG0
: break;
936 case OFFB_GEFLAG1
: break;
937 case OFFB_GEFLAG2
: break;
938 case OFFB_GEFLAG3
: break;
939 case OFFB_TPIDRURW
: break;
940 default: vassert(0); /* awaiting more cases */
942 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I32
);
944 if (guardT
== IRTemp_INVALID
) {
945 /* unconditional write */
946 stmt(IRStmt_Put(gsoffset
, e
));
950 IRExpr_ITE( binop(Iop_CmpNE32
, mkexpr(guardT
), mkU32(0)),
951 e
, IRExpr_Get(gsoffset
, Ity_I32
) )
956 static IRTemp
get_ITSTATE ( void )
959 IRTemp t
= newTemp(Ity_I32
);
960 assign(t
, IRExpr_Get( OFFB_ITSTATE
, Ity_I32
));
964 static void put_ITSTATE ( IRTemp t
)
967 stmt( IRStmt_Put( OFFB_ITSTATE
, mkexpr(t
)) );
970 static IRTemp
get_QFLAG32 ( void )
972 IRTemp t
= newTemp(Ity_I32
);
973 assign(t
, IRExpr_Get( OFFB_QFLAG32
, Ity_I32
));
977 static void put_QFLAG32 ( IRTemp t
, IRTemp condT
)
979 putMiscReg32( OFFB_QFLAG32
, mkexpr(t
), condT
);
982 /* Stickily set the 'Q' flag (APSR bit 27) of the APSR (Application Program
983 Status Register) to indicate that overflow or saturation occurred.
984 Nb: t must be zero to denote no saturation, and any nonzero
985 value to indicate saturation. */
986 static void or_into_QFLAG32 ( IRExpr
* e
, IRTemp condT
)
988 IRTemp old
= get_QFLAG32();
989 IRTemp nyu
= newTemp(Ity_I32
);
990 assign(nyu
, binop(Iop_Or32
, mkexpr(old
), e
) );
991 put_QFLAG32(nyu
, condT
);
994 /* Generate code to set APSR.GE[flagNo]. Each fn call sets 1 bit.
995 flagNo: which flag bit to set [3...0]
996 lowbits_to_ignore: 0 = look at all 32 bits
997 8 = look at top 24 bits only
998 16 = look at top 16 bits only
999 31 = look at the top bit only
1000 e: input value to be evaluated.
1001 The new value is taken from 'e' with the lowest 'lowbits_to_ignore'
1002 masked out. If the resulting value is zero then the GE flag is
1003 set to 0; any other value sets the flag to 1. */
1004 static void put_GEFLAG32 ( Int flagNo
, /* 0, 1, 2 or 3 */
1005 Int lowbits_to_ignore
, /* 0, 8, 16 or 31 */
1006 IRExpr
* e
, /* Ity_I32 */
1009 vassert( flagNo
>= 0 && flagNo
<= 3 );
1010 vassert( lowbits_to_ignore
== 0 ||
1011 lowbits_to_ignore
== 8 ||
1012 lowbits_to_ignore
== 16 ||
1013 lowbits_to_ignore
== 31 );
1014 IRTemp masked
= newTemp(Ity_I32
);
1015 assign(masked
, binop(Iop_Shr32
, e
, mkU8(lowbits_to_ignore
)));
1018 case 0: putMiscReg32(OFFB_GEFLAG0
, mkexpr(masked
), condT
); break;
1019 case 1: putMiscReg32(OFFB_GEFLAG1
, mkexpr(masked
), condT
); break;
1020 case 2: putMiscReg32(OFFB_GEFLAG2
, mkexpr(masked
), condT
); break;
1021 case 3: putMiscReg32(OFFB_GEFLAG3
, mkexpr(masked
), condT
); break;
1022 default: vassert(0);
1026 /* Return the (32-bit, zero-or-nonzero representation scheme) of
1027 the specified GE flag. */
1028 static IRExpr
* get_GEFLAG32( Int flagNo
/* 0, 1, 2, 3 */ )
1031 case 0: return IRExpr_Get( OFFB_GEFLAG0
, Ity_I32
);
1032 case 1: return IRExpr_Get( OFFB_GEFLAG1
, Ity_I32
);
1033 case 2: return IRExpr_Get( OFFB_GEFLAG2
, Ity_I32
);
1034 case 3: return IRExpr_Get( OFFB_GEFLAG3
, Ity_I32
);
1035 default: vassert(0);
1039 /* Set all 4 GE flags from the given 32-bit value as follows: GE 3 and
1040 2 are set from bit 31 of the value, and GE 1 and 0 are set from bit
1041 15 of the value. All other bits are ignored. */
1042 static void set_GE_32_10_from_bits_31_15 ( IRTemp t32
, IRTemp condT
)
1044 IRTemp ge10
= newTemp(Ity_I32
);
1045 IRTemp ge32
= newTemp(Ity_I32
);
1046 assign(ge10
, binop(Iop_And32
, mkexpr(t32
), mkU32(0x00008000)));
1047 assign(ge32
, binop(Iop_And32
, mkexpr(t32
), mkU32(0x80000000)));
1048 put_GEFLAG32( 0, 0, mkexpr(ge10
), condT
);
1049 put_GEFLAG32( 1, 0, mkexpr(ge10
), condT
);
1050 put_GEFLAG32( 2, 0, mkexpr(ge32
), condT
);
1051 put_GEFLAG32( 3, 0, mkexpr(ge32
), condT
);
1055 /* Set all 4 GE flags from the given 32-bit value as follows: GE 3
1056 from bit 31, GE 2 from bit 23, GE 1 from bit 15, and GE0 from
1057 bit 7. All other bits are ignored. */
1058 static void set_GE_3_2_1_0_from_bits_31_23_15_7 ( IRTemp t32
, IRTemp condT
)
1060 IRTemp ge0
= newTemp(Ity_I32
);
1061 IRTemp ge1
= newTemp(Ity_I32
);
1062 IRTemp ge2
= newTemp(Ity_I32
);
1063 IRTemp ge3
= newTemp(Ity_I32
);
1064 assign(ge0
, binop(Iop_And32
, mkexpr(t32
), mkU32(0x00000080)));
1065 assign(ge1
, binop(Iop_And32
, mkexpr(t32
), mkU32(0x00008000)));
1066 assign(ge2
, binop(Iop_And32
, mkexpr(t32
), mkU32(0x00800000)));
1067 assign(ge3
, binop(Iop_And32
, mkexpr(t32
), mkU32(0x80000000)));
1068 put_GEFLAG32( 0, 0, mkexpr(ge0
), condT
);
1069 put_GEFLAG32( 1, 0, mkexpr(ge1
), condT
);
1070 put_GEFLAG32( 2, 0, mkexpr(ge2
), condT
);
1071 put_GEFLAG32( 3, 0, mkexpr(ge3
), condT
);
1075 /* ---------------- FPSCR stuff ---------------- */
1077 /* Generate IR to get hold of the rounding mode bits in FPSCR, and
1078 convert them to IR format. Bind the final result to the
1080 static IRTemp
/* :: Ity_I32 */ mk_get_IR_rounding_mode ( void )
1082 /* The ARMvfp encoding for rounding mode bits is:
1087 We need to convert that to the IR encoding:
1088 00 to nearest (the default)
1092 Which can be done by swapping bits 0 and 1.
1093 The rmode bits are at 23:22 in FPSCR.
1095 IRTemp armEncd
= newTemp(Ity_I32
);
1096 IRTemp swapped
= newTemp(Ity_I32
);
1097 /* Fish FPSCR[23:22] out, and slide to bottom. Doesn't matter that
1098 we don't zero out bits 24 and above, since the assignment to
1099 'swapped' will mask them out anyway. */
1101 binop(Iop_Shr32
, IRExpr_Get(OFFB_FPSCR
, Ity_I32
), mkU8(22)));
1102 /* Now swap them. */
1106 binop(Iop_Shl32
, mkexpr(armEncd
), mkU8(1)),
1109 binop(Iop_Shr32
, mkexpr(armEncd
), mkU8(1)),
1116 /*------------------------------------------------------------*/
1117 /*--- Helpers for flag handling and conditional insns ---*/
1118 /*------------------------------------------------------------*/
1120 static const HChar
* name_ARMCondcode ( ARMCondcode cond
)
1123 case ARMCondEQ
: return "{eq}";
1124 case ARMCondNE
: return "{ne}";
1125 case ARMCondHS
: return "{hs}"; // or 'cs'
1126 case ARMCondLO
: return "{lo}"; // or 'cc'
1127 case ARMCondMI
: return "{mi}";
1128 case ARMCondPL
: return "{pl}";
1129 case ARMCondVS
: return "{vs}";
1130 case ARMCondVC
: return "{vc}";
1131 case ARMCondHI
: return "{hi}";
1132 case ARMCondLS
: return "{ls}";
1133 case ARMCondGE
: return "{ge}";
1134 case ARMCondLT
: return "{lt}";
1135 case ARMCondGT
: return "{gt}";
1136 case ARMCondLE
: return "{le}";
1137 case ARMCondAL
: return ""; // {al}: is the default
1138 case ARMCondNV
: return "{nv}";
1139 default: vpanic("name_ARMCondcode");
1142 /* and a handy shorthand for it */
1143 static const HChar
* nCC ( ARMCondcode cond
) {
1144 return name_ARMCondcode(cond
);
1148 /* Build IR to calculate some particular condition from stored
1149 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression of type
1150 Ity_I32, suitable for narrowing. Although the return type is
1151 Ity_I32, the returned value is either 0 or 1. 'cond' must be
1152 :: Ity_I32 and must denote the condition to compute in
1153 bits 7:4, and be zero everywhere else.
1155 static IRExpr
* mk_armg_calculate_condition_dyn ( IRExpr
* cond
)
1157 vassert(typeOfIRExpr(irsb
->tyenv
, cond
) == Ity_I32
);
1158 /* And 'cond' had better produce a value in which only bits 7:4 are
1159 nonzero. However, obviously we can't assert for that. */
1161 /* So what we're constructing for the first argument is
1162 "(cond << 4) | stored-operation".
1163 However, as per comments above, 'cond' must be supplied
1164 pre-shifted to this function.
1166 This pairing scheme requires that the ARM_CC_OP_ values all fit
1167 in 4 bits. Hence we are passing a (COND, OP) pair in the lowest
1168 8 bits of the first argument. */
1171 binop(Iop_Or32
, IRExpr_Get(OFFB_CC_OP
, Ity_I32
), cond
),
1172 IRExpr_Get(OFFB_CC_DEP1
, Ity_I32
),
1173 IRExpr_Get(OFFB_CC_DEP2
, Ity_I32
),
1174 IRExpr_Get(OFFB_CC_NDEP
, Ity_I32
)
1180 "armg_calculate_condition", &armg_calculate_condition
,
1184 /* Exclude the requested condition, OP and NDEP from definedness
1185 checking. We're only interested in DEP1 and DEP2. */
1186 call
->Iex
.CCall
.cee
->mcx_mask
= (1<<0) | (1<<3);
1191 /* Build IR to calculate some particular condition from stored
1192 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression of type
1193 Ity_I32, suitable for narrowing. Although the return type is
1194 Ity_I32, the returned value is either 0 or 1.
1196 static IRExpr
* mk_armg_calculate_condition ( ARMCondcode cond
)
1198 /* First arg is "(cond << 4) | condition". This requires that the
1199 ARM_CC_OP_ values all fit in 4 bits. Hence we are passing a
1200 (COND, OP) pair in the lowest 8 bits of the first argument. */
1201 vassert(cond
>= 0 && cond
<= 15);
1202 return mk_armg_calculate_condition_dyn( mkU32(cond
<< 4) );
1206 /* Build IR to calculate just the carry flag from stored
1207 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression ::
1209 static IRExpr
* mk_armg_calculate_flag_c ( void )
1212 = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP
, Ity_I32
),
1213 IRExpr_Get(OFFB_CC_DEP1
, Ity_I32
),
1214 IRExpr_Get(OFFB_CC_DEP2
, Ity_I32
),
1215 IRExpr_Get(OFFB_CC_NDEP
, Ity_I32
) );
1220 "armg_calculate_flag_c", &armg_calculate_flag_c
,
1223 /* Exclude OP and NDEP from definedness checking. We're only
1224 interested in DEP1 and DEP2. */
1225 call
->Iex
.CCall
.cee
->mcx_mask
= (1<<0) | (1<<3);
1230 /* Build IR to calculate just the overflow flag from stored
1231 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression ::
1233 static IRExpr
* mk_armg_calculate_flag_v ( void )
1236 = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP
, Ity_I32
),
1237 IRExpr_Get(OFFB_CC_DEP1
, Ity_I32
),
1238 IRExpr_Get(OFFB_CC_DEP2
, Ity_I32
),
1239 IRExpr_Get(OFFB_CC_NDEP
, Ity_I32
) );
1244 "armg_calculate_flag_v", &armg_calculate_flag_v
,
1247 /* Exclude OP and NDEP from definedness checking. We're only
1248 interested in DEP1 and DEP2. */
1249 call
->Iex
.CCall
.cee
->mcx_mask
= (1<<0) | (1<<3);
1254 /* Build IR to calculate N Z C V in bits 31:28 of the
1256 static IRExpr
* mk_armg_calculate_flags_nzcv ( void )
1259 = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP
, Ity_I32
),
1260 IRExpr_Get(OFFB_CC_DEP1
, Ity_I32
),
1261 IRExpr_Get(OFFB_CC_DEP2
, Ity_I32
),
1262 IRExpr_Get(OFFB_CC_NDEP
, Ity_I32
) );
1267 "armg_calculate_flags_nzcv", &armg_calculate_flags_nzcv
,
1270 /* Exclude OP and NDEP from definedness checking. We're only
1271 interested in DEP1 and DEP2. */
1272 call
->Iex
.CCall
.cee
->mcx_mask
= (1<<0) | (1<<3);
1276 static IRExpr
* mk_armg_calculate_flag_qc ( IRExpr
* resL
, IRExpr
* resR
, Bool Q
)
1280 IRExpr
*call1
, *call2
, *res
;
1283 args1
= mkIRExprVec_4 ( binop(Iop_GetElem32x4
, resL
, mkU8(0)),
1284 binop(Iop_GetElem32x4
, resL
, mkU8(1)),
1285 binop(Iop_GetElem32x4
, resR
, mkU8(0)),
1286 binop(Iop_GetElem32x4
, resR
, mkU8(1)) );
1287 args2
= mkIRExprVec_4 ( binop(Iop_GetElem32x4
, resL
, mkU8(2)),
1288 binop(Iop_GetElem32x4
, resL
, mkU8(3)),
1289 binop(Iop_GetElem32x4
, resR
, mkU8(2)),
1290 binop(Iop_GetElem32x4
, resR
, mkU8(3)) );
1292 args1
= mkIRExprVec_4 ( binop(Iop_GetElem32x2
, resL
, mkU8(0)),
1293 binop(Iop_GetElem32x2
, resL
, mkU8(1)),
1294 binop(Iop_GetElem32x2
, resR
, mkU8(0)),
1295 binop(Iop_GetElem32x2
, resR
, mkU8(1)) );
1298 call1
= mkIRExprCCall(
1301 "armg_calculate_flag_qc", &armg_calculate_flag_qc
,
1305 call2
= mkIRExprCCall(
1308 "armg_calculate_flag_qc", &armg_calculate_flag_qc
,
1313 res
= binop(Iop_Or32
, call1
, call2
);
1320 // FIXME: this is named wrongly .. looks like a sticky set of
1321 // QC, not a write to it.
1322 static void setFlag_QC ( IRExpr
* resL
, IRExpr
* resR
, Bool Q
,
1325 putMiscReg32 (OFFB_FPSCR
,
1327 IRExpr_Get(OFFB_FPSCR
, Ity_I32
),
1329 mk_armg_calculate_flag_qc(resL
, resR
, Q
),
1334 /* Build IR to conditionally set the flags thunk. As with putIReg, if
1335 guard is IRTemp_INVALID then it's unconditional, else it holds a
1336 condition :: Ity_I32. */
1338 void setFlags_D1_D2_ND ( UInt cc_op
, IRTemp t_dep1
,
1339 IRTemp t_dep2
, IRTemp t_ndep
,
1340 IRTemp guardT
/* :: Ity_I32, 0 or 1 */ )
1342 vassert(typeOfIRTemp(irsb
->tyenv
, t_dep1
== Ity_I32
));
1343 vassert(typeOfIRTemp(irsb
->tyenv
, t_dep2
== Ity_I32
));
1344 vassert(typeOfIRTemp(irsb
->tyenv
, t_ndep
== Ity_I32
));
1345 vassert(cc_op
>= ARMG_CC_OP_COPY
&& cc_op
< ARMG_CC_OP_NUMBER
);
1346 if (guardT
== IRTemp_INVALID
) {
1348 stmt( IRStmt_Put( OFFB_CC_OP
, mkU32(cc_op
) ));
1349 stmt( IRStmt_Put( OFFB_CC_DEP1
, mkexpr(t_dep1
) ));
1350 stmt( IRStmt_Put( OFFB_CC_DEP2
, mkexpr(t_dep2
) ));
1351 stmt( IRStmt_Put( OFFB_CC_NDEP
, mkexpr(t_ndep
) ));
1354 IRTemp c1
= newTemp(Ity_I1
);
1355 assign( c1
, binop(Iop_CmpNE32
, mkexpr(guardT
), mkU32(0)) );
1358 IRExpr_ITE( mkexpr(c1
),
1360 IRExpr_Get(OFFB_CC_OP
, Ity_I32
) ) ));
1363 IRExpr_ITE( mkexpr(c1
),
1365 IRExpr_Get(OFFB_CC_DEP1
, Ity_I32
) ) ));
1368 IRExpr_ITE( mkexpr(c1
),
1370 IRExpr_Get(OFFB_CC_DEP2
, Ity_I32
) ) ));
1373 IRExpr_ITE( mkexpr(c1
),
1375 IRExpr_Get(OFFB_CC_NDEP
, Ity_I32
) ) ));
1380 /* Minor variant of the above that sets NDEP to zero (if it
1382 static void setFlags_D1_D2 ( UInt cc_op
, IRTemp t_dep1
,
1384 IRTemp guardT
/* :: Ity_I32, 0 or 1 */ )
1386 IRTemp z32
= newTemp(Ity_I32
);
1387 assign( z32
, mkU32(0) );
1388 setFlags_D1_D2_ND( cc_op
, t_dep1
, t_dep2
, z32
, guardT
);
1392 /* Minor variant of the above that sets DEP2 to zero (if it
1394 static void setFlags_D1_ND ( UInt cc_op
, IRTemp t_dep1
,
1396 IRTemp guardT
/* :: Ity_I32, 0 or 1 */ )
1398 IRTemp z32
= newTemp(Ity_I32
);
1399 assign( z32
, mkU32(0) );
1400 setFlags_D1_D2_ND( cc_op
, t_dep1
, z32
, t_ndep
, guardT
);
1404 /* Minor variant of the above that sets DEP2 and NDEP to zero (if it
1405 sets them at all) */
1406 static void setFlags_D1 ( UInt cc_op
, IRTemp t_dep1
,
1407 IRTemp guardT
/* :: Ity_I32, 0 or 1 */ )
1409 IRTemp z32
= newTemp(Ity_I32
);
1410 assign( z32
, mkU32(0) );
1411 setFlags_D1_D2_ND( cc_op
, t_dep1
, z32
, z32
, guardT
);
1416 /* Generate a side-exit to the next instruction, if the given guard
1417 expression :: Ity_I32 is 0 (note! the side exit is taken if the
1418 condition is false!) This is used to skip over conditional
1419 instructions which we can't generate straight-line code for, either
1420 because they are too complex or (more likely) they potentially
1421 generate exceptions.
1423 static void mk_skip_over_A32_if_cond_is_false (
1424 IRTemp guardT
/* :: Ity_I32, 0 or 1 */
1428 vassert(guardT
!= IRTemp_INVALID
);
1429 vassert(0 == (guest_R15_curr_instr_notENC
& 3));
1431 unop(Iop_Not1
, unop(Iop_32to1
, mkexpr(guardT
))),
1433 IRConst_U32(toUInt(guest_R15_curr_instr_notENC
+ 4)),
1439 /* ditto, but jump over a 16-bit thumb insn */
1440 static void mk_skip_over_T16_if_cond_is_false (
1441 IRTemp guardT
/* :: Ity_I32, 0 or 1 */
1445 vassert(guardT
!= IRTemp_INVALID
);
1446 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
1448 unop(Iop_Not1
, unop(Iop_32to1
, mkexpr(guardT
))),
1450 IRConst_U32(toUInt((guest_R15_curr_instr_notENC
+ 2) | 1)),
1457 /* ditto, but jump over a 32-bit thumb insn */
1458 static void mk_skip_over_T32_if_cond_is_false (
1459 IRTemp guardT
/* :: Ity_I32, 0 or 1 */
1463 vassert(guardT
!= IRTemp_INVALID
);
1464 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
1466 unop(Iop_Not1
, unop(Iop_32to1
, mkexpr(guardT
))),
1468 IRConst_U32(toUInt((guest_R15_curr_instr_notENC
+ 4) | 1)),
1474 /* Thumb16 and Thumb32 only
1475 Generate a SIGILL followed by a restart of the current instruction
1476 if the given temp is nonzero. */
1477 static void gen_SIGILL_T_if_nonzero ( IRTemp t
/* :: Ity_I32 */ )
1480 vassert(t
!= IRTemp_INVALID
);
1481 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
1484 binop(Iop_CmpNE32
, mkexpr(t
), mkU32(0)),
1486 IRConst_U32(toUInt(guest_R15_curr_instr_notENC
| 1)),
1493 /* Inspect the old_itstate, and generate a SIGILL if it indicates that
1494 we are currently in an IT block and are not the last in the block.
1495 This also rolls back guest_ITSTATE to its old value before the exit
1496 and restores it to its new value afterwards. This is so that if
1497 the exit is taken, we have an up to date version of ITSTATE
1498 available. Without doing that, we have no hope of making precise
1500 static void gen_SIGILL_T_if_in_but_NLI_ITBlock (
1501 IRTemp old_itstate
/* :: Ity_I32 */,
1502 IRTemp new_itstate
/* :: Ity_I32 */
1506 put_ITSTATE(old_itstate
); // backout
1507 IRTemp guards_for_next3
= newTemp(Ity_I32
);
1508 assign(guards_for_next3
,
1509 binop(Iop_Shr32
, mkexpr(old_itstate
), mkU8(8)));
1510 gen_SIGILL_T_if_nonzero(guards_for_next3
);
1511 put_ITSTATE(new_itstate
); //restore
1515 /* Simpler version of the above, which generates a SIGILL if
1516 we're anywhere within an IT block. */
1517 static void gen_SIGILL_T_if_in_ITBlock (
1518 IRTemp old_itstate
/* :: Ity_I32 */,
1519 IRTemp new_itstate
/* :: Ity_I32 */
1522 put_ITSTATE(old_itstate
); // backout
1523 gen_SIGILL_T_if_nonzero(old_itstate
);
1524 put_ITSTATE(new_itstate
); //restore
1528 /* Generate an APSR value, from the NZCV thunk, and
1529 from QFLAG32 and GEFLAG0 .. GEFLAG3. */
1530 static IRTemp
synthesise_APSR ( void )
1532 IRTemp res1
= newTemp(Ity_I32
);
1534 assign( res1
, mk_armg_calculate_flags_nzcv() );
1535 // OR in the Q value
1536 IRTemp res2
= newTemp(Ity_I32
);
1544 mkexpr(get_QFLAG32()),
1546 mkU8(ARMG_CC_SHIFT_Q
)))
1550 = unop(Iop_1Uto32
, binop(Iop_CmpNE32
, get_GEFLAG32(0), mkU32(0)));
1552 = unop(Iop_1Uto32
, binop(Iop_CmpNE32
, get_GEFLAG32(1), mkU32(0)));
1554 = unop(Iop_1Uto32
, binop(Iop_CmpNE32
, get_GEFLAG32(2), mkU32(0)));
1556 = unop(Iop_1Uto32
, binop(Iop_CmpNE32
, get_GEFLAG32(3), mkU32(0)));
1557 IRTemp res3
= newTemp(Ity_I32
);
1563 binop(Iop_Shl32
, ge0
, mkU8(16)),
1564 binop(Iop_Shl32
, ge1
, mkU8(17))),
1566 binop(Iop_Shl32
, ge2
, mkU8(18)),
1567 binop(Iop_Shl32
, ge3
, mkU8(19))) )));
1572 /* and the inverse transformation: given an APSR value,
1573 set the NZCV thunk, the Q flag, and the GE flags. */
1574 static void desynthesise_APSR ( Bool write_nzcvq
, Bool write_ge
,
1575 IRTemp apsrT
, IRTemp condT
)
1577 vassert(write_nzcvq
|| write_ge
);
1580 IRTemp immT
= newTemp(Ity_I32
);
1581 assign(immT
, binop(Iop_And32
, mkexpr(apsrT
), mkU32(0xF0000000)) );
1582 setFlags_D1(ARMG_CC_OP_COPY
, immT
, condT
);
1584 IRTemp qnewT
= newTemp(Ity_I32
);
1585 assign(qnewT
, binop(Iop_And32
, mkexpr(apsrT
), mkU32(ARMG_CC_MASK_Q
)));
1586 put_QFLAG32(qnewT
, condT
);
1590 put_GEFLAG32(0, 0, binop(Iop_And32
, mkexpr(apsrT
), mkU32(1<<16)),
1592 put_GEFLAG32(1, 0, binop(Iop_And32
, mkexpr(apsrT
), mkU32(1<<17)),
1594 put_GEFLAG32(2, 0, binop(Iop_And32
, mkexpr(apsrT
), mkU32(1<<18)),
1596 put_GEFLAG32(3, 0, binop(Iop_And32
, mkexpr(apsrT
), mkU32(1<<19)),
1602 /*------------------------------------------------------------*/
1603 /*--- Helpers for saturation ---*/
1604 /*------------------------------------------------------------*/
1606 /* FIXME: absolutely the only diff. between (a) armUnsignedSatQ and
1607 (b) armSignedSatQ is that in (a) the floor is set to 0, whereas in
1608 (b) the floor is computed from the value of imm5. these two fnsn
1609 should be commoned up. */
1611 /* UnsignedSatQ(): 'clamp' each value so it lies between 0 <= x <= (2^N)-1
1612 Optionally return flag resQ saying whether saturation occurred.
1613 See definition in manual, section A2.2.1, page 41
1614 (bits(N), boolean) UnsignedSatQ( integer i, integer N )
1616 if ( i > (2^N)-1 ) { result = (2^N)-1; saturated = TRUE; }
1617 elsif ( i < 0 ) { result = 0; saturated = TRUE; }
1618 else { result = i; saturated = FALSE; }
1619 return ( result<N-1:0>, saturated );
1622 static void armUnsignedSatQ( IRTemp
* res
, /* OUT - Ity_I32 */
1623 IRTemp
* resQ
, /* OUT - Ity_I32 */
1624 IRTemp regT
, /* value to clamp - Ity_I32 */
1625 UInt imm5
) /* saturation ceiling */
1627 ULong ceil64
= (1ULL << imm5
) - 1; // (2^imm5)-1
1628 UInt ceil
= (UInt
)ceil64
;
1631 IRTemp nd0
= newTemp(Ity_I32
);
1632 IRTemp nd1
= newTemp(Ity_I32
);
1633 IRTemp nd2
= newTemp(Ity_I1
);
1634 IRTemp nd3
= newTemp(Ity_I32
);
1635 IRTemp nd4
= newTemp(Ity_I32
);
1636 IRTemp nd5
= newTemp(Ity_I1
);
1637 IRTemp nd6
= newTemp(Ity_I32
);
1639 assign( nd0
, mkexpr(regT
) );
1640 assign( nd1
, mkU32(ceil
) );
1641 assign( nd2
, binop( Iop_CmpLT32S
, mkexpr(nd1
), mkexpr(nd0
) ) );
1642 assign( nd3
, IRExpr_ITE(mkexpr(nd2
), mkexpr(nd1
), mkexpr(nd0
)) );
1643 assign( nd4
, mkU32(floor
) );
1644 assign( nd5
, binop( Iop_CmpLT32S
, mkexpr(nd3
), mkexpr(nd4
) ) );
1645 assign( nd6
, IRExpr_ITE(mkexpr(nd5
), mkexpr(nd4
), mkexpr(nd3
)) );
1646 assign( *res
, mkexpr(nd6
) );
1648 /* if saturation occurred, then resQ is set to some nonzero value
1649 if sat did not occur, resQ is guaranteed to be zero. */
1651 assign( *resQ
, binop(Iop_Xor32
, mkexpr(*res
), mkexpr(regT
)) );
1656 /* SignedSatQ(): 'clamp' each value so it lies between -2^N <= x <= (2^N) - 1
1657 Optionally return flag resQ saying whether saturation occurred.
1658 - see definition in manual, section A2.2.1, page 41
1659 (bits(N), boolean ) SignedSatQ( integer i, integer N )
1661 if ( i > 2^(N-1) - 1 ) { result = 2^(N-1) - 1; saturated = TRUE; }
1662 elsif ( i < -(2^(N-1)) ) { result = -(2^(N-1)); saturated = FALSE; }
1663 else { result = i; saturated = FALSE; }
1664 return ( result[N-1:0], saturated );
1667 static void armSignedSatQ( IRTemp regT
, /* value to clamp - Ity_I32 */
1668 UInt imm5
, /* saturation ceiling */
1669 IRTemp
* res
, /* OUT - Ity_I32 */
1670 IRTemp
* resQ
) /* OUT - Ity_I32 */
1672 Long ceil64
= (1LL << (imm5
-1)) - 1; // (2^(imm5-1))-1
1673 Long floor64
= -(1LL << (imm5
-1)); // -(2^(imm5-1))
1674 Int ceil
= (Int
)ceil64
;
1675 Int floor
= (Int
)floor64
;
1677 IRTemp nd0
= newTemp(Ity_I32
);
1678 IRTemp nd1
= newTemp(Ity_I32
);
1679 IRTemp nd2
= newTemp(Ity_I1
);
1680 IRTemp nd3
= newTemp(Ity_I32
);
1681 IRTemp nd4
= newTemp(Ity_I32
);
1682 IRTemp nd5
= newTemp(Ity_I1
);
1683 IRTemp nd6
= newTemp(Ity_I32
);
1685 assign( nd0
, mkexpr(regT
) );
1686 assign( nd1
, mkU32(ceil
) );
1687 assign( nd2
, binop( Iop_CmpLT32S
, mkexpr(nd1
), mkexpr(nd0
) ) );
1688 assign( nd3
, IRExpr_ITE( mkexpr(nd2
), mkexpr(nd1
), mkexpr(nd0
) ) );
1689 assign( nd4
, mkU32(floor
) );
1690 assign( nd5
, binop( Iop_CmpLT32S
, mkexpr(nd3
), mkexpr(nd4
) ) );
1691 assign( nd6
, IRExpr_ITE( mkexpr(nd5
), mkexpr(nd4
), mkexpr(nd3
) ) );
1692 assign( *res
, mkexpr(nd6
) );
1694 /* if saturation occurred, then resQ is set to some nonzero value
1695 if sat did not occur, resQ is guaranteed to be zero. */
1697 assign( *resQ
, binop(Iop_Xor32
, mkexpr(*res
), mkexpr(regT
)) );
1702 /* Compute a value 0 :: I32 or 1 :: I32, indicating whether signed
1703 overflow occurred for 32-bit addition. Needs both args and the
1706 IRExpr
* signed_overflow_after_Add32 ( IRExpr
* resE
,
1707 IRTemp argL
, IRTemp argR
)
1709 IRTemp res
= newTemp(Ity_I32
);
1714 binop( Iop_Xor32
, mkexpr(res
), mkexpr(argL
) ),
1715 binop( Iop_Xor32
, mkexpr(res
), mkexpr(argR
) )),
1719 /* Similarly .. also from HD p27 .. */
1721 IRExpr
* signed_overflow_after_Sub32 ( IRExpr
* resE
,
1722 IRTemp argL
, IRTemp argR
)
1724 IRTemp res
= newTemp(Ity_I32
);
1729 binop( Iop_Xor32
, mkexpr(argL
), mkexpr(argR
) ),
1730 binop( Iop_Xor32
, mkexpr(res
), mkexpr(argL
) )),
1735 /*------------------------------------------------------------*/
1736 /*--- Larger helpers ---*/
1737 /*------------------------------------------------------------*/
1739 /* Compute both the result and new C flag value for a LSL by an imm5
1740 or by a register operand. May generate reads of the old C value
1741 (hence only safe to use before any writes to guest state happen).
1742 Are factored out so can be used by both ARM and Thumb.
1744 Note that in compute_result_and_C_after_{LSL,LSR,ASR}_by{imm5,reg},
1745 "res" (the result) is a.k.a. "shop", shifter operand
1746 "newC" (the new C) is a.k.a. "shco", shifter carry out
1748 The calling convention for res and newC is a bit funny. They could
1749 be passed by value, but instead are passed by ref.
1751 The C (shco) value computed must be zero in bits 31:1, as the IR
1752 optimisations for flag handling (guest_arm_spechelper) rely on
1753 that, and the slow-path handlers (armg_calculate_flags_nzcv) assert
1754 for it. Same applies to all these functions that compute shco
1755 after a shift or rotate, not just this one.
1758 static void compute_result_and_C_after_LSL_by_imm5 (
1762 IRTemp rMt
, UInt shift_amt
, /* operands */
1763 UInt rM
/* only for debug printing */
1766 if (shift_amt
== 0) {
1768 assign( *newC
, mk_armg_calculate_flag_c() );
1770 assign( *res
, mkexpr(rMt
) );
1771 DIS(buf
, "r%u", rM
);
1773 vassert(shift_amt
>= 1 && shift_amt
<= 31);
1777 binop(Iop_Shr32
, mkexpr(rMt
),
1778 mkU8(32 - shift_amt
)),
1782 binop(Iop_Shl32
, mkexpr(rMt
), mkU8(shift_amt
)) );
1783 DIS(buf
, "r%u, LSL #%u", rM
, shift_amt
);
1788 static void compute_result_and_C_after_LSL_by_reg (
1792 IRTemp rMt
, IRTemp rSt
, /* operands */
1793 UInt rM
, UInt rS
/* only for debug printing */
1796 // shift left in range 0 .. 255
1798 // res = amt < 32 ? Rm << amt : 0
1799 // newC = amt == 0 ? oldC :
1800 // amt in 1..32 ? Rm[32-amt] : 0
1801 IRTemp amtT
= newTemp(Ity_I32
);
1802 assign( amtT
, binop(Iop_And32
, mkexpr(rSt
), mkU32(255)) );
1810 /* About the best you can do is pray that iropt is able
1811 to nuke most or all of the following junk. */
1812 IRTemp oldC
= newTemp(Ity_I32
);
1813 assign(oldC
, mk_armg_calculate_flag_c() );
1817 binop(Iop_CmpEQ32
, mkexpr(amtT
), mkU32(0)),
1820 binop(Iop_CmpLE32U
, mkexpr(amtT
), mkU32(32)),
1840 // (Rm << (Rs & 31)) & (((Rs & 255) - 32) >>s 31)
1841 // Lhs of the & limits the shift to 31 bits, so as to
1842 // give known IR semantics. Rhs of the & is all 1s for
1843 // Rs <= 31 and all 0s for Rs >= 32.
1851 binop(Iop_And32
, mkexpr(rSt
), mkU32(31)))),
1857 DIS(buf
, "r%u, LSL r%u", rM
, rS
);
1861 static void compute_result_and_C_after_LSR_by_imm5 (
1865 IRTemp rMt
, UInt shift_amt
, /* operands */
1866 UInt rM
/* only for debug printing */
1869 if (shift_amt
== 0) {
1870 // conceptually a 32-bit shift, however:
1876 binop(Iop_Shr32
, mkexpr(rMt
), mkU8(31)),
1879 assign( *res
, mkU32(0) );
1880 DIS(buf
, "r%u, LSR #0(a.k.a. 32)", rM
);
1882 // shift in range 1..31
1883 // res = Rm >>u shift_amt
1884 // newC = Rm[shift_amt - 1]
1885 vassert(shift_amt
>= 1 && shift_amt
<= 31);
1889 binop(Iop_Shr32
, mkexpr(rMt
),
1890 mkU8(shift_amt
- 1)),
1894 binop(Iop_Shr32
, mkexpr(rMt
), mkU8(shift_amt
)) );
1895 DIS(buf
, "r%u, LSR #%u", rM
, shift_amt
);
1900 static void compute_result_and_C_after_LSR_by_reg (
1904 IRTemp rMt
, IRTemp rSt
, /* operands */
1905 UInt rM
, UInt rS
/* only for debug printing */
1908 // shift right in range 0 .. 255
1910 // res = amt < 32 ? Rm >>u amt : 0
1911 // newC = amt == 0 ? oldC :
1912 // amt in 1..32 ? Rm[amt-1] : 0
1913 IRTemp amtT
= newTemp(Ity_I32
);
1914 assign( amtT
, binop(Iop_And32
, mkexpr(rSt
), mkU32(255)) );
1922 IRTemp oldC
= newTemp(Ity_I32
);
1923 assign(oldC
, mk_armg_calculate_flag_c() );
1927 binop(Iop_CmpEQ32
, mkexpr(amtT
), mkU32(0)),
1930 binop(Iop_CmpLE32U
, mkexpr(amtT
), mkU32(32)),
1950 // (Rm >>u (Rs & 31)) & (((Rs & 255) - 32) >>s 31)
1951 // Lhs of the & limits the shift to 31 bits, so as to
1952 // give known IR semantics. Rhs of the & is all 1s for
1953 // Rs <= 31 and all 0s for Rs >= 32.
1961 binop(Iop_And32
, mkexpr(rSt
), mkU32(31)))),
1967 DIS(buf
, "r%u, LSR r%u", rM
, rS
);
1971 static void compute_result_and_C_after_ASR_by_imm5 (
1975 IRTemp rMt
, UInt shift_amt
, /* operands */
1976 UInt rM
/* only for debug printing */
1979 if (shift_amt
== 0) {
1980 // conceptually a 32-bit shift, however:
1986 binop(Iop_Shr32
, mkexpr(rMt
), mkU8(31)),
1989 assign( *res
, binop(Iop_Sar32
, mkexpr(rMt
), mkU8(31)) );
1990 DIS(buf
, "r%u, ASR #0(a.k.a. 32)", rM
);
1992 // shift in range 1..31
1993 // res = Rm >>s shift_amt
1994 // newC = Rm[shift_amt - 1]
1995 vassert(shift_amt
>= 1 && shift_amt
<= 31);
1999 binop(Iop_Shr32
, mkexpr(rMt
),
2000 mkU8(shift_amt
- 1)),
2004 binop(Iop_Sar32
, mkexpr(rMt
), mkU8(shift_amt
)) );
2005 DIS(buf
, "r%u, ASR #%u", rM
, shift_amt
);
2010 static void compute_result_and_C_after_ASR_by_reg (
2014 IRTemp rMt
, IRTemp rSt
, /* operands */
2015 UInt rM
, UInt rS
/* only for debug printing */
2018 // arithmetic shift right in range 0 .. 255
2020 // res = amt < 32 ? Rm >>s amt : Rm >>s 31
2021 // newC = amt == 0 ? oldC :
2022 // amt in 1..32 ? Rm[amt-1] : Rm[31]
2023 IRTemp amtT
= newTemp(Ity_I32
);
2024 assign( amtT
, binop(Iop_And32
, mkexpr(rSt
), mkU32(255)) );
2032 IRTemp oldC
= newTemp(Ity_I32
);
2033 assign(oldC
, mk_armg_calculate_flag_c() );
2037 binop(Iop_CmpEQ32
, mkexpr(amtT
), mkU32(0)),
2040 binop(Iop_CmpLE32U
, mkexpr(amtT
), mkU32(32)),
2066 // (Rm >>s (amt <u 32 ? amt : 31))
2075 binop(Iop_CmpLT32U
, mkexpr(amtT
), mkU32(32)),
2078 DIS(buf
, "r%u, ASR r%u", rM
, rS
);
2082 static void compute_result_and_C_after_ROR_by_reg (
2086 IRTemp rMt
, IRTemp rSt
, /* operands */
2087 UInt rM
, UInt rS
/* only for debug printing */
2090 // rotate right in range 0 .. 255
2092 // shop = Rm `ror` (amt & 31)
2093 // shco = amt == 0 ? oldC : Rm[(amt-1) & 31]
2094 IRTemp amtT
= newTemp(Ity_I32
);
2095 assign( amtT
, binop(Iop_And32
, mkexpr(rSt
), mkU32(255)) );
2096 IRTemp amt5T
= newTemp(Ity_I32
);
2097 assign( amt5T
, binop(Iop_And32
, mkexpr(rSt
), mkU32(31)) );
2098 IRTemp oldC
= newTemp(Ity_I32
);
2099 assign(oldC
, mk_armg_calculate_flag_c() );
2104 binop(Iop_CmpNE32
, mkexpr(amtT
), mkU32(0)),
2127 binop(Iop_CmpNE32
, mkexpr(amt5T
), mkU32(0)),
2131 unop(Iop_32to8
, mkexpr(amt5T
))
2136 binop(Iop_Sub32
, mkU32(32), mkexpr(amt5T
))
2143 DIS(buf
, "r%u, ROR r#%u", rM
, rS
);
2147 /* Generate an expression corresponding to the immediate-shift case of
2148 a shifter operand. This is used both for ARM and Thumb2.
2150 Bind it to a temporary, and return that via *res. If newC is
2151 non-NULL, also compute a value for the shifter's carry out (in the
2152 LSB of a word), bind it to a temporary, and return that via *shco.
2154 Generates GETs from the guest state and is therefore not safe to
2155 use once we start doing PUTs to it, for any given instruction.
2157 'how' is encoded thusly:
2158 00b LSL, 01b LSR, 10b ASR, 11b ROR
2159 Most but not all ARM and Thumb integer insns use this encoding.
2160 Be careful to ensure the right value is passed here.
2162 static void compute_result_and_C_after_shift_by_imm5 (
2165 /*OUT*/IRTemp
* newC
,
2166 IRTemp rMt
, /* reg to shift */
2167 UInt how
, /* what kind of shift */
2168 UInt shift_amt
, /* shift amount (0..31) */
2169 UInt rM
/* only for debug printing */
2172 vassert(shift_amt
< 32);
2178 compute_result_and_C_after_LSL_by_imm5(
2179 buf
, res
, newC
, rMt
, shift_amt
, rM
2184 compute_result_and_C_after_LSR_by_imm5(
2185 buf
, res
, newC
, rMt
, shift_amt
, rM
2190 compute_result_and_C_after_ASR_by_imm5(
2191 buf
, res
, newC
, rMt
, shift_amt
, rM
2196 if (shift_amt
== 0) {
2197 IRTemp oldcT
= newTemp(Ity_I32
);
2198 // rotate right 1 bit through carry (?)
2199 // RRX -- described at ARM ARM A5-17
2200 // res = (oldC << 31) | (Rm >>u 1)
2204 binop(Iop_And32
, mkexpr(rMt
), mkU32(1)));
2206 assign( oldcT
, mk_armg_calculate_flag_c() );
2209 binop(Iop_Shl32
, mkexpr(oldcT
), mkU8(31)),
2210 binop(Iop_Shr32
, mkexpr(rMt
), mkU8(1))) );
2211 DIS(buf
, "r%u, RRX", rM
);
2213 // rotate right in range 1..31
2214 // res = Rm `ror` shift_amt
2215 // newC = Rm[shift_amt - 1]
2216 vassert(shift_amt
>= 1 && shift_amt
<= 31);
2220 binop(Iop_Shr32
, mkexpr(rMt
),
2221 mkU8(shift_amt
- 1)),
2226 binop(Iop_Shr32
, mkexpr(rMt
), mkU8(shift_amt
)),
2227 binop(Iop_Shl32
, mkexpr(rMt
),
2228 mkU8(32-shift_amt
))));
2229 DIS(buf
, "r%u, ROR #%u", rM
, shift_amt
);
2240 /* Generate an expression corresponding to the register-shift case of
2241 a shifter operand. This is used both for ARM and Thumb2.
2243 Bind it to a temporary, and return that via *res. If newC is
2244 non-NULL, also compute a value for the shifter's carry out (in the
2245 LSB of a word), bind it to a temporary, and return that via *shco.
2247 Generates GETs from the guest state and is therefore not safe to
2248 use once we start doing PUTs to it, for any given instruction.
2250 'how' is encoded thusly:
2251 00b LSL, 01b LSR, 10b ASR, 11b ROR
2252 Most but not all ARM and Thumb integer insns use this encoding.
2253 Be careful to ensure the right value is passed here.
2255 static void compute_result_and_C_after_shift_by_reg (
2258 /*OUT*/IRTemp
* newC
,
2259 IRTemp rMt
, /* reg to shift */
2260 UInt how
, /* what kind of shift */
2261 IRTemp rSt
, /* shift amount */
2262 UInt rM
, /* only for debug printing */
2263 UInt rS
/* only for debug printing */
2269 compute_result_and_C_after_LSL_by_reg(
2270 buf
, res
, newC
, rMt
, rSt
, rM
, rS
2275 compute_result_and_C_after_LSR_by_reg(
2276 buf
, res
, newC
, rMt
, rSt
, rM
, rS
2281 compute_result_and_C_after_ASR_by_reg(
2282 buf
, res
, newC
, rMt
, rSt
, rM
, rS
2287 compute_result_and_C_after_ROR_by_reg(
2288 buf
, res
, newC
, rMt
, rSt
, rM
, rS
2299 /* Generate an expression corresponding to a shifter_operand, bind it
2300 to a temporary, and return that via *shop. If shco is non-NULL,
2301 also compute a value for the shifter's carry out (in the LSB of a
2302 word), bind it to a temporary, and return that via *shco.
2304 If for some reason we can't come up with a shifter operand (missing
2305 case? not really a shifter operand?) return False.
2307 Generates GETs from the guest state and is therefore not safe to
2308 use once we start doing PUTs to it, for any given instruction.
2310 For ARM insns only; not for Thumb.
2312 static Bool
mk_shifter_operand ( UInt insn_25
, UInt insn_11_0
,
2313 /*OUT*/IRTemp
* shop
,
2314 /*OUT*/IRTemp
* shco
,
2317 UInt insn_4
= (insn_11_0
>> 4) & 1;
2318 UInt insn_7
= (insn_11_0
>> 7) & 1;
2319 vassert(insn_25
<= 0x1);
2320 vassert(insn_11_0
<= 0xFFF);
2322 vassert(shop
&& *shop
== IRTemp_INVALID
);
2323 *shop
= newTemp(Ity_I32
);
2326 vassert(*shco
== IRTemp_INVALID
);
2327 *shco
= newTemp(Ity_I32
);
2330 /* 32-bit immediate */
2333 /* immediate: (7:0) rotated right by 2 * (11:8) */
2334 UInt imm
= (insn_11_0
>> 0) & 0xFF;
2335 UInt rot
= 2 * ((insn_11_0
>> 8) & 0xF);
2337 imm
= ROR32(imm
, rot
);
2340 assign( *shco
, mk_armg_calculate_flag_c() );
2342 assign( *shco
, mkU32( (imm
>> 31) & 1 ) );
2345 DIS(buf
, "#0x%x", imm
);
2346 assign( *shop
, mkU32(imm
) );
2350 /* Shift/rotate by immediate */
2352 if (insn_25
== 0 && insn_4
== 0) {
2353 /* Rm (3:0) shifted (6:5) by immediate (11:7) */
2354 UInt shift_amt
= (insn_11_0
>> 7) & 0x1F;
2355 UInt rM
= (insn_11_0
>> 0) & 0xF;
2356 UInt how
= (insn_11_0
>> 5) & 3;
2357 /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
2358 IRTemp rMt
= newTemp(Ity_I32
);
2359 assign(rMt
, getIRegA(rM
));
2361 vassert(shift_amt
<= 31);
2363 compute_result_and_C_after_shift_by_imm5(
2364 buf
, shop
, shco
, rMt
, how
, shift_amt
, rM
2369 /* Shift/rotate by register */
2370 if (insn_25
== 0 && insn_4
== 1) {
2371 /* Rm (3:0) shifted (6:5) by Rs (11:8) */
2372 UInt rM
= (insn_11_0
>> 0) & 0xF;
2373 UInt rS
= (insn_11_0
>> 8) & 0xF;
2374 UInt how
= (insn_11_0
>> 5) & 3;
2375 /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
2376 IRTemp rMt
= newTemp(Ity_I32
);
2377 IRTemp rSt
= newTemp(Ity_I32
);
2380 return False
; /* not really a shifter operand */
2382 assign(rMt
, getIRegA(rM
));
2383 assign(rSt
, getIRegA(rS
));
2385 compute_result_and_C_after_shift_by_reg(
2386 buf
, shop
, shco
, rMt
, how
, rSt
, rM
, rS
2391 vex_printf("mk_shifter_operand(0x%x,0x%x)\n", insn_25
, insn_11_0
);
2398 IRExpr
* mk_EA_reg_plusminus_imm12 ( UInt rN
, UInt bU
, UInt imm12
,
2403 vassert(imm12
< 0x1000);
2404 HChar opChar
= bU
== 1 ? '+' : '-';
2405 DIS(buf
, "[r%u, #%c%u]", rN
, opChar
, imm12
);
2407 binop( (bU
== 1 ? Iop_Add32
: Iop_Sub32
),
2414 NB: This is "DecodeImmShift" in newer versions of the the ARM ARM.
2417 IRExpr
* mk_EA_reg_plusminus_shifted_reg ( UInt rN
, UInt bU
, UInt rM
,
2418 UInt sh2
, UInt imm5
,
2426 HChar opChar
= bU
== 1 ? '+' : '-';
2427 IRExpr
* index
= NULL
;
2430 /* imm5 can be in the range 0 .. 31 inclusive. */
2431 index
= binop(Iop_Shl32
, getIRegA(rM
), mkU8(imm5
));
2432 DIS(buf
, "[r%u, %c r%u LSL #%u]", rN
, opChar
, rM
, imm5
);
2439 index
= binop(Iop_Shr32
, getIRegA(rM
), mkU8(imm5
));
2441 DIS(buf
, "[r%u, %cr%u, LSR #%u]",
2442 rN
, opChar
, rM
, imm5
== 0 ? 32 : imm5
);
2445 /* Doesn't this just mean that the behaviour with imm5 == 0
2446 is the same as if it had been 31 ? */
2448 index
= binop(Iop_Sar32
, getIRegA(rM
), mkU8(31));
2451 index
= binop(Iop_Sar32
, getIRegA(rM
), mkU8(imm5
));
2453 DIS(buf
, "[r%u, %cr%u, ASR #%u]",
2454 rN
, opChar
, rM
, imm5
== 0 ? 32 : imm5
);
2456 case 3: /* ROR or RRX */
2458 IRTemp rmT
= newTemp(Ity_I32
);
2459 IRTemp cflagT
= newTemp(Ity_I32
);
2460 assign(rmT
, getIRegA(rM
));
2461 assign(cflagT
, mk_armg_calculate_flag_c());
2462 index
= binop(Iop_Or32
,
2463 binop(Iop_Shl32
, mkexpr(cflagT
), mkU8(31)),
2464 binop(Iop_Shr32
, mkexpr(rmT
), mkU8(1)));
2465 DIS(buf
, "[r%u, %cr%u, RRX]", rN
, opChar
, rM
);
2467 IRTemp rmT
= newTemp(Ity_I32
);
2468 assign(rmT
, getIRegA(rM
));
2469 vassert(imm5
>= 1 && imm5
<= 31);
2470 index
= binop(Iop_Or32
,
2471 binop(Iop_Shl32
, mkexpr(rmT
), mkU8(32-imm5
)),
2472 binop(Iop_Shr32
, mkexpr(rmT
), mkU8(imm5
)));
2473 DIS(buf
, "[r%u, %cr%u, ROR #%u]", rN
, opChar
, rM
, imm5
);
2480 return binop(bU
== 1 ? Iop_Add32
: Iop_Sub32
,
2481 getIRegA(rN
), index
);
2487 IRExpr
* mk_EA_reg_plusminus_imm8 ( UInt rN
, UInt bU
, UInt imm8
,
2492 vassert(imm8
< 0x100);
2493 HChar opChar
= bU
== 1 ? '+' : '-';
2494 DIS(buf
, "[r%u, #%c%u]", rN
, opChar
, imm8
);
2496 binop( (bU
== 1 ? Iop_Add32
: Iop_Sub32
),
2504 IRExpr
* mk_EA_reg_plusminus_reg ( UInt rN
, UInt bU
, UInt rM
,
2510 HChar opChar
= bU
== 1 ? '+' : '-';
2511 IRExpr
* index
= getIRegA(rM
);
2512 DIS(buf
, "[r%u, %c r%u]", rN
, opChar
, rM
);
2513 return binop(bU
== 1 ? Iop_Add32
: Iop_Sub32
,
2514 getIRegA(rN
), index
);
2518 /* irRes :: Ity_I32 holds a floating point comparison result encoded
2519 as an IRCmpF64Result. Generate code to convert it to an
2520 ARM-encoded (N,Z,C,V) group in the lowest 4 bits of an I32 value.
2521 Assign a new temp to hold that value, and return the temp. */
2523 IRTemp
mk_convert_IRCmpF64Result_to_NZCV ( IRTemp irRes
)
2525 IRTemp ix
= newTemp(Ity_I32
);
2526 IRTemp termL
= newTemp(Ity_I32
);
2527 IRTemp termR
= newTemp(Ity_I32
);
2528 IRTemp nzcv
= newTemp(Ity_I32
);
2530 /* This is where the fun starts. We have to convert 'irRes' from
2531 an IR-convention return result (IRCmpF64Result) to an
2532 ARM-encoded (N,Z,C,V) group. The final result is in the bottom
2533 4 bits of 'nzcv'. */
2534 /* Map compare result from IR to ARM(nzcv) */
2536 FP cmp result | IR | ARM(nzcv)
2537 --------------------------------
2543 /* Now since you're probably wondering WTF ..
2545 ix fishes the useful bits out of the IR value, bits 6 and 0, and
2546 places them side by side, giving a number which is 0, 1, 2 or 3.
2548 termL is a sequence cooked up by GNU superopt. It converts ix
2549 into an almost correct value NZCV value (incredibly), except
2550 for the case of UN, where it produces 0100 instead of the
2553 termR is therefore a correction term, also computed from ix. It
2554 is 1 in the UN case and 0 for LT, GT and UN. Hence, to get
2555 the final correct value, we subtract termR from termL.
2557 Don't take my word for it. There's a test program at the bottom
2558 of this file, to try this out with.
2564 binop(Iop_Shr32
, mkexpr(irRes
), mkU8(5)),
2566 binop(Iop_And32
, mkexpr(irRes
), mkU32(1))));
2574 binop(Iop_Xor32
, mkexpr(ix
), mkU32(1)),
2585 binop(Iop_Shr32
, mkexpr(ix
), mkU8(1))),
2588 assign(nzcv
, binop(Iop_Sub32
, mkexpr(termL
), mkexpr(termR
)));
2593 /* Thumb32 only. This is "ThumbExpandImm" in the ARM ARM. If
2594 updatesC is non-NULL, a boolean is written to it indicating whether
2595 or not the C flag is updated, as per ARM ARM "ThumbExpandImm_C".
2597 static UInt
thumbExpandImm ( Bool
* updatesC
,
2598 UInt imm1
, UInt imm3
, UInt imm8
)
2600 vassert(imm1
< (1<<1));
2601 vassert(imm3
< (1<<3));
2602 vassert(imm8
< (1<<8));
2603 UInt i_imm3_a
= (imm1
<< 4) | (imm3
<< 1) | ((imm8
>> 7) & 1);
2604 UInt abcdefgh
= imm8
;
2605 UInt lbcdefgh
= imm8
| 0x80;
2607 *updatesC
= i_imm3_a
>= 8;
2613 return (abcdefgh
<< 16) | abcdefgh
;
2615 return (abcdefgh
<< 24) | (abcdefgh
<< 8);
2617 return (abcdefgh
<< 24) | (abcdefgh
<< 16)
2618 | (abcdefgh
<< 8) | abcdefgh
;
2620 return lbcdefgh
<< (32 - i_imm3_a
);
2624 /*NOTREACHED*/vassert(0);
2628 /* Version of thumbExpandImm where we simply feed it the
2629 instruction halfwords (the lowest addressed one is I0). */
2630 static UInt
thumbExpandImm_from_I0_I1 ( Bool
* updatesC
,
2631 UShort i0s
, UShort i1s
)
2633 UInt i0
= (UInt
)i0s
;
2634 UInt i1
= (UInt
)i1s
;
2635 UInt imm1
= SLICE_UInt(i0
,10,10);
2636 UInt imm3
= SLICE_UInt(i1
,14,12);
2637 UInt imm8
= SLICE_UInt(i1
,7,0);
2638 return thumbExpandImm(updatesC
, imm1
, imm3
, imm8
);
2642 /* Thumb16 only. Given the firstcond and mask fields from an IT
2643 instruction, compute the 32-bit ITSTATE value implied, as described
2644 in libvex_guest_arm.h. This is not the ARM ARM representation.
2645 Also produce the t/e chars for the 2nd, 3rd, 4th insns, for
2646 disassembly printing. Returns False if firstcond or mask
2647 denote something invalid.
2649 The number and conditions for the instructions to be
2650 conditionalised depend on firstcond and mask:
2652 mask cond 1 cond 2 cond 3 cond 4
2655 x100 fc[3:0] fc[3:1]:x
2656 xy10 fc[3:0] fc[3:1]:x fc[3:1]:y
2657 xyz1 fc[3:0] fc[3:1]:x fc[3:1]:y fc[3:1]:z
2659 The condition fields are assembled in *itstate backwards (cond 4 at
2660 the top, cond 1 at the bottom). Conditions are << 4'd and then
2661 ^0xE'd, and those fields that correspond to instructions in the IT
2662 block are tagged with a 1 bit.
2664 static Bool
compute_ITSTATE ( /*OUT*/UInt
* itstate
,
2668 UInt firstcond
, UInt mask
)
2670 vassert(firstcond
<= 0xF);
2671 vassert(mask
<= 0xF);
2673 *ch1
= *ch2
= *ch3
= '.';
2675 return False
; /* the logic below actually ensures this anyway,
2676 but clearer to make it explicit. */
2677 if (firstcond
== 0xF)
2678 return False
; /* NV is not allowed */
2679 if (firstcond
== 0xE && popcount32(mask
) != 1)
2680 return False
; /* if firstcond is AL then all the rest must be too */
2682 UInt m3
= (mask
>> 3) & 1;
2683 UInt m2
= (mask
>> 2) & 1;
2684 UInt m1
= (mask
>> 1) & 1;
2685 UInt m0
= (mask
>> 0) & 1;
2687 UInt fc
= (firstcond
<< 4) | 1/*in-IT-block*/;
2688 UInt ni
= (0xE/*AL*/ << 4) | 0/*not-in-IT-block*/;
2690 if (m3
== 1 && (m2
|m1
|m0
) == 0) {
2691 *itstate
= (ni
<< 24) | (ni
<< 16) | (ni
<< 8) | fc
;
2692 *itstate
^= 0xE0E0E0E0;
2696 if (m2
== 1 && (m1
|m0
) == 0) {
2697 *itstate
= (ni
<< 24) | (ni
<< 16) | (setbit32(fc
, 4, m3
) << 8) | fc
;
2698 *itstate
^= 0xE0E0E0E0;
2699 *ch1
= m3
== (firstcond
& 1) ? 't' : 'e';
2703 if (m1
== 1 && m0
== 0) {
2704 *itstate
= (ni
<< 24)
2705 | (setbit32(fc
, 4, m2
) << 16)
2706 | (setbit32(fc
, 4, m3
) << 8) | fc
;
2707 *itstate
^= 0xE0E0E0E0;
2708 *ch1
= m3
== (firstcond
& 1) ? 't' : 'e';
2709 *ch2
= m2
== (firstcond
& 1) ? 't' : 'e';
2714 *itstate
= (setbit32(fc
, 4, m1
) << 24)
2715 | (setbit32(fc
, 4, m2
) << 16)
2716 | (setbit32(fc
, 4, m3
) << 8) | fc
;
2717 *itstate
^= 0xE0E0E0E0;
2718 *ch1
= m3
== (firstcond
& 1) ? 't' : 'e';
2719 *ch2
= m2
== (firstcond
& 1) ? 't' : 'e';
2720 *ch3
= m1
== (firstcond
& 1) ? 't' : 'e';
2728 /* Generate IR to do 32-bit bit reversal, a la Hacker's Delight
2729 Chapter 7 Section 1. */
2730 static IRTemp
gen_BITREV ( IRTemp x0
)
2732 IRTemp x1
= newTemp(Ity_I32
);
2733 IRTemp x2
= newTemp(Ity_I32
);
2734 IRTemp x3
= newTemp(Ity_I32
);
2735 IRTemp x4
= newTemp(Ity_I32
);
2736 IRTemp x5
= newTemp(Ity_I32
);
2737 UInt c1
= 0x55555555;
2738 UInt c2
= 0x33333333;
2739 UInt c3
= 0x0F0F0F0F;
2740 UInt c4
= 0x00FF00FF;
2741 UInt c5
= 0x0000FFFF;
2745 binop(Iop_And32
, mkexpr(x0
), mkU32(c1
)),
2748 binop(Iop_And32
, mkexpr(x0
), mkU32(~c1
)),
2754 binop(Iop_And32
, mkexpr(x1
), mkU32(c2
)),
2757 binop(Iop_And32
, mkexpr(x1
), mkU32(~c2
)),
2763 binop(Iop_And32
, mkexpr(x2
), mkU32(c3
)),
2766 binop(Iop_And32
, mkexpr(x2
), mkU32(~c3
)),
2772 binop(Iop_And32
, mkexpr(x3
), mkU32(c4
)),
2775 binop(Iop_And32
, mkexpr(x3
), mkU32(~c4
)),
2781 binop(Iop_And32
, mkexpr(x4
), mkU32(c5
)),
2784 binop(Iop_And32
, mkexpr(x4
), mkU32(~c5
)),
2791 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
2792 0:1:2:3 (aka byte-swap). */
2793 static IRTemp
gen_REV ( IRTemp arg
)
2795 IRTemp res
= newTemp(Ity_I32
);
2798 binop(Iop_Shl32
, mkexpr(arg
), mkU8(24)),
2800 binop(Iop_And32
, binop(Iop_Shl32
, mkexpr(arg
), mkU8(8)),
2803 binop(Iop_And32
, binop(Iop_Shr32
, mkexpr(arg
), mkU8(8)),
2805 binop(Iop_And32
, binop(Iop_Shr32
, mkexpr(arg
), mkU8(24)),
2812 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
2813 2:3:0:1 (swap within lo and hi halves). */
2814 static IRTemp
gen_REV16 ( IRTemp arg
)
2816 IRTemp res
= newTemp(Ity_I32
);
2820 binop(Iop_Shl32
, mkexpr(arg
), mkU8(8)),
2823 binop(Iop_Shr32
, mkexpr(arg
), mkU8(8)),
2824 mkU32(0x00FF00FF))));
2829 /*------------------------------------------------------------*/
2830 /*--- Advanced SIMD (NEON) instructions ---*/
2831 /*------------------------------------------------------------*/
2833 /*------------------------------------------------------------*/
2834 /*--- NEON data processing ---*/
2835 /*------------------------------------------------------------*/
2837 /* For all NEON DP ops, we use the normal scheme to handle conditional
2838 writes to registers -- pass in condT and hand that on to the
2839 put*Reg functions. In ARM mode condT is always IRTemp_INVALID
2840 since NEON is unconditional for ARM. In Thumb mode condT is
2841 derived from the ITSTATE shift register in the normal way. */
2844 UInt
get_neon_d_regno(UInt theInstr
)
2846 UInt x
= ((theInstr
>> 18) & 0x10) | ((theInstr
>> 12) & 0xF);
2847 if (theInstr
& 0x40) {
2858 UInt
get_neon_n_regno(UInt theInstr
)
2860 UInt x
= ((theInstr
>> 3) & 0x10) | ((theInstr
>> 16) & 0xF);
2861 if (theInstr
& 0x40) {
2872 UInt
get_neon_m_regno(UInt theInstr
)
2874 UInt x
= ((theInstr
>> 1) & 0x10) | (theInstr
& 0xF);
2875 if (theInstr
& 0x40) {
2886 Bool
dis_neon_vext ( UInt theInstr
, IRTemp condT
)
2888 UInt dreg
= get_neon_d_regno(theInstr
);
2889 UInt mreg
= get_neon_m_regno(theInstr
);
2890 UInt nreg
= get_neon_n_regno(theInstr
);
2891 UInt imm4
= (theInstr
>> 8) & 0xf;
2892 UInt Q
= (theInstr
>> 6) & 1;
2893 HChar reg_t
= Q
? 'q' : 'd';
2896 putQReg(dreg
, triop(Iop_SliceV128
, /*hiV128*/getQReg(mreg
),
2897 /*loV128*/getQReg(nreg
), mkU8(imm4
)), condT
);
2899 putDRegI64(dreg
, triop(Iop_Slice64
, /*hiI64*/getDRegI64(mreg
),
2900 /*loI64*/getDRegI64(nreg
), mkU8(imm4
)), condT
);
2902 DIP("vext.8 %c%u, %c%u, %c%u, #%u\n", reg_t
, dreg
, reg_t
, nreg
,
2907 /* Generate specific vector FP binary ops, possibly with a fake
2908 rounding mode as required by the primop. */
2910 IRExpr
* binop_w_fake_RM ( IROp op
, IRExpr
* argL
, IRExpr
* argR
)
2916 return triop(op
, get_FAKE_roundingmode(), argL
, argR
);
2917 case Iop_Add32x4
: case Iop_Add16x8
:
2918 case Iop_Sub32x4
: case Iop_Sub16x8
:
2919 case Iop_Mul32x4
: case Iop_Mul16x8
:
2920 case Iop_Mul32x2
: case Iop_Mul16x4
:
2924 case Iop_PwAdd32Fx2
:
2925 return binop(op
, argL
, argR
);
2934 Bool
dis_neon_vtb ( UInt theInstr
, IRTemp condT
)
2936 UInt op
= (theInstr
>> 6) & 1;
2937 UInt dreg
= get_neon_d_regno(theInstr
& ~(1 << 6));
2938 UInt nreg
= get_neon_n_regno(theInstr
& ~(1 << 6));
2939 UInt mreg
= get_neon_m_regno(theInstr
& ~(1 << 6));
2940 UInt len
= (theInstr
>> 8) & 3;
2945 IRTemp old_mask
, new_mask
, cur_mask
;
2946 IRTemp old_res
, new_res
;
2947 IRTemp old_arg
, new_arg
;
2949 if (dreg
>= 0x100 || mreg
>= 0x100 || nreg
>= 0x100)
2951 if (nreg
+ len
> 31)
2954 cmp
= Iop_CmpGT8Ux8
;
2956 old_mask
= newTemp(Ity_I64
);
2957 old_res
= newTemp(Ity_I64
);
2958 old_arg
= newTemp(Ity_I64
);
2959 assign(old_mask
, mkU64(0));
2960 assign(old_res
, mkU64(0));
2961 assign(old_arg
, getDRegI64(mreg
));
2963 imm
= (imm
<< 8) | imm
;
2964 imm
= (imm
<< 16) | imm
;
2965 imm
= (imm
<< 32) | imm
;
2967 for (i
= 0; i
<= len
; i
++) {
2968 arg_l
= newTemp(Ity_I64
);
2969 new_mask
= newTemp(Ity_I64
);
2970 cur_mask
= newTemp(Ity_I64
);
2971 new_res
= newTemp(Ity_I64
);
2972 new_arg
= newTemp(Ity_I64
);
2973 assign(arg_l
, getDRegI64(nreg
+i
));
2974 assign(new_arg
, binop(Iop_Sub8x8
, mkexpr(old_arg
), mkU64(imm
)));
2975 assign(cur_mask
, binop(cmp
, mkU64(imm
), mkexpr(old_arg
)));
2976 assign(new_mask
, binop(Iop_Or64
, mkexpr(old_mask
), mkexpr(cur_mask
)));
2977 assign(new_res
, binop(Iop_Or64
,
2985 mkexpr(cur_mask
))));
2988 old_mask
= new_mask
;
2992 new_res
= newTemp(Ity_I64
);
2993 assign(new_res
, binop(Iop_Or64
,
2996 unop(Iop_Not64
, mkexpr(old_mask
))),
3001 putDRegI64(dreg
, mkexpr(old_res
), condT
);
3002 DIP("vtb%c.8 d%u, {", op
? 'x' : 'l', dreg
);
3004 DIP("d%u-d%u", nreg
, nreg
+ len
);
3008 DIP("}, d%u\n", mreg
);
3014 Bool
dis_neon_vdup ( UInt theInstr
, IRTemp condT
)
3016 UInt Q
= (theInstr
>> 6) & 1;
3017 UInt dreg
= ((theInstr
>> 18) & 0x10) | ((theInstr
>> 12) & 0xF);
3018 UInt mreg
= ((theInstr
>> 1) & 0x10) | (theInstr
& 0xF);
3019 UInt imm4
= (theInstr
>> 16) & 0xF;
3026 if ((imm4
== 0) || (imm4
== 8))
3028 if ((Q
== 1) && ((dreg
& 1) == 1))
3032 arg_m
= newTemp(Ity_I64
);
3033 assign(arg_m
, getDRegI64(mreg
));
3035 res
= newTemp(Ity_V128
);
3037 res
= newTemp(Ity_I64
);
3038 if ((imm4
& 1) == 1) {
3039 op
= Q
? Iop_Dup8x16
: Iop_Dup8x8
;
3040 op2
= Iop_GetElem8x8
;
3043 } else if ((imm4
& 3) == 2) {
3044 op
= Q
? Iop_Dup16x8
: Iop_Dup16x4
;
3045 op2
= Iop_GetElem16x4
;
3048 } else if ((imm4
& 7) == 4) {
3049 op
= Q
? Iop_Dup32x4
: Iop_Dup32x2
;
3050 op2
= Iop_GetElem32x2
;
3054 return False
; // can this ever happen?
3056 assign(res
, unop(op
, binop(op2
, mkexpr(arg_m
), mkU8(index
))));
3058 putQReg(dreg
, mkexpr(res
), condT
);
3060 putDRegI64(dreg
, mkexpr(res
), condT
);
3062 DIP("vdup.%u %c%u, d%u[%u]\n", size
, Q
? 'q' : 'd', dreg
, mreg
, index
);
3066 /* A7.4.1 Three registers of the same length */
3068 Bool
dis_neon_data_3same ( UInt theInstr
, IRTemp condT
)
3070 /* In paths where this returns False, indicating a non-decodable
3071 instruction, there may still be some IR assignments to temporaries
3072 generated. This is inconvenient but harmless, and the post-front-end
3073 IR optimisation pass will just remove them anyway. So there's no
3074 effort made here to tidy it up.
3076 UInt Q
= (theInstr
>> 6) & 1;
3077 UInt dreg
= get_neon_d_regno(theInstr
);
3078 UInt nreg
= get_neon_n_regno(theInstr
);
3079 UInt mreg
= get_neon_m_regno(theInstr
);
3080 UInt A
= (theInstr
>> 8) & 0xF;
3081 UInt B
= (theInstr
>> 4) & 1;
3082 UInt C
= (theInstr
>> 20) & 0x3;
3083 UInt U
= (theInstr
>> 24) & 1;
3091 arg_n
= newTemp(Ity_V128
);
3092 arg_m
= newTemp(Ity_V128
);
3093 res
= newTemp(Ity_V128
);
3094 assign(arg_n
, getQReg(nreg
));
3095 assign(arg_m
, getQReg(mreg
));
3097 arg_n
= newTemp(Ity_I64
);
3098 arg_m
= newTemp(Ity_I64
);
3099 res
= newTemp(Ity_I64
);
3100 assign(arg_n
, getDRegI64(nreg
));
3101 assign(arg_m
, getDRegI64(mreg
));
3113 HChar regType
= Q
? 'q' : 'd';
3118 case 0: imm
= 0x101010101010101LL
; break;
3119 case 1: imm
= 0x1000100010001LL
; break;
3120 case 2: imm
= 0x100000001LL
; break;
3121 default: vassert(0);
3124 imm_val
= binop(Iop_64HLtoV128
, mkU64(imm
), mkU64(imm
));
3125 andOp
= Iop_AndV128
;
3127 imm_val
= mkU64(imm
);
3133 addOp
= Q
? Iop_Add8x16
: Iop_Add8x8
;
3134 shOp
= Q
? Iop_ShrN8x16
: Iop_ShrN8x8
;
3137 addOp
= Q
? Iop_Add16x8
: Iop_Add16x4
;
3138 shOp
= Q
? Iop_ShrN16x8
: Iop_ShrN16x4
;
3141 addOp
= Q
? Iop_Add32x4
: Iop_Add32x2
;
3142 shOp
= Q
? Iop_ShrN32x4
: Iop_ShrN32x2
;
3150 addOp
= Q
? Iop_Add8x16
: Iop_Add8x8
;
3151 shOp
= Q
? Iop_SarN8x16
: Iop_SarN8x8
;
3154 addOp
= Q
? Iop_Add16x8
: Iop_Add16x4
;
3155 shOp
= Q
? Iop_SarN16x8
: Iop_SarN16x4
;
3158 addOp
= Q
? Iop_Add32x4
: Iop_Add32x2
;
3159 shOp
= Q
? Iop_SarN32x4
: Iop_SarN32x2
;
3168 binop(shOp
, mkexpr(arg_m
), mkU8(1)),
3169 binop(shOp
, mkexpr(arg_n
), mkU8(1))),
3172 binop(andOp
, mkexpr(arg_m
), imm_val
),
3173 binop(andOp
, mkexpr(arg_n
), imm_val
)),
3175 DIP("vhadd.%c%d %c%u, %c%u, %c%u\n",
3176 U
? 'u' : 's', 8 << size
, regType
,
3177 dreg
, regType
, nreg
, regType
, mreg
);
3182 HChar reg_t
= Q
? 'q' : 'd';
3186 op
= U
? Iop_QAdd8Ux16
: Iop_QAdd8Sx16
;
3190 op
= U
? Iop_QAdd16Ux8
: Iop_QAdd16Sx8
;
3194 op
= U
? Iop_QAdd32Ux4
: Iop_QAdd32Sx4
;
3198 op
= U
? Iop_QAdd64Ux2
: Iop_QAdd64Sx2
;
3207 op
= U
? Iop_QAdd8Ux8
: Iop_QAdd8Sx8
;
3211 op
= U
? Iop_QAdd16Ux4
: Iop_QAdd16Sx4
;
3215 op
= U
? Iop_QAdd32Ux2
: Iop_QAdd32Sx2
;
3219 op
= U
? Iop_QAdd64Ux1
: Iop_QAdd64Sx1
;
3227 tmp
= newTemp(Ity_V128
);
3229 tmp
= newTemp(Ity_I64
);
3231 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
3232 assign(tmp
, binop(op2
, mkexpr(arg_n
), mkexpr(arg_m
)));
3233 setFlag_QC(mkexpr(res
), mkexpr(tmp
), Q
, condT
);
3234 DIP("vqadd.%c%d %c%u %c%u, %c%u\n",
3236 8 << size
, reg_t
, dreg
, reg_t
, nreg
, reg_t
, mreg
);
3242 /* VRHADD C, A, B ::=
3243 C = (A >> 1) + (B >> 1) + (((A & 1) + (B & 1) + 1) >> 1) */
3244 IROp shift_op
, add_op
;
3247 HChar reg_t
= Q
? 'q' : 'd';
3249 case 0: one
= (one
<< 8) | one
; /* fall through */
3250 case 1: one
= (one
<< 16) | one
; /* fall through */
3251 case 2: one
= (one
<< 32) | one
; break;
3252 case 3: return False
;
3253 default: vassert(0);
3258 shift_op
= U
? Iop_ShrN8x16
: Iop_SarN8x16
;
3259 add_op
= Iop_Add8x16
;
3262 shift_op
= U
? Iop_ShrN16x8
: Iop_SarN16x8
;
3263 add_op
= Iop_Add16x8
;
3266 shift_op
= U
? Iop_ShrN32x4
: Iop_SarN32x4
;
3267 add_op
= Iop_Add32x4
;
3277 shift_op
= U
? Iop_ShrN8x8
: Iop_SarN8x8
;
3278 add_op
= Iop_Add8x8
;
3281 shift_op
= U
? Iop_ShrN16x4
: Iop_SarN16x4
;
3282 add_op
= Iop_Add16x4
;
3285 shift_op
= U
? Iop_ShrN32x2
: Iop_SarN32x2
;
3286 add_op
= Iop_Add32x2
;
3295 cc
= newTemp(Ity_V128
);
3296 assign(cc
, binop(shift_op
,
3301 binop(Iop_64HLtoV128
,
3306 binop(Iop_64HLtoV128
,
3309 binop(Iop_64HLtoV128
,
3313 assign(res
, binop(add_op
,
3323 cc
= newTemp(Ity_I64
);
3324 assign(cc
, binop(shift_op
,
3335 assign(res
, binop(add_op
,
3345 DIP("vrhadd.%c%d %c%u, %c%u, %c%u\n",
3347 8 << size
, reg_t
, dreg
, reg_t
, nreg
, reg_t
, mreg
);
3353 HChar reg_t
= Q
? 'q' : 'd';
3355 assign(res
, binop(Iop_AndV128
, mkexpr(arg_n
),
3358 assign(res
, binop(Iop_And64
, mkexpr(arg_n
),
3361 DIP("vand %c%u, %c%u, %c%u\n",
3362 reg_t
, dreg
, reg_t
, nreg
, reg_t
, mreg
);
3367 HChar reg_t
= Q
? 'q' : 'd';
3369 assign(res
, binop(Iop_AndV128
,mkexpr(arg_n
),
3370 unop(Iop_NotV128
, mkexpr(arg_m
))));
3372 assign(res
, binop(Iop_And64
, mkexpr(arg_n
),
3373 unop(Iop_Not64
, mkexpr(arg_m
))));
3375 DIP("vbic %c%u, %c%u, %c%u\n",
3376 reg_t
, dreg
, reg_t
, nreg
, reg_t
, mreg
);
3380 if ( nreg
!= mreg
) {
3382 HChar reg_t
= Q
? 'q' : 'd';
3384 assign(res
, binop(Iop_OrV128
, mkexpr(arg_n
),
3387 assign(res
, binop(Iop_Or64
, mkexpr(arg_n
),
3390 DIP("vorr %c%u, %c%u, %c%u\n",
3391 reg_t
, dreg
, reg_t
, nreg
, reg_t
, mreg
);
3394 HChar reg_t
= Q
? 'q' : 'd';
3395 assign(res
, mkexpr(arg_m
));
3396 DIP("vmov %c%u, %c%u\n", reg_t
, dreg
, reg_t
, mreg
);
3401 HChar reg_t
= Q
? 'q' : 'd';
3403 assign(res
, binop(Iop_OrV128
,mkexpr(arg_n
),
3404 unop(Iop_NotV128
, mkexpr(arg_m
))));
3406 assign(res
, binop(Iop_Or64
, mkexpr(arg_n
),
3407 unop(Iop_Not64
, mkexpr(arg_m
))));
3409 DIP("vorn %c%u, %c%u, %c%u\n",
3410 reg_t
, dreg
, reg_t
, nreg
, reg_t
, mreg
);
3421 assign(res
, binop(Iop_XorV128
, mkexpr(arg_n
),
3424 assign(res
, binop(Iop_Xor64
, mkexpr(arg_n
),
3427 DIP("veor %c%u, %c%u, %c%u\n", Q
? 'q' : 'd', dreg
,
3428 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
3433 IRTemp reg_d
= newTemp(Ity_V128
);
3434 assign(reg_d
, getQReg(dreg
));
3437 binop(Iop_AndV128
, mkexpr(arg_n
),
3442 mkexpr(reg_d
)) ) ) );
3444 IRTemp reg_d
= newTemp(Ity_I64
);
3445 assign(reg_d
, getDRegI64(dreg
));
3448 binop(Iop_And64
, mkexpr(arg_n
),
3452 unop(Iop_Not64
, mkexpr(reg_d
)))));
3454 DIP("vbsl %c%u, %c%u, %c%u\n",
3455 Q
? 'q' : 'd', dreg
,
3456 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
3461 IRTemp reg_d
= newTemp(Ity_V128
);
3462 assign(reg_d
, getQReg(dreg
));
3465 binop(Iop_AndV128
, mkexpr(arg_n
),
3469 unop(Iop_NotV128
, mkexpr(arg_m
)))));
3471 IRTemp reg_d
= newTemp(Ity_I64
);
3472 assign(reg_d
, getDRegI64(dreg
));
3475 binop(Iop_And64
, mkexpr(arg_n
),
3479 unop(Iop_Not64
, mkexpr(arg_m
)))));
3481 DIP("vbit %c%u, %c%u, %c%u\n",
3482 Q
? 'q' : 'd', dreg
,
3483 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
3488 IRTemp reg_d
= newTemp(Ity_V128
);
3489 assign(reg_d
, getQReg(dreg
));
3492 binop(Iop_AndV128
, mkexpr(reg_d
),
3496 unop(Iop_NotV128
, mkexpr(arg_m
)))));
3498 IRTemp reg_d
= newTemp(Ity_I64
);
3499 assign(reg_d
, getDRegI64(dreg
));
3502 binop(Iop_And64
, mkexpr(reg_d
),
3506 unop(Iop_Not64
, mkexpr(arg_m
)))));
3508 DIP("vbif %c%u, %c%u, %c%u\n",
3509 Q
? 'q' : 'd', dreg
,
3510 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
3521 /* (A >> 1) - (B >> 1) - (NOT (A) & B & 1) */
3531 case 0: imm
= 0x101010101010101LL
; break;
3532 case 1: imm
= 0x1000100010001LL
; break;
3533 case 2: imm
= 0x100000001LL
; break;
3534 default: vassert(0);
3537 imm_val
= binop(Iop_64HLtoV128
, mkU64(imm
), mkU64(imm
));
3538 andOp
= Iop_AndV128
;
3539 notOp
= Iop_NotV128
;
3541 imm_val
= mkU64(imm
);
3548 subOp
= Q
? Iop_Sub8x16
: Iop_Sub8x8
;
3549 shOp
= Q
? Iop_ShrN8x16
: Iop_ShrN8x8
;
3552 subOp
= Q
? Iop_Sub16x8
: Iop_Sub16x4
;
3553 shOp
= Q
? Iop_ShrN16x8
: Iop_ShrN16x4
;
3556 subOp
= Q
? Iop_Sub32x4
: Iop_Sub32x2
;
3557 shOp
= Q
? Iop_ShrN32x4
: Iop_ShrN32x2
;
3565 subOp
= Q
? Iop_Sub8x16
: Iop_Sub8x8
;
3566 shOp
= Q
? Iop_SarN8x16
: Iop_SarN8x8
;
3569 subOp
= Q
? Iop_Sub16x8
: Iop_Sub16x4
;
3570 shOp
= Q
? Iop_SarN16x8
: Iop_SarN16x4
;
3573 subOp
= Q
? Iop_Sub32x4
: Iop_Sub32x2
;
3574 shOp
= Q
? Iop_SarN32x4
: Iop_SarN32x2
;
3583 binop(shOp
, mkexpr(arg_n
), mkU8(1)),
3584 binop(shOp
, mkexpr(arg_m
), mkU8(1))),
3587 unop(notOp
, mkexpr(arg_n
)),
3590 DIP("vhsub.%c%d %c%u, %c%u, %c%u\n",
3591 U
? 'u' : 's', 8 << size
,
3592 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd',
3601 op
= U
? Iop_QSub8Ux16
: Iop_QSub8Sx16
;
3605 op
= U
? Iop_QSub16Ux8
: Iop_QSub16Sx8
;
3609 op
= U
? Iop_QSub32Ux4
: Iop_QSub32Sx4
;
3613 op
= U
? Iop_QSub64Ux2
: Iop_QSub64Sx2
;
3622 op
= U
? Iop_QSub8Ux8
: Iop_QSub8Sx8
;
3626 op
= U
? Iop_QSub16Ux4
: Iop_QSub16Sx4
;
3630 op
= U
? Iop_QSub32Ux2
: Iop_QSub32Sx2
;
3634 op
= U
? Iop_QSub64Ux1
: Iop_QSub64Sx1
;
3642 tmp
= newTemp(Ity_V128
);
3644 tmp
= newTemp(Ity_I64
);
3645 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
3646 assign(tmp
, binop(op2
, mkexpr(arg_n
), mkexpr(arg_m
)));
3647 setFlag_QC(mkexpr(res
), mkexpr(tmp
), Q
, condT
);
3648 DIP("vqsub.%c%d %c%u, %c%u, %c%u\n",
3649 U
? 'u' : 's', 8 << size
,
3650 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd',
3658 case 0: op
= U
? Iop_CmpGT8Ux16
: Iop_CmpGT8Sx16
; break;
3659 case 1: op
= U
? Iop_CmpGT16Ux8
: Iop_CmpGT16Sx8
; break;
3660 case 2: op
= U
? Iop_CmpGT32Ux4
: Iop_CmpGT32Sx4
; break;
3661 case 3: return False
;
3662 default: vassert(0);
3666 case 0: op
= U
? Iop_CmpGT8Ux8
: Iop_CmpGT8Sx8
; break;
3667 case 1: op
= U
? Iop_CmpGT16Ux4
: Iop_CmpGT16Sx4
; break;
3668 case 2: op
= U
? Iop_CmpGT32Ux2
: Iop_CmpGT32Sx2
; break;
3669 case 3: return False
;
3670 default: vassert(0);
3675 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
3676 DIP("vcgt.%c%d %c%u, %c%u, %c%u\n",
3677 U
? 'u' : 's', 8 << size
,
3678 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd',
3682 /* VCGE res, argn, argm
3684 VCGT tmp, argm, argn
3687 unop(Q
? Iop_NotV128
: Iop_Not64
,
3688 binop(op
, mkexpr(arg_m
), mkexpr(arg_n
))));
3689 DIP("vcge.%c%d %c%u, %c%u, %c%u\n",
3690 U
? 'u' : 's', 8 << size
,
3691 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd',
3699 IROp op
= Iop_INVALID
, sub_op
= Iop_INVALID
;
3700 IRTemp tmp
= IRTemp_INVALID
;
3703 case 0: op
= Q
? Iop_Shl8x16
: Iop_Shl8x8
; break;
3704 case 1: op
= Q
? Iop_Shl16x8
: Iop_Shl16x4
; break;
3705 case 2: op
= Q
? Iop_Shl32x4
: Iop_Shl32x2
; break;
3706 case 3: op
= Q
? Iop_Shl64x2
: Iop_Shl64
; break;
3707 default: vassert(0);
3710 tmp
= newTemp(Q
? Ity_V128
: Ity_I64
);
3713 op
= Q
? Iop_Sar8x16
: Iop_Sar8x8
;
3714 sub_op
= Q
? Iop_Sub8x16
: Iop_Sub8x8
;
3717 op
= Q
? Iop_Sar16x8
: Iop_Sar16x4
;
3718 sub_op
= Q
? Iop_Sub16x8
: Iop_Sub16x4
;
3721 op
= Q
? Iop_Sar32x4
: Iop_Sar32x2
;
3722 sub_op
= Q
? Iop_Sub32x4
: Iop_Sub32x2
;
3725 op
= Q
? Iop_Sar64x2
: Iop_Sar64
;
3726 sub_op
= Q
? Iop_Sub64x2
: Iop_Sub64
;
3733 if (!Q
&& (size
== 3))
3734 assign(res
, binop(op
, mkexpr(arg_m
),
3735 unop(Iop_64to8
, mkexpr(arg_n
))));
3737 assign(res
, binop(op
, mkexpr(arg_m
), mkexpr(arg_n
)));
3740 assign(tmp
, binop(sub_op
,
3741 binop(Iop_64HLtoV128
, mkU64(0), mkU64(0)),
3744 assign(tmp
, binop(sub_op
, mkU64(0), mkexpr(arg_n
)));
3745 if (!Q
&& (size
== 3))
3746 assign(res
, binop(op
, mkexpr(arg_m
),
3747 unop(Iop_64to8
, mkexpr(tmp
))));
3749 assign(res
, binop(op
, mkexpr(arg_m
), mkexpr(tmp
)));
3751 DIP("vshl.%c%d %c%u, %c%u, %c%u\n",
3752 U
? 'u' : 's', 8 << size
,
3753 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
, Q
? 'q' : 'd',
3757 IROp op
, op_rev
, op_shrn
, op_shln
, cmp_neq
, cmp_gt
;
3758 IRTemp tmp
, shval
, mask
, old_shval
;
3761 cmp_neq
= Q
? Iop_CmpNEZ8x16
: Iop_CmpNEZ8x8
;
3762 cmp_gt
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
;
3766 op
= Q
? Iop_QShl8x16
: Iop_QShl8x8
;
3767 op_rev
= Q
? Iop_Shr8x16
: Iop_Shr8x8
;
3768 op_shrn
= Q
? Iop_ShrN8x16
: Iop_ShrN8x8
;
3769 op_shln
= Q
? Iop_ShlN8x16
: Iop_ShlN8x8
;
3772 op
= Q
? Iop_QShl16x8
: Iop_QShl16x4
;
3773 op_rev
= Q
? Iop_Shr16x8
: Iop_Shr16x4
;
3774 op_shrn
= Q
? Iop_ShrN16x8
: Iop_ShrN16x4
;
3775 op_shln
= Q
? Iop_ShlN16x8
: Iop_ShlN16x4
;
3778 op
= Q
? Iop_QShl32x4
: Iop_QShl32x2
;
3779 op_rev
= Q
? Iop_Shr32x4
: Iop_Shr32x2
;
3780 op_shrn
= Q
? Iop_ShrN32x4
: Iop_ShrN32x2
;
3781 op_shln
= Q
? Iop_ShlN32x4
: Iop_ShlN32x2
;
3784 op
= Q
? Iop_QShl64x2
: Iop_QShl64x1
;
3785 op_rev
= Q
? Iop_Shr64x2
: Iop_Shr64
;
3786 op_shrn
= Q
? Iop_ShrN64x2
: Iop_Shr64
;
3787 op_shln
= Q
? Iop_ShlN64x2
: Iop_Shl64
;
3795 op
= Q
? Iop_QSal8x16
: Iop_QSal8x8
;
3796 op_rev
= Q
? Iop_Sar8x16
: Iop_Sar8x8
;
3797 op_shrn
= Q
? Iop_ShrN8x16
: Iop_ShrN8x8
;
3798 op_shln
= Q
? Iop_ShlN8x16
: Iop_ShlN8x8
;
3801 op
= Q
? Iop_QSal16x8
: Iop_QSal16x4
;
3802 op_rev
= Q
? Iop_Sar16x8
: Iop_Sar16x4
;
3803 op_shrn
= Q
? Iop_ShrN16x8
: Iop_ShrN16x4
;
3804 op_shln
= Q
? Iop_ShlN16x8
: Iop_ShlN16x4
;
3807 op
= Q
? Iop_QSal32x4
: Iop_QSal32x2
;
3808 op_rev
= Q
? Iop_Sar32x4
: Iop_Sar32x2
;
3809 op_shrn
= Q
? Iop_ShrN32x4
: Iop_ShrN32x2
;
3810 op_shln
= Q
? Iop_ShlN32x4
: Iop_ShlN32x2
;
3813 op
= Q
? Iop_QSal64x2
: Iop_QSal64x1
;
3814 op_rev
= Q
? Iop_Sar64x2
: Iop_Sar64
;
3815 op_shrn
= Q
? Iop_ShrN64x2
: Iop_Shr64
;
3816 op_shln
= Q
? Iop_ShlN64x2
: Iop_Shl64
;
3823 tmp
= newTemp(Ity_V128
);
3824 shval
= newTemp(Ity_V128
);
3825 mask
= newTemp(Ity_V128
);
3827 tmp
= newTemp(Ity_I64
);
3828 shval
= newTemp(Ity_I64
);
3829 mask
= newTemp(Ity_I64
);
3831 assign(res
, binop(op
, mkexpr(arg_m
), mkexpr(arg_n
)));
3832 /* Only least significant byte from second argument is used.
3833 Copy this byte to the whole vector element. */
3834 assign(shval
, binop(op_shrn
,
3837 mkU8((8 << size
) - 8)),
3838 mkU8((8 << size
) - 8)));
3839 for(i
= 0; i
< size
; i
++) {
3841 shval
= newTemp(Q
? Ity_V128
: Ity_I64
);
3842 assign(shval
, binop(Q
? Iop_OrV128
: Iop_Or64
,
3848 /* If shift is greater or equal to the element size and
3849 element is non-zero, then QC flag should be set. */
3850 esize
= (8 << size
) - 1;
3851 esize
= (esize
<< 8) | esize
;
3852 esize
= (esize
<< 16) | esize
;
3853 esize
= (esize
<< 32) | esize
;
3854 setFlag_QC(binop(Q
? Iop_AndV128
: Iop_And64
,
3855 binop(cmp_gt
, mkexpr(shval
),
3856 Q
? mkU128(esize
) : mkU64(esize
)),
3857 unop(cmp_neq
, mkexpr(arg_m
))),
3858 Q
? mkU128(0) : mkU64(0),
3860 /* Othervise QC flag should be set if shift value is positive and
3861 result beign rightshifted the same value is not equal to left
3863 assign(mask
, binop(cmp_gt
, mkexpr(shval
),
3864 Q
? mkU128(0) : mkU64(0)));
3865 if (!Q
&& size
== 3)
3866 assign(tmp
, binop(op_rev
, mkexpr(res
),
3867 unop(Iop_64to8
, mkexpr(arg_n
))));
3869 assign(tmp
, binop(op_rev
, mkexpr(res
), mkexpr(arg_n
)));
3870 setFlag_QC(binop(Q
? Iop_AndV128
: Iop_And64
,
3871 mkexpr(tmp
), mkexpr(mask
)),
3872 binop(Q
? Iop_AndV128
: Iop_And64
,
3873 mkexpr(arg_m
), mkexpr(mask
)),
3875 DIP("vqshl.%c%d %c%u, %c%u, %c%u\n",
3876 U
? 'u' : 's', 8 << size
,
3877 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
, Q
? 'q' : 'd',
3884 IROp op
, op_shrn
, op_shln
, cmp_gt
, op_add
;
3885 IRTemp shval
, old_shval
, imm_val
, round
;
3888 cmp_gt
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
;
3891 case 0: imm
= (imm
<< 8) | imm
; /* fall through */
3892 case 1: imm
= (imm
<< 16) | imm
; /* fall through */
3893 case 2: imm
= (imm
<< 32) | imm
; /* fall through */
3895 default: vassert(0);
3897 imm_val
= newTemp(Q
? Ity_V128
: Ity_I64
);
3898 round
= newTemp(Q
? Ity_V128
: Ity_I64
);
3899 assign(imm_val
, Q
? mkU128(imm
) : mkU64(imm
));
3903 op
= Q
? Iop_Shl8x16
: Iop_Shl8x8
;
3904 op_add
= Q
? Iop_Add8x16
: Iop_Add8x8
;
3905 op_shrn
= Q
? Iop_ShrN8x16
: Iop_ShrN8x8
;
3906 op_shln
= Q
? Iop_ShlN8x16
: Iop_ShlN8x8
;
3909 op
= Q
? Iop_Shl16x8
: Iop_Shl16x4
;
3910 op_add
= Q
? Iop_Add16x8
: Iop_Add16x4
;
3911 op_shrn
= Q
? Iop_ShrN16x8
: Iop_ShrN16x4
;
3912 op_shln
= Q
? Iop_ShlN16x8
: Iop_ShlN16x4
;
3915 op
= Q
? Iop_Shl32x4
: Iop_Shl32x2
;
3916 op_add
= Q
? Iop_Add32x4
: Iop_Add32x2
;
3917 op_shrn
= Q
? Iop_ShrN32x4
: Iop_ShrN32x2
;
3918 op_shln
= Q
? Iop_ShlN32x4
: Iop_ShlN32x2
;
3921 op
= Q
? Iop_Shl64x2
: Iop_Shl64
;
3922 op_add
= Q
? Iop_Add64x2
: Iop_Add64
;
3923 op_shrn
= Q
? Iop_ShrN64x2
: Iop_Shr64
;
3924 op_shln
= Q
? Iop_ShlN64x2
: Iop_Shl64
;
3932 op
= Q
? Iop_Sal8x16
: Iop_Sal8x8
;
3933 op_add
= Q
? Iop_Add8x16
: Iop_Add8x8
;
3934 op_shrn
= Q
? Iop_ShrN8x16
: Iop_ShrN8x8
;
3935 op_shln
= Q
? Iop_ShlN8x16
: Iop_ShlN8x8
;
3938 op
= Q
? Iop_Sal16x8
: Iop_Sal16x4
;
3939 op_add
= Q
? Iop_Add16x8
: Iop_Add16x4
;
3940 op_shrn
= Q
? Iop_ShrN16x8
: Iop_ShrN16x4
;
3941 op_shln
= Q
? Iop_ShlN16x8
: Iop_ShlN16x4
;
3944 op
= Q
? Iop_Sal32x4
: Iop_Sal32x2
;
3945 op_add
= Q
? Iop_Add32x4
: Iop_Add32x2
;
3946 op_shrn
= Q
? Iop_ShrN32x4
: Iop_ShrN32x2
;
3947 op_shln
= Q
? Iop_ShlN32x4
: Iop_ShlN32x2
;
3950 op
= Q
? Iop_Sal64x2
: Iop_Sal64x1
;
3951 op_add
= Q
? Iop_Add64x2
: Iop_Add64
;
3952 op_shrn
= Q
? Iop_ShrN64x2
: Iop_Shr64
;
3953 op_shln
= Q
? Iop_ShlN64x2
: Iop_Shl64
;
3960 shval
= newTemp(Ity_V128
);
3962 shval
= newTemp(Ity_I64
);
3964 /* Only least significant byte from second argument is used.
3965 Copy this byte to the whole vector element. */
3966 assign(shval
, binop(op_shrn
,
3969 mkU8((8 << size
) - 8)),
3970 mkU8((8 << size
) - 8)));
3971 for (i
= 0; i
< size
; i
++) {
3973 shval
= newTemp(Q
? Ity_V128
: Ity_I64
);
3974 assign(shval
, binop(Q
? Iop_OrV128
: Iop_Or64
,
3980 /* Compute the result */
3981 if (!Q
&& size
== 3 && U
) {
3982 assign(round
, binop(Q
? Iop_AndV128
: Iop_And64
,
3989 binop(Q
? Iop_AndV128
: Iop_And64
,
3992 Q
? mkU128(0) : mkU64(0),
3994 assign(res
, binop(op_add
,
3997 unop(Iop_64to8
, mkexpr(arg_n
))),
4000 assign(round
, binop(Q
? Iop_AndV128
: Iop_And64
,
4006 binop(Q
? Iop_AndV128
: Iop_And64
,
4009 Q
? mkU128(0) : mkU64(0),
4011 assign(res
, binop(op_add
,
4012 binop(op
, mkexpr(arg_m
), mkexpr(arg_n
)),
4015 DIP("vrshl.%c%d %c%u, %c%u, %c%u\n",
4016 U
? 'u' : 's', 8 << size
,
4017 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
, Q
? 'q' : 'd',
4021 IROp op
, op_rev
, op_shrn
, op_shln
, cmp_neq
, cmp_gt
, op_add
;
4022 IRTemp tmp
, shval
, mask
, old_shval
, imm_val
, round
;
4025 cmp_neq
= Q
? Iop_CmpNEZ8x16
: Iop_CmpNEZ8x8
;
4026 cmp_gt
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
;
4029 case 0: imm
= (imm
<< 8) | imm
; /* fall through */
4030 case 1: imm
= (imm
<< 16) | imm
; /* fall through */
4031 case 2: imm
= (imm
<< 32) | imm
; /* fall through */
4033 default: vassert(0);
4035 imm_val
= newTemp(Q
? Ity_V128
: Ity_I64
);
4036 round
= newTemp(Q
? Ity_V128
: Ity_I64
);
4037 assign(imm_val
, Q
? mkU128(imm
) : mkU64(imm
));
4041 op
= Q
? Iop_QShl8x16
: Iop_QShl8x8
;
4042 op_add
= Q
? Iop_Add8x16
: Iop_Add8x8
;
4043 op_rev
= Q
? Iop_Shr8x16
: Iop_Shr8x8
;
4044 op_shrn
= Q
? Iop_ShrN8x16
: Iop_ShrN8x8
;
4045 op_shln
= Q
? Iop_ShlN8x16
: Iop_ShlN8x8
;
4048 op
= Q
? Iop_QShl16x8
: Iop_QShl16x4
;
4049 op_add
= Q
? Iop_Add16x8
: Iop_Add16x4
;
4050 op_rev
= Q
? Iop_Shr16x8
: Iop_Shr16x4
;
4051 op_shrn
= Q
? Iop_ShrN16x8
: Iop_ShrN16x4
;
4052 op_shln
= Q
? Iop_ShlN16x8
: Iop_ShlN16x4
;
4055 op
= Q
? Iop_QShl32x4
: Iop_QShl32x2
;
4056 op_add
= Q
? Iop_Add32x4
: Iop_Add32x2
;
4057 op_rev
= Q
? Iop_Shr32x4
: Iop_Shr32x2
;
4058 op_shrn
= Q
? Iop_ShrN32x4
: Iop_ShrN32x2
;
4059 op_shln
= Q
? Iop_ShlN32x4
: Iop_ShlN32x2
;
4062 op
= Q
? Iop_QShl64x2
: Iop_QShl64x1
;
4063 op_add
= Q
? Iop_Add64x2
: Iop_Add64
;
4064 op_rev
= Q
? Iop_Shr64x2
: Iop_Shr64
;
4065 op_shrn
= Q
? Iop_ShrN64x2
: Iop_Shr64
;
4066 op_shln
= Q
? Iop_ShlN64x2
: Iop_Shl64
;
4074 op
= Q
? Iop_QSal8x16
: Iop_QSal8x8
;
4075 op_add
= Q
? Iop_Add8x16
: Iop_Add8x8
;
4076 op_rev
= Q
? Iop_Sar8x16
: Iop_Sar8x8
;
4077 op_shrn
= Q
? Iop_ShrN8x16
: Iop_ShrN8x8
;
4078 op_shln
= Q
? Iop_ShlN8x16
: Iop_ShlN8x8
;
4081 op
= Q
? Iop_QSal16x8
: Iop_QSal16x4
;
4082 op_add
= Q
? Iop_Add16x8
: Iop_Add16x4
;
4083 op_rev
= Q
? Iop_Sar16x8
: Iop_Sar16x4
;
4084 op_shrn
= Q
? Iop_ShrN16x8
: Iop_ShrN16x4
;
4085 op_shln
= Q
? Iop_ShlN16x8
: Iop_ShlN16x4
;
4088 op
= Q
? Iop_QSal32x4
: Iop_QSal32x2
;
4089 op_add
= Q
? Iop_Add32x4
: Iop_Add32x2
;
4090 op_rev
= Q
? Iop_Sar32x4
: Iop_Sar32x2
;
4091 op_shrn
= Q
? Iop_ShrN32x4
: Iop_ShrN32x2
;
4092 op_shln
= Q
? Iop_ShlN32x4
: Iop_ShlN32x2
;
4095 op
= Q
? Iop_QSal64x2
: Iop_QSal64x1
;
4096 op_add
= Q
? Iop_Add64x2
: Iop_Add64
;
4097 op_rev
= Q
? Iop_Sar64x2
: Iop_Sar64
;
4098 op_shrn
= Q
? Iop_ShrN64x2
: Iop_Shr64
;
4099 op_shln
= Q
? Iop_ShlN64x2
: Iop_Shl64
;
4106 tmp
= newTemp(Ity_V128
);
4107 shval
= newTemp(Ity_V128
);
4108 mask
= newTemp(Ity_V128
);
4110 tmp
= newTemp(Ity_I64
);
4111 shval
= newTemp(Ity_I64
);
4112 mask
= newTemp(Ity_I64
);
4114 /* Only least significant byte from second argument is used.
4115 Copy this byte to the whole vector element. */
4116 assign(shval
, binop(op_shrn
,
4119 mkU8((8 << size
) - 8)),
4120 mkU8((8 << size
) - 8)));
4121 for (i
= 0; i
< size
; i
++) {
4123 shval
= newTemp(Q
? Ity_V128
: Ity_I64
);
4124 assign(shval
, binop(Q
? Iop_OrV128
: Iop_Or64
,
4130 /* Compute the result */
4131 assign(round
, binop(Q
? Iop_AndV128
: Iop_And64
,
4137 binop(Q
? Iop_AndV128
: Iop_And64
,
4140 Q
? mkU128(0) : mkU64(0),
4142 assign(res
, binop(op_add
,
4143 binop(op
, mkexpr(arg_m
), mkexpr(arg_n
)),
4145 /* If shift is greater or equal to the element size and element is
4146 non-zero, then QC flag should be set. */
4147 esize
= (8 << size
) - 1;
4148 esize
= (esize
<< 8) | esize
;
4149 esize
= (esize
<< 16) | esize
;
4150 esize
= (esize
<< 32) | esize
;
4151 setFlag_QC(binop(Q
? Iop_AndV128
: Iop_And64
,
4152 binop(cmp_gt
, mkexpr(shval
),
4153 Q
? mkU128(esize
) : mkU64(esize
)),
4154 unop(cmp_neq
, mkexpr(arg_m
))),
4155 Q
? mkU128(0) : mkU64(0),
4157 /* Othervise QC flag should be set if shift value is positive and
4158 result beign rightshifted the same value is not equal to left
4160 assign(mask
, binop(cmp_gt
, mkexpr(shval
),
4161 Q
? mkU128(0) : mkU64(0)));
4162 if (!Q
&& size
== 3)
4163 assign(tmp
, binop(op_rev
, mkexpr(res
),
4164 unop(Iop_64to8
, mkexpr(arg_n
))));
4166 assign(tmp
, binop(op_rev
, mkexpr(res
), mkexpr(arg_n
)));
4167 setFlag_QC(binop(Q
? Iop_AndV128
: Iop_And64
,
4168 mkexpr(tmp
), mkexpr(mask
)),
4169 binop(Q
? Iop_AndV128
: Iop_And64
,
4170 mkexpr(arg_m
), mkexpr(mask
)),
4172 DIP("vqrshl.%c%d %c%u, %c%u, %c%u\n",
4173 U
? 'u' : 's', 8 << size
,
4174 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
, Q
? 'q' : 'd',
4185 case 0: op
= Q
? Iop_Max8Sx16
: Iop_Max8Sx8
; break;
4186 case 1: op
= Q
? Iop_Max16Sx8
: Iop_Max16Sx4
; break;
4187 case 2: op
= Q
? Iop_Max32Sx4
: Iop_Max32Sx2
; break;
4188 case 3: return False
;
4189 default: vassert(0);
4193 case 0: op
= Q
? Iop_Max8Ux16
: Iop_Max8Ux8
; break;
4194 case 1: op
= Q
? Iop_Max16Ux8
: Iop_Max16Ux4
; break;
4195 case 2: op
= Q
? Iop_Max32Ux4
: Iop_Max32Ux2
; break;
4196 case 3: return False
;
4197 default: vassert(0);
4200 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4201 DIP("vmax.%c%d %c%u, %c%u, %c%u\n",
4202 U
? 'u' : 's', 8 << size
,
4203 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd',
4210 case 0: op
= Q
? Iop_Min8Sx16
: Iop_Min8Sx8
; break;
4211 case 1: op
= Q
? Iop_Min16Sx8
: Iop_Min16Sx4
; break;
4212 case 2: op
= Q
? Iop_Min32Sx4
: Iop_Min32Sx2
; break;
4213 case 3: return False
;
4214 default: vassert(0);
4218 case 0: op
= Q
? Iop_Min8Ux16
: Iop_Min8Ux8
; break;
4219 case 1: op
= Q
? Iop_Min16Ux8
: Iop_Min16Ux4
; break;
4220 case 2: op
= Q
? Iop_Min32Ux4
: Iop_Min32Ux2
; break;
4221 case 3: return False
;
4222 default: vassert(0);
4225 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4226 DIP("vmin.%c%d %c%u, %c%u, %c%u\n",
4227 U
? 'u' : 's', 8 << size
,
4228 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd',
4235 IROp op_cmp
, op_sub
;
4237 if ((theInstr
>> 23) & 1) {
4238 vpanic("VABDL should not be in dis_neon_data_3same\n");
4243 op_cmp
= U
? Iop_CmpGT8Ux16
: Iop_CmpGT8Sx16
;
4244 op_sub
= Iop_Sub8x16
;
4247 op_cmp
= U
? Iop_CmpGT16Ux8
: Iop_CmpGT16Sx8
;
4248 op_sub
= Iop_Sub16x8
;
4251 op_cmp
= U
? Iop_CmpGT32Ux4
: Iop_CmpGT32Sx4
;
4252 op_sub
= Iop_Sub32x4
;
4262 op_cmp
= U
? Iop_CmpGT8Ux8
: Iop_CmpGT8Sx8
;
4263 op_sub
= Iop_Sub8x8
;
4266 op_cmp
= U
? Iop_CmpGT16Ux4
: Iop_CmpGT16Sx4
;
4267 op_sub
= Iop_Sub16x4
;
4270 op_cmp
= U
? Iop_CmpGT32Ux2
: Iop_CmpGT32Sx2
;
4271 op_sub
= Iop_Sub32x2
;
4280 cond
= newTemp(Ity_V128
);
4282 cond
= newTemp(Ity_I64
);
4284 assign(cond
, binop(op_cmp
, mkexpr(arg_n
), mkexpr(arg_m
)));
4285 assign(res
, binop(Q
? Iop_OrV128
: Iop_Or64
,
4286 binop(Q
? Iop_AndV128
: Iop_And64
,
4287 binop(op_sub
, mkexpr(arg_n
),
4290 binop(Q
? Iop_AndV128
: Iop_And64
,
4291 binop(op_sub
, mkexpr(arg_m
),
4293 unop(Q
? Iop_NotV128
: Iop_Not64
,
4295 DIP("vabd.%c%d %c%u, %c%u, %c%u\n",
4296 U
? 'u' : 's', 8 << size
,
4297 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd',
4301 IROp op_cmp
, op_sub
, op_add
;
4302 IRTemp cond
, acc
, tmp
;
4303 if ((theInstr
>> 23) & 1) {
4304 vpanic("VABAL should not be in dis_neon_data_3same");
4309 op_cmp
= U
? Iop_CmpGT8Ux16
: Iop_CmpGT8Sx16
;
4310 op_sub
= Iop_Sub8x16
;
4311 op_add
= Iop_Add8x16
;
4314 op_cmp
= U
? Iop_CmpGT16Ux8
: Iop_CmpGT16Sx8
;
4315 op_sub
= Iop_Sub16x8
;
4316 op_add
= Iop_Add16x8
;
4319 op_cmp
= U
? Iop_CmpGT32Ux4
: Iop_CmpGT32Sx4
;
4320 op_sub
= Iop_Sub32x4
;
4321 op_add
= Iop_Add32x4
;
4331 op_cmp
= U
? Iop_CmpGT8Ux8
: Iop_CmpGT8Sx8
;
4332 op_sub
= Iop_Sub8x8
;
4333 op_add
= Iop_Add8x8
;
4336 op_cmp
= U
? Iop_CmpGT16Ux4
: Iop_CmpGT16Sx4
;
4337 op_sub
= Iop_Sub16x4
;
4338 op_add
= Iop_Add16x4
;
4341 op_cmp
= U
? Iop_CmpGT32Ux2
: Iop_CmpGT32Sx2
;
4342 op_sub
= Iop_Sub32x2
;
4343 op_add
= Iop_Add32x2
;
4352 cond
= newTemp(Ity_V128
);
4353 acc
= newTemp(Ity_V128
);
4354 tmp
= newTemp(Ity_V128
);
4355 assign(acc
, getQReg(dreg
));
4357 cond
= newTemp(Ity_I64
);
4358 acc
= newTemp(Ity_I64
);
4359 tmp
= newTemp(Ity_I64
);
4360 assign(acc
, getDRegI64(dreg
));
4362 assign(cond
, binop(op_cmp
, mkexpr(arg_n
), mkexpr(arg_m
)));
4363 assign(tmp
, binop(Q
? Iop_OrV128
: Iop_Or64
,
4364 binop(Q
? Iop_AndV128
: Iop_And64
,
4365 binop(op_sub
, mkexpr(arg_n
),
4368 binop(Q
? Iop_AndV128
: Iop_And64
,
4369 binop(op_sub
, mkexpr(arg_m
),
4371 unop(Q
? Iop_NotV128
: Iop_Not64
,
4373 assign(res
, binop(op_add
, mkexpr(acc
), mkexpr(tmp
)));
4374 DIP("vaba.%c%d %c%u, %c%u, %c%u\n",
4375 U
? 'u' : 's', 8 << size
,
4376 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd',
4386 case 0: op
= Q
? Iop_Add8x16
: Iop_Add8x8
; break;
4387 case 1: op
= Q
? Iop_Add16x8
: Iop_Add16x4
; break;
4388 case 2: op
= Q
? Iop_Add32x4
: Iop_Add32x2
; break;
4389 case 3: op
= Q
? Iop_Add64x2
: Iop_Add64
; break;
4390 default: vassert(0);
4392 DIP("vadd.i%d %c%u, %c%u, %c%u\n",
4393 8 << size
, Q
? 'q' : 'd',
4394 dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4398 case 0: op
= Q
? Iop_Sub8x16
: Iop_Sub8x8
; break;
4399 case 1: op
= Q
? Iop_Sub16x8
: Iop_Sub16x4
; break;
4400 case 2: op
= Q
? Iop_Sub32x4
: Iop_Sub32x2
; break;
4401 case 3: op
= Q
? Iop_Sub64x2
: Iop_Sub64
; break;
4402 default: vassert(0);
4404 DIP("vsub.i%d %c%u, %c%u, %c%u\n",
4405 8 << size
, Q
? 'q' : 'd',
4406 dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4408 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4412 case 0: op
= Q
? Iop_CmpNEZ8x16
: Iop_CmpNEZ8x8
; break;
4413 case 1: op
= Q
? Iop_CmpNEZ16x8
: Iop_CmpNEZ16x4
; break;
4414 case 2: op
= Q
? Iop_CmpNEZ32x4
: Iop_CmpNEZ32x2
; break;
4415 case 3: op
= Q
? Iop_CmpNEZ64x2
: Iop_CmpwNEZ64
; break;
4416 default: vassert(0);
4420 assign(res
, unop(op
, binop(Q
? Iop_AndV128
: Iop_And64
,
4423 DIP("vtst.%d %c%u, %c%u, %c%u\n",
4424 8 << size
, Q
? 'q' : 'd',
4425 dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4428 assign(res
, unop(Q
? Iop_NotV128
: Iop_Not64
,
4430 binop(Q
? Iop_XorV128
: Iop_Xor64
,
4433 DIP("vceq.i%d %c%u, %c%u, %c%u\n",
4434 8 << size
, Q
? 'q' : 'd',
4435 dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4441 /* VMLA, VMLS (integer) */
4443 UInt P
= (theInstr
>> 24) & 1;
4447 op
= Q
? Iop_Mul8x16
: Iop_Mul8x8
;
4448 op2
= Q
? Iop_Sub8x16
: Iop_Sub8x8
;
4451 op
= Q
? Iop_Mul16x8
: Iop_Mul16x4
;
4452 op2
= Q
? Iop_Sub16x8
: Iop_Sub16x4
;
4455 op
= Q
? Iop_Mul32x4
: Iop_Mul32x2
;
4456 op2
= Q
? Iop_Sub32x4
: Iop_Sub32x2
;
4466 op
= Q
? Iop_Mul8x16
: Iop_Mul8x8
;
4467 op2
= Q
? Iop_Add8x16
: Iop_Add8x8
;
4470 op
= Q
? Iop_Mul16x8
: Iop_Mul16x4
;
4471 op2
= Q
? Iop_Add16x8
: Iop_Add16x4
;
4474 op
= Q
? Iop_Mul32x4
: Iop_Mul32x2
;
4475 op2
= Q
? Iop_Add32x4
: Iop_Add32x2
;
4483 assign(res
, binop(op2
,
4484 Q
? getQReg(dreg
) : getDRegI64(dreg
),
4485 binop(op
, mkexpr(arg_n
), mkexpr(arg_m
))));
4486 DIP("vml%c.i%d %c%u, %c%u, %c%u\n",
4487 P
? 's' : 'a', 8 << size
,
4488 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd',
4493 UInt P
= (theInstr
>> 24) & 1;
4497 op
= Q
? Iop_PolynomialMul8x16
: Iop_PolynomialMul8x8
;
4499 case 1: case 2: case 3: return False
;
4500 default: vassert(0);
4504 case 0: op
= Q
? Iop_Mul8x16
: Iop_Mul8x8
; break;
4505 case 1: op
= Q
? Iop_Mul16x8
: Iop_Mul16x4
; break;
4506 case 2: op
= Q
? Iop_Mul32x4
: Iop_Mul32x2
; break;
4507 case 3: return False
;
4508 default: vassert(0);
4511 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4512 DIP("vmul.%c%d %c%u, %c%u, %c%u\n",
4513 P
? 'p' : 'i', 8 << size
,
4514 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd',
4520 UInt P
= (theInstr
>> 4) & 1;
4526 case 0: op
= U
? Iop_PwMin8Ux8
: Iop_PwMin8Sx8
; break;
4527 case 1: op
= U
? Iop_PwMin16Ux4
: Iop_PwMin16Sx4
; break;
4528 case 2: op
= U
? Iop_PwMin32Ux2
: Iop_PwMin32Sx2
; break;
4529 case 3: return False
;
4530 default: vassert(0);
4534 case 0: op
= U
? Iop_PwMax8Ux8
: Iop_PwMax8Sx8
; break;
4535 case 1: op
= U
? Iop_PwMax16Ux4
: Iop_PwMax16Sx4
; break;
4536 case 2: op
= U
? Iop_PwMax32Ux2
: Iop_PwMax32Sx2
; break;
4537 case 3: return False
;
4538 default: vassert(0);
4541 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4542 DIP("vp%s.%c%d %c%u, %c%u, %c%u\n",
4543 P
? "min" : "max", U
? 'u' : 's',
4544 8 << size
, Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
,
4545 Q
? 'q' : 'd', mreg
);
4558 op
= Q
? Iop_QDMulHi16Sx8
: Iop_QDMulHi16Sx4
;
4559 op2
= Q
? Iop_CmpEQ16x8
: Iop_CmpEQ16x4
;
4561 imm
= (imm
<< 16) | imm
;
4562 imm
= (imm
<< 32) | imm
;
4565 op
= Q
? Iop_QDMulHi32Sx4
: Iop_QDMulHi32Sx2
;
4566 op2
= Q
? Iop_CmpEQ32x4
: Iop_CmpEQ32x2
;
4568 imm
= (imm
<< 32) | imm
;
4573 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4574 setFlag_QC(binop(Q
? Iop_AndV128
: Iop_And64
,
4575 binop(op2
, mkexpr(arg_n
),
4576 Q
? mkU128(imm
) : mkU64(imm
)),
4577 binop(op2
, mkexpr(arg_m
),
4578 Q
? mkU128(imm
) : mkU64(imm
))),
4579 Q
? mkU128(0) : mkU64(0),
4581 DIP("vqdmulh.s%d %c%u, %c%u, %c%u\n",
4582 8 << size
, Q
? 'q' : 'd',
4583 dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4593 imm
= (imm
<< 16) | imm
;
4594 imm
= (imm
<< 32) | imm
;
4595 op
= Q
? Iop_QRDMulHi16Sx8
: Iop_QRDMulHi16Sx4
;
4596 op2
= Q
? Iop_CmpEQ16x8
: Iop_CmpEQ16x4
;
4600 imm
= (imm
<< 32) | imm
;
4601 op
= Q
? Iop_QRDMulHi32Sx4
: Iop_QRDMulHi32Sx2
;
4602 op2
= Q
? Iop_CmpEQ32x4
: Iop_CmpEQ32x2
;
4607 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4608 setFlag_QC(binop(Q
? Iop_AndV128
: Iop_And64
,
4609 binop(op2
, mkexpr(arg_n
),
4610 Q
? mkU128(imm
) : mkU64(imm
)),
4611 binop(op2
, mkexpr(arg_m
),
4612 Q
? mkU128(imm
) : mkU64(imm
))),
4613 Q
? mkU128(0) : mkU64(0),
4615 DIP("vqrdmulh.s%d %c%u, %c%u, %c%u\n",
4616 8 << size
, Q
? 'q' : 'd',
4617 dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4626 case 0: op
= Q
? Iop_PwAdd8x16
: Iop_PwAdd8x8
; break;
4627 case 1: op
= Q
? Iop_PwAdd16x8
: Iop_PwAdd16x4
; break;
4628 case 2: op
= Q
? Iop_PwAdd32x4
: Iop_PwAdd32x2
; break;
4629 case 3: return False
;
4630 default: vassert(0);
4632 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4633 DIP("vpadd.i%d %c%u, %c%u, %c%u\n",
4634 8 << size
, Q
? 'q' : 'd',
4635 dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4644 /* Starting from here these are FP SIMD cases */
4649 if ((C
>> 1) == 0) {
4651 op
= Q
? Iop_Add32Fx4
: Iop_Add32Fx2
;
4652 DIP("vadd.f32 %c%u, %c%u, %c%u\n",
4653 Q
? 'q' : 'd', dreg
,
4654 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4657 op
= Q
? Iop_Sub32Fx4
: Iop_Sub32Fx2
;
4658 DIP("vsub.f32 %c%u, %c%u, %c%u\n",
4659 Q
? 'q' : 'd', dreg
,
4660 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4663 if ((C
>> 1) == 0) {
4667 op
= Iop_PwAdd32Fx2
;
4668 DIP("vpadd.f32 d%u, d%u, d%u\n", dreg
, nreg
, mreg
);
4672 assign(res
, unop(Iop_Abs32Fx4
,
4674 get_FAKE_roundingmode(),
4678 assign(res
, unop(Iop_Abs32Fx2
,
4683 DIP("vabd.f32 %c%u, %c%u, %c%u\n",
4684 Q
? 'q' : 'd', dreg
,
4685 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4689 assign(res
, binop_w_fake_RM(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4694 UInt P
= (theInstr
>> 21) & 1;
4698 op
= Q
? Iop_Mul32Fx4
: Iop_Mul32Fx2
;
4699 op2
= Q
? Iop_Sub32Fx4
: Iop_Sub32Fx2
;
4701 case 1: return False
;
4702 default: vassert(0);
4707 op
= Q
? Iop_Mul32Fx4
: Iop_Mul32Fx2
;
4708 op2
= Q
? Iop_Add32Fx4
: Iop_Add32Fx2
;
4710 case 1: return False
;
4711 default: vassert(0);
4714 assign(res
, binop_w_fake_RM(
4716 Q
? getQReg(dreg
) : getDRegI64(dreg
),
4717 binop_w_fake_RM(op
, mkexpr(arg_n
),
4720 DIP("vml%c.f32 %c%u, %c%u, %c%u\n",
4721 P
? 's' : 'a', Q
? 'q' : 'd',
4722 dreg
, Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4728 op
= Q
? Iop_Mul32Fx4
: Iop_Mul32Fx2
;
4729 assign(res
, binop_w_fake_RM(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4730 DIP("vmul.f32 %c%u, %c%u, %c%u\n",
4731 Q
? 'q' : 'd', dreg
,
4732 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4739 if ((C
>> 1) == 0) {
4742 if ((theInstr
>> 20) & 1)
4744 op
= Q
? Iop_CmpEQ32Fx4
: Iop_CmpEQ32Fx2
;
4745 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4746 DIP("vceq.f32 %c%u, %c%u, %c%u\n",
4747 Q
? 'q' : 'd', dreg
,
4748 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4753 if ((C
>> 1) == 0) {
4756 if ((theInstr
>> 20) & 1)
4758 op
= Q
? Iop_CmpGE32Fx4
: Iop_CmpGE32Fx2
;
4759 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4760 DIP("vcge.f32 %c%u, %c%u, %c%u\n",
4761 Q
? 'q' : 'd', dreg
,
4762 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4766 if ((theInstr
>> 20) & 1)
4768 op
= Q
? Iop_CmpGT32Fx4
: Iop_CmpGT32Fx2
;
4769 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4770 DIP("vcgt.f32 %c%u, %c%u, %c%u\n",
4771 Q
? 'q' : 'd', dreg
,
4772 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4778 UInt op_bit
= (theInstr
>> 21) & 1;
4780 op2
= Q
? Iop_Abs32Fx4
: Iop_Abs32Fx2
;
4782 op
= Q
? Iop_CmpGT32Fx4
: Iop_CmpGT32Fx2
;
4783 assign(res
, binop(op
,
4784 unop(op2
, mkexpr(arg_n
)),
4785 unop(op2
, mkexpr(arg_m
))));
4787 op
= Q
? Iop_CmpGE32Fx4
: Iop_CmpGE32Fx2
;
4788 assign(res
, binop(op
,
4789 unop(op2
, mkexpr(arg_n
)),
4790 unop(op2
, mkexpr(arg_m
))));
4792 DIP("vacg%c.f32 %c%u, %c%u, %c%u\n", op_bit
? 't' : 'e',
4793 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
,
4794 Q
? 'q' : 'd', mreg
);
4805 if ((theInstr
>> 20) & 1)
4807 if ((theInstr
>> 21) & 1) {
4808 op
= Q
? Iop_Min32Fx4
: Iop_Min32Fx2
;
4809 DIP("vmin.f32 %c%u, %c%u, %c%u\n", Q
? 'q' : 'd', dreg
,
4810 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4812 op
= Q
? Iop_Max32Fx4
: Iop_Max32Fx2
;
4813 DIP("vmax.f32 %c%u, %c%u, %c%u\n", Q
? 'q' : 'd', dreg
,
4814 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4816 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4822 if ((theInstr
>> 20) & 1)
4824 if ((theInstr
>> 21) & 1) {
4825 op
= Iop_PwMin32Fx2
;
4826 DIP("vpmin.f32 d%u, d%u, d%u\n", dreg
, nreg
, mreg
);
4828 op
= Iop_PwMax32Fx2
;
4829 DIP("vpmax.f32 d%u, d%u, d%u\n", dreg
, nreg
, mreg
);
4831 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
4835 if ((C
>> 1) == 0) {
4837 if ((theInstr
>> 20) & 1)
4839 assign(res
, binop(Q
? Iop_RecipStep32Fx4
4840 : Iop_RecipStep32Fx2
,
4843 DIP("vrecps.f32 %c%u, %c%u, %c%u\n", Q
? 'q' : 'd', dreg
,
4844 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4847 if ((theInstr
>> 20) & 1)
4849 assign(res
, binop(Q
? Iop_RSqrtStep32Fx4
4850 : Iop_RSqrtStep32Fx2
,
4853 DIP("vrsqrts.f32 %c%u, %c%u, %c%u\n", Q
? 'q' : 'd', dreg
,
4854 Q
? 'q' : 'd', nreg
, Q
? 'q' : 'd', mreg
);
4867 putQReg(dreg
, mkexpr(res
), condT
);
4869 putDRegI64(dreg
, mkexpr(res
), condT
);
4875 /* A7.4.2 Three registers of different length */
4877 Bool
dis_neon_data_3diff ( UInt theInstr
, IRTemp condT
)
4879 /* In paths where this returns False, indicating a non-decodable
4880 instruction, there may still be some IR assignments to temporaries
4881 generated. This is inconvenient but harmless, and the post-front-end
4882 IR optimisation pass will just remove them anyway. So there's no
4883 effort made here to tidy it up.
4885 UInt A
= (theInstr
>> 8) & 0xf;
4886 UInt B
= (theInstr
>> 20) & 3;
4887 UInt U
= (theInstr
>> 24) & 1;
4888 UInt P
= (theInstr
>> 9) & 1;
4889 UInt mreg
= get_neon_m_regno(theInstr
);
4890 UInt nreg
= get_neon_n_regno(theInstr
);
4891 UInt dreg
= get_neon_d_regno(theInstr
);
4894 IRTemp res
, arg_m
, arg_n
, cond
, tmp
;
4895 IROp cvt
, cvt2
, cmp
, op
, op2
, sh
, add
;
4897 case 0: case 1: case 2: case 3:
4898 /* VADDL, VADDW, VSUBL, VSUBW */
4905 cvt
= U
? Iop_Widen8Uto16x8
: Iop_Widen8Sto16x8
;
4906 op
= (A
& 2) ? Iop_Sub16x8
: Iop_Add16x8
;
4909 cvt
= U
? Iop_Widen16Uto32x4
: Iop_Widen16Sto32x4
;
4910 op
= (A
& 2) ? Iop_Sub32x4
: Iop_Add32x4
;
4913 cvt
= U
? Iop_Widen32Uto64x2
: Iop_Widen32Sto64x2
;
4914 op
= (A
& 2) ? Iop_Sub64x2
: Iop_Add64x2
;
4921 arg_n
= newTemp(Ity_V128
);
4922 arg_m
= newTemp(Ity_V128
);
4927 assign(arg_n
, getQReg(nreg
));
4929 assign(arg_n
, unop(cvt
, getDRegI64(nreg
)));
4931 assign(arg_m
, unop(cvt
, getDRegI64(mreg
)));
4932 putQReg(dreg
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)),
4934 DIP("v%s%c.%c%d q%u, %c%u, d%u\n", (A
& 2) ? "sub" : "add",
4935 (A
& 1) ? 'w' : 'l', U
? 'u' : 's', 8 << size
, dreg
,
4936 (A
& 1) ? 'q' : 'd', nreg
, mreg
);
4939 /* VADDHN, VRADDHN */
4950 cvt
= Iop_NarrowUn16to8x8
;
4953 imm
= (imm
<< 16) | imm
;
4954 imm
= (imm
<< 32) | imm
;
4958 cvt
= Iop_NarrowUn32to16x4
;
4961 imm
= (imm
<< 32) | imm
;
4965 cvt
= Iop_NarrowUn64to32x2
;
4974 tmp
= newTemp(Ity_V128
);
4975 res
= newTemp(Ity_V128
);
4976 assign(tmp
, binop(op
, getQReg(nreg
), getQReg(mreg
)));
4979 assign(res
, binop(op
, mkexpr(tmp
),
4980 binop(Iop_64HLtoV128
, mkU64(imm
), mkU64(imm
))));
4982 assign(res
, mkexpr(tmp
));
4984 putDRegI64(dreg
, unop(cvt
, binop(sh
, mkexpr(res
), mkU8(8 << size
))),
4986 DIP("v%saddhn.i%d d%u, q%u, q%u\n", U
? "r" : "", 16 << size
, dreg
,
4991 if (!((theInstr
>> 23) & 1)) {
4992 vpanic("VABA should not be in dis_neon_data_3diff\n");
4999 cmp
= U
? Iop_CmpGT8Ux8
: Iop_CmpGT8Sx8
;
5000 cvt
= U
? Iop_Widen8Uto16x8
: Iop_Widen8Sto16x8
;
5001 cvt2
= Iop_Widen8Sto16x8
;
5006 cmp
= U
? Iop_CmpGT16Ux4
: Iop_CmpGT16Sx4
;
5007 cvt
= U
? Iop_Widen16Uto32x4
: Iop_Widen16Sto32x4
;
5008 cvt2
= Iop_Widen16Sto32x4
;
5013 cmp
= U
? Iop_CmpGT32Ux2
: Iop_CmpGT32Sx2
;
5014 cvt
= U
? Iop_Widen32Uto64x2
: Iop_Widen32Sto64x2
;
5015 cvt2
= Iop_Widen32Sto64x2
;
5024 arg_n
= newTemp(Ity_V128
);
5025 arg_m
= newTemp(Ity_V128
);
5026 cond
= newTemp(Ity_V128
);
5027 res
= newTemp(Ity_V128
);
5028 assign(arg_n
, unop(cvt
, getDRegI64(nreg
)));
5029 assign(arg_m
, unop(cvt
, getDRegI64(mreg
)));
5030 assign(cond
, unop(cvt2
, binop(cmp
, getDRegI64(nreg
),
5031 getDRegI64(mreg
))));
5032 assign(res
, binop(op2
,
5035 binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)),
5038 binop(op
, mkexpr(arg_m
), mkexpr(arg_n
)),
5039 unop(Iop_NotV128
, mkexpr(cond
)))),
5041 putQReg(dreg
, mkexpr(res
), condT
);
5042 DIP("vabal.%c%d q%u, d%u, d%u\n", U
? 'u' : 's', 8 << size
, dreg
,
5046 /* VSUBHN, VRSUBHN */
5058 cvt
= Iop_NarrowUn16to8x8
;
5061 imm
= (imm
<< 16) | imm
;
5062 imm
= (imm
<< 32) | imm
;
5067 cvt
= Iop_NarrowUn32to16x4
;
5070 imm
= (imm
<< 32) | imm
;
5075 cvt
= Iop_NarrowUn64to32x2
;
5084 tmp
= newTemp(Ity_V128
);
5085 res
= newTemp(Ity_V128
);
5086 assign(tmp
, binop(op
, getQReg(nreg
), getQReg(mreg
)));
5089 assign(res
, binop(op2
, mkexpr(tmp
),
5090 binop(Iop_64HLtoV128
, mkU64(imm
), mkU64(imm
))));
5092 assign(res
, mkexpr(tmp
));
5094 putDRegI64(dreg
, unop(cvt
, binop(sh
, mkexpr(res
), mkU8(8 << size
))),
5096 DIP("v%ssubhn.i%d d%u, q%u, q%u\n", U
? "r" : "", 16 << size
, dreg
,
5101 if (!((theInstr
>> 23) & 1)) {
5102 vpanic("VABL should not be in dis_neon_data_3diff\n");
5109 cmp
= U
? Iop_CmpGT8Ux8
: Iop_CmpGT8Sx8
;
5110 cvt
= U
? Iop_Widen8Uto16x8
: Iop_Widen8Sto16x8
;
5111 cvt2
= Iop_Widen8Sto16x8
;
5115 cmp
= U
? Iop_CmpGT16Ux4
: Iop_CmpGT16Sx4
;
5116 cvt
= U
? Iop_Widen16Uto32x4
: Iop_Widen16Sto32x4
;
5117 cvt2
= Iop_Widen16Sto32x4
;
5121 cmp
= U
? Iop_CmpGT32Ux2
: Iop_CmpGT32Sx2
;
5122 cvt
= U
? Iop_Widen32Uto64x2
: Iop_Widen32Sto64x2
;
5123 cvt2
= Iop_Widen32Sto64x2
;
5131 arg_n
= newTemp(Ity_V128
);
5132 arg_m
= newTemp(Ity_V128
);
5133 cond
= newTemp(Ity_V128
);
5134 res
= newTemp(Ity_V128
);
5135 assign(arg_n
, unop(cvt
, getDRegI64(nreg
)));
5136 assign(arg_m
, unop(cvt
, getDRegI64(mreg
)));
5137 assign(cond
, unop(cvt2
, binop(cmp
, getDRegI64(nreg
),
5138 getDRegI64(mreg
))));
5139 assign(res
, binop(Iop_OrV128
,
5141 binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)),
5144 binop(op
, mkexpr(arg_m
), mkexpr(arg_n
)),
5145 unop(Iop_NotV128
, mkexpr(cond
)))));
5146 putQReg(dreg
, mkexpr(res
), condT
);
5147 DIP("vabdl.%c%d q%u, d%u, d%u\n", U
? 'u' : 's', 8 << size
, dreg
,
5152 /* VMLAL, VMLSL (integer) */
5159 op
= U
? Iop_Mull8Ux8
: Iop_Mull8Sx8
;
5160 op2
= P
? Iop_Sub16x8
: Iop_Add16x8
;
5163 op
= U
? Iop_Mull16Ux4
: Iop_Mull16Sx4
;
5164 op2
= P
? Iop_Sub32x4
: Iop_Add32x4
;
5167 op
= U
? Iop_Mull32Ux2
: Iop_Mull32Sx2
;
5168 op2
= P
? Iop_Sub64x2
: Iop_Add64x2
;
5175 res
= newTemp(Ity_V128
);
5176 assign(res
, binop(op
, getDRegI64(nreg
),getDRegI64(mreg
)));
5177 putQReg(dreg
, binop(op2
, getQReg(dreg
), mkexpr(res
)), condT
);
5178 DIP("vml%cl.%c%d q%u, d%u, d%u\n", P
? 's' : 'a', U
? 'u' : 's',
5179 8 << size
, dreg
, nreg
, mreg
);
5183 /* VQDMLAL, VQDMLSL */
5194 op
= Iop_QDMull16Sx4
;
5195 cmp
= Iop_CmpEQ16x4
;
5196 add
= P
? Iop_QSub32Sx4
: Iop_QAdd32Sx4
;
5197 op2
= P
? Iop_Sub32x4
: Iop_Add32x4
;
5199 imm
= (imm
<< 16) | imm
;
5200 imm
= (imm
<< 32) | imm
;
5203 op
= Iop_QDMull32Sx2
;
5204 cmp
= Iop_CmpEQ32x2
;
5205 add
= P
? Iop_QSub64Sx2
: Iop_QAdd64Sx2
;
5206 op2
= P
? Iop_Sub64x2
: Iop_Add64x2
;
5208 imm
= (imm
<< 32) | imm
;
5213 res
= newTemp(Ity_V128
);
5214 tmp
= newTemp(Ity_V128
);
5215 assign(res
, binop(op
, getDRegI64(nreg
), getDRegI64(mreg
)));
5216 assign(tmp
, binop(op2
, getQReg(dreg
), mkexpr(res
)));
5217 setFlag_QC(mkexpr(tmp
), binop(add
, getQReg(dreg
), mkexpr(res
)),
5219 setFlag_QC(binop(Iop_And64
,
5220 binop(cmp
, getDRegI64(nreg
), mkU64(imm
)),
5221 binop(cmp
, getDRegI64(mreg
), mkU64(imm
))),
5224 putQReg(dreg
, binop(add
, getQReg(dreg
), mkexpr(res
)), condT
);
5225 DIP("vqdml%cl.s%d q%u, d%u, d%u\n", P
? 's' : 'a', 8 << size
, dreg
,
5230 /* VMULL (integer or polynomial) */
5237 op
= (U
) ? Iop_Mull8Ux8
: Iop_Mull8Sx8
;
5239 op
= Iop_PolynomialMull8x8
;
5242 if (P
) return False
;
5243 op
= (U
) ? Iop_Mull16Ux4
: Iop_Mull16Sx4
;
5246 if (P
) return False
;
5247 op
= (U
) ? Iop_Mull32Ux2
: Iop_Mull32Sx2
;
5254 putQReg(dreg
, binop(op
, getDRegI64(nreg
),
5255 getDRegI64(mreg
)), condT
);
5256 DIP("vmull.%c%d q%u, d%u, d%u\n", P
? 'p' : (U
? 'u' : 's'),
5257 8 << size
, dreg
, nreg
, mreg
);
5272 op
= Iop_QDMull16Sx4
;
5273 op2
= Iop_CmpEQ16x4
;
5275 imm
= (imm
<< 16) | imm
;
5276 imm
= (imm
<< 32) | imm
;
5279 op
= Iop_QDMull32Sx2
;
5280 op2
= Iop_CmpEQ32x2
;
5282 imm
= (imm
<< 32) | imm
;
5287 putQReg(dreg
, binop(op
, getDRegI64(nreg
), getDRegI64(mreg
)),
5289 setFlag_QC(binop(Iop_And64
,
5290 binop(op2
, getDRegI64(nreg
), mkU64(imm
)),
5291 binop(op2
, getDRegI64(mreg
), mkU64(imm
))),
5294 DIP("vqdmull.s%d q%u, d%u, d%u\n", 8 << size
, dreg
, nreg
, mreg
);
5302 /* A7.4.3 Two registers and a scalar */
5304 Bool
dis_neon_data_2reg_and_scalar ( UInt theInstr
, IRTemp condT
)
5306 # define INSN(_bMax,_bMin) SLICE_UInt(theInstr, (_bMax), (_bMin))
5307 UInt U
= INSN(24,24);
5308 UInt dreg
= get_neon_d_regno(theInstr
& ~(1 << 6));
5309 UInt nreg
= get_neon_n_regno(theInstr
& ~(1 << 6));
5310 UInt mreg
= get_neon_m_regno(theInstr
& ~(1 << 6));
5311 UInt size
= INSN(21,20);
5313 UInt Q
= INSN(24,24);
5315 if (INSN(27,25) != 1 || INSN(23,23) != 1
5316 || INSN(6,6) != 1 || INSN(4,4) != 0)
5319 /* VMLA, VMLS (scalar) */
5320 if ((INSN(11,8) & BITS4(1,0,1,0)) == BITS4(0,0,0,0)) {
5321 IRTemp res
, arg_m
, arg_n
;
5322 IROp dup
, get
, op
, op2
, add
, sub
;
5324 if ((dreg
& 1) || (nreg
& 1))
5328 res
= newTemp(Ity_V128
);
5329 arg_m
= newTemp(Ity_V128
);
5330 arg_n
= newTemp(Ity_V128
);
5331 assign(arg_n
, getQReg(nreg
));
5335 get
= Iop_GetElem16x4
;
5341 get
= Iop_GetElem32x2
;
5351 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5353 res
= newTemp(Ity_I64
);
5354 arg_m
= newTemp(Ity_I64
);
5355 arg_n
= newTemp(Ity_I64
);
5356 assign(arg_n
, getDRegI64(nreg
));
5360 get
= Iop_GetElem16x4
;
5366 get
= Iop_GetElem32x2
;
5376 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5381 op
= Q
? Iop_Mul32Fx4
: Iop_Mul32Fx2
;
5382 add
= Q
? Iop_Add32Fx4
: Iop_Add32Fx2
;
5383 sub
= Q
? Iop_Sub32Fx4
: Iop_Sub32Fx2
;
5395 op
= Q
? Iop_Mul16x8
: Iop_Mul16x4
;
5396 add
= Q
? Iop_Add16x8
: Iop_Add16x4
;
5397 sub
= Q
? Iop_Sub16x8
: Iop_Sub16x4
;
5400 op
= Q
? Iop_Mul32x4
: Iop_Mul32x2
;
5401 add
= Q
? Iop_Add32x4
: Iop_Add32x2
;
5402 sub
= Q
? Iop_Sub32x4
: Iop_Sub32x2
;
5411 op2
= INSN(10,10) ? sub
: add
;
5412 assign(res
, binop_w_fake_RM(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
5414 putQReg(dreg
, binop_w_fake_RM(op2
, getQReg(dreg
), mkexpr(res
)),
5417 putDRegI64(dreg
, binop(op2
, getDRegI64(dreg
), mkexpr(res
)),
5419 DIP("vml%c.%c%d %c%u, %c%u, d%u[%u]\n", INSN(10,10) ? 's' : 'a',
5420 INSN(8,8) ? 'f' : 'i', 8 << size
,
5421 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', nreg
, mreg
, index
);
5425 /* VMLAL, VMLSL (scalar) */
5426 if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,0)) {
5427 IRTemp res
, arg_m
, arg_n
;
5428 IROp dup
, get
, op
, op2
, add
, sub
;
5432 res
= newTemp(Ity_V128
);
5433 arg_m
= newTemp(Ity_I64
);
5434 arg_n
= newTemp(Ity_I64
);
5435 assign(arg_n
, getDRegI64(nreg
));
5439 get
= Iop_GetElem16x4
;
5445 get
= Iop_GetElem32x2
;
5455 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5458 op
= U
? Iop_Mull16Ux4
: Iop_Mull16Sx4
;
5463 op
= U
? Iop_Mull32Ux2
: Iop_Mull32Sx2
;
5473 op2
= INSN(10,10) ? sub
: add
;
5474 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
5475 putQReg(dreg
, binop(op2
, getQReg(dreg
), mkexpr(res
)), condT
);
5476 DIP("vml%cl.%c%d q%u, d%u, d%u[%u]\n",
5477 INSN(10,10) ? 's' : 'a', U
? 'u' : 's',
5478 8 << size
, dreg
, nreg
, mreg
, index
);
5482 /* VQDMLAL, VQDMLSL (scalar) */
5483 if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,1) && !U
) {
5484 IRTemp res
, arg_m
, arg_n
, tmp
;
5485 IROp dup
, get
, op
, op2
, add
, cmp
;
5486 UInt P
= INSN(10,10);
5491 res
= newTemp(Ity_V128
);
5492 arg_m
= newTemp(Ity_I64
);
5493 arg_n
= newTemp(Ity_I64
);
5494 assign(arg_n
, getDRegI64(nreg
));
5498 get
= Iop_GetElem16x4
;
5504 get
= Iop_GetElem32x2
;
5514 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5520 op
= Iop_QDMull16Sx4
;
5521 cmp
= Iop_CmpEQ16x4
;
5522 add
= P
? Iop_QSub32Sx4
: Iop_QAdd32Sx4
;
5523 op2
= P
? Iop_Sub32x4
: Iop_Add32x4
;
5525 imm
= (imm
<< 16) | imm
;
5526 imm
= (imm
<< 32) | imm
;
5529 op
= Iop_QDMull32Sx2
;
5530 cmp
= Iop_CmpEQ32x2
;
5531 add
= P
? Iop_QSub64Sx2
: Iop_QAdd64Sx2
;
5532 op2
= P
? Iop_Sub64x2
: Iop_Add64x2
;
5534 imm
= (imm
<< 32) | imm
;
5539 res
= newTemp(Ity_V128
);
5540 tmp
= newTemp(Ity_V128
);
5541 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
5542 assign(tmp
, binop(op2
, getQReg(dreg
), mkexpr(res
)));
5543 setFlag_QC(binop(Iop_And64
,
5544 binop(cmp
, mkexpr(arg_n
), mkU64(imm
)),
5545 binop(cmp
, mkexpr(arg_m
), mkU64(imm
))),
5548 setFlag_QC(mkexpr(tmp
), binop(add
, getQReg(dreg
), mkexpr(res
)),
5550 putQReg(dreg
, binop(add
, getQReg(dreg
), mkexpr(res
)), condT
);
5551 DIP("vqdml%cl.s%d q%u, d%u, d%u[%u]\n", P
? 's' : 'a', 8 << size
,
5552 dreg
, nreg
, mreg
, index
);
5556 /* VMUL (by scalar) */
5557 if ((INSN(11,8) & BITS4(1,1,1,0)) == BITS4(1,0,0,0)) {
5558 IRTemp res
, arg_m
, arg_n
;
5561 if ((dreg
& 1) || (nreg
& 1))
5565 res
= newTemp(Ity_V128
);
5566 arg_m
= newTemp(Ity_V128
);
5567 arg_n
= newTemp(Ity_V128
);
5568 assign(arg_n
, getQReg(nreg
));
5572 get
= Iop_GetElem16x4
;
5578 get
= Iop_GetElem32x2
;
5588 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5590 res
= newTemp(Ity_I64
);
5591 arg_m
= newTemp(Ity_I64
);
5592 arg_n
= newTemp(Ity_I64
);
5593 assign(arg_n
, getDRegI64(nreg
));
5597 get
= Iop_GetElem16x4
;
5603 get
= Iop_GetElem32x2
;
5613 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5618 op
= Q
? Iop_Mul32Fx4
: Iop_Mul32Fx2
;
5630 op
= Q
? Iop_Mul16x8
: Iop_Mul16x4
;
5633 op
= Q
? Iop_Mul32x4
: Iop_Mul32x2
;
5642 assign(res
, binop_w_fake_RM(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
5644 putQReg(dreg
, mkexpr(res
), condT
);
5646 putDRegI64(dreg
, mkexpr(res
), condT
);
5647 DIP("vmul.%c%d %c%u, %c%u, d%u[%u]\n", INSN(8,8) ? 'f' : 'i',
5648 8 << size
, Q
? 'q' : 'd', dreg
,
5649 Q
? 'q' : 'd', nreg
, mreg
, index
);
5653 /* VMULL (scalar) */
5654 if (INSN(11,8) == BITS4(1,0,1,0)) {
5655 IRTemp res
, arg_m
, arg_n
;
5660 res
= newTemp(Ity_V128
);
5661 arg_m
= newTemp(Ity_I64
);
5662 arg_n
= newTemp(Ity_I64
);
5663 assign(arg_n
, getDRegI64(nreg
));
5667 get
= Iop_GetElem16x4
;
5673 get
= Iop_GetElem32x2
;
5683 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5685 case 1: op
= U
? Iop_Mull16Ux4
: Iop_Mull16Sx4
; break;
5686 case 2: op
= U
? Iop_Mull32Ux2
: Iop_Mull32Sx2
; break;
5687 case 0: case 3: return False
;
5688 default: vassert(0);
5690 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
5691 putQReg(dreg
, mkexpr(res
), condT
);
5692 DIP("vmull.%c%d q%u, d%u, d%u[%u]\n", U
? 'u' : 's', 8 << size
, dreg
,
5698 if (INSN(11,8) == BITS4(1,0,1,1) && !U
) {
5699 IROp op
,op2
, dup
, get
;
5701 IRTemp arg_m
, arg_n
;
5705 arg_m
= newTemp(Ity_I64
);
5706 arg_n
= newTemp(Ity_I64
);
5707 assign(arg_n
, getDRegI64(nreg
));
5711 get
= Iop_GetElem16x4
;
5717 get
= Iop_GetElem32x2
;
5727 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5733 op
= Iop_QDMull16Sx4
;
5734 op2
= Iop_CmpEQ16x4
;
5736 imm
= (imm
<< 16) | imm
;
5737 imm
= (imm
<< 32) | imm
;
5740 op
= Iop_QDMull32Sx2
;
5741 op2
= Iop_CmpEQ32x2
;
5743 imm
= (imm
<< 32) | imm
;
5748 putQReg(dreg
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)),
5750 setFlag_QC(binop(Iop_And64
,
5751 binop(op2
, mkexpr(arg_n
), mkU64(imm
)),
5752 binop(op2
, mkexpr(arg_m
), mkU64(imm
))),
5755 DIP("vqdmull.s%d q%u, d%u, d%u[%u]\n", 8 << size
, dreg
, nreg
, mreg
,
5761 if (INSN(11,8) == BITS4(1,1,0,0)) {
5762 IROp op
,op2
, dup
, get
;
5764 IRTemp res
, arg_m
, arg_n
;
5766 if ((dreg
& 1) || (nreg
& 1))
5770 res
= newTemp(Ity_V128
);
5771 arg_m
= newTemp(Ity_V128
);
5772 arg_n
= newTemp(Ity_V128
);
5773 assign(arg_n
, getQReg(nreg
));
5777 get
= Iop_GetElem16x4
;
5783 get
= Iop_GetElem32x2
;
5793 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5795 res
= newTemp(Ity_I64
);
5796 arg_m
= newTemp(Ity_I64
);
5797 arg_n
= newTemp(Ity_I64
);
5798 assign(arg_n
, getDRegI64(nreg
));
5802 get
= Iop_GetElem16x4
;
5808 get
= Iop_GetElem32x2
;
5818 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5825 op
= Q
? Iop_QDMulHi16Sx8
: Iop_QDMulHi16Sx4
;
5826 op2
= Q
? Iop_CmpEQ16x8
: Iop_CmpEQ16x4
;
5828 imm
= (imm
<< 16) | imm
;
5829 imm
= (imm
<< 32) | imm
;
5832 op
= Q
? Iop_QDMulHi32Sx4
: Iop_QDMulHi32Sx2
;
5833 op2
= Q
? Iop_CmpEQ32x4
: Iop_CmpEQ32x2
;
5835 imm
= (imm
<< 32) | imm
;
5840 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
5841 setFlag_QC(binop(Q
? Iop_AndV128
: Iop_And64
,
5842 binop(op2
, mkexpr(arg_n
),
5843 Q
? mkU128(imm
) : mkU64(imm
)),
5844 binop(op2
, mkexpr(arg_m
),
5845 Q
? mkU128(imm
) : mkU64(imm
))),
5846 Q
? mkU128(0) : mkU64(0),
5849 putQReg(dreg
, mkexpr(res
), condT
);
5851 putDRegI64(dreg
, mkexpr(res
), condT
);
5852 DIP("vqdmulh.s%d %c%u, %c%u, d%u[%u]\n",
5853 8 << size
, Q
? 'q' : 'd', dreg
,
5854 Q
? 'q' : 'd', nreg
, mreg
, index
);
5858 /* VQRDMULH (scalar) */
5859 if (INSN(11,8) == BITS4(1,1,0,1)) {
5860 IROp op
,op2
, dup
, get
;
5862 IRTemp res
, arg_m
, arg_n
;
5864 if ((dreg
& 1) || (nreg
& 1))
5868 res
= newTemp(Ity_V128
);
5869 arg_m
= newTemp(Ity_V128
);
5870 arg_n
= newTemp(Ity_V128
);
5871 assign(arg_n
, getQReg(nreg
));
5875 get
= Iop_GetElem16x4
;
5881 get
= Iop_GetElem32x2
;
5891 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5893 res
= newTemp(Ity_I64
);
5894 arg_m
= newTemp(Ity_I64
);
5895 arg_n
= newTemp(Ity_I64
);
5896 assign(arg_n
, getDRegI64(nreg
));
5900 get
= Iop_GetElem16x4
;
5906 get
= Iop_GetElem32x2
;
5916 assign(arg_m
, unop(dup
, binop(get
, getDRegI64(mreg
), mkU8(index
))));
5923 op
= Q
? Iop_QRDMulHi16Sx8
: Iop_QRDMulHi16Sx4
;
5924 op2
= Q
? Iop_CmpEQ16x8
: Iop_CmpEQ16x4
;
5926 imm
= (imm
<< 16) | imm
;
5927 imm
= (imm
<< 32) | imm
;
5930 op
= Q
? Iop_QRDMulHi32Sx4
: Iop_QRDMulHi32Sx2
;
5931 op2
= Q
? Iop_CmpEQ32x4
: Iop_CmpEQ32x2
;
5933 imm
= (imm
<< 32) | imm
;
5938 assign(res
, binop(op
, mkexpr(arg_n
), mkexpr(arg_m
)));
5939 setFlag_QC(binop(Q
? Iop_AndV128
: Iop_And64
,
5940 binop(op2
, mkexpr(arg_n
),
5941 Q
? mkU128(imm
) : mkU64(imm
)),
5942 binop(op2
, mkexpr(arg_m
),
5943 Q
? mkU128(imm
) : mkU64(imm
))),
5944 Q
? mkU128(0) : mkU64(0),
5947 putQReg(dreg
, mkexpr(res
), condT
);
5949 putDRegI64(dreg
, mkexpr(res
), condT
);
5950 DIP("vqrdmulh.s%d %c%u, %c%u, d%u[%u]\n",
5951 8 << size
, Q
? 'q' : 'd', dreg
,
5952 Q
? 'q' : 'd', nreg
, mreg
, index
);
5960 /* A7.4.4 Two registers and a shift amount */
5962 Bool
dis_neon_data_2reg_and_shift ( UInt theInstr
, IRTemp condT
)
5964 UInt A
= (theInstr
>> 8) & 0xf;
5965 UInt B
= (theInstr
>> 6) & 1;
5966 UInt L
= (theInstr
>> 7) & 1;
5967 UInt U
= (theInstr
>> 24) & 1;
5969 UInt imm6
= (theInstr
>> 16) & 0x3f;
5973 UInt mreg
= get_neon_m_regno(theInstr
);
5974 UInt dreg
= get_neon_d_regno(theInstr
);
5976 IROp op
, cvt
, add
= Iop_INVALID
, cvt2
, op_rev
;
5977 IRTemp reg_m
, res
, mask
;
5979 if (L
== 0 && ((theInstr
>> 19) & 7) == 0)
5980 /* It is one reg and immediate */
5983 tmp
= (L
<< 6) | imm6
;
5986 shift_imm
= 64 - imm6
;
5987 } else if (tmp
& 0x20) {
5989 shift_imm
= 64 - imm6
;
5990 } else if (tmp
& 0x10) {
5992 shift_imm
= 32 - imm6
;
5993 } else if (tmp
& 0x8) {
5995 shift_imm
= 16 - imm6
;
6004 if (shift_imm
> 0) {
6009 imm
= (imm
<< 8) | imm
;
6012 imm
= (imm
<< 16) | imm
;
6015 imm
= (imm
<< 32) | imm
;
6023 reg_m
= newTemp(Ity_V128
);
6024 res
= newTemp(Ity_V128
);
6025 imm_val
= binop(Iop_64HLtoV128
, mkU64(imm
), mkU64(imm
));
6026 assign(reg_m
, getQReg(mreg
));
6030 op
= U
? Iop_ShrN8x16
: Iop_SarN8x16
;
6034 op
= U
? Iop_ShrN16x8
: Iop_SarN16x8
;
6038 op
= U
? Iop_ShrN32x4
: Iop_SarN32x4
;
6042 op
= U
? Iop_ShrN64x2
: Iop_SarN64x2
;
6048 reg_m
= newTemp(Ity_I64
);
6049 res
= newTemp(Ity_I64
);
6050 imm_val
= mkU64(imm
);
6051 assign(reg_m
, getDRegI64(mreg
));
6055 op
= U
? Iop_ShrN8x8
: Iop_SarN8x8
;
6059 op
= U
? Iop_ShrN16x4
: Iop_SarN16x4
;
6063 op
= U
? Iop_ShrN32x2
: Iop_SarN32x2
;
6067 op
= U
? Iop_Shr64
: Iop_Sar64
;
6078 binop(Q
? Iop_AndV128
: Iop_And64
,
6081 mkU8(shift_imm
- 1)),
6085 res
= newTemp(Ity_V128
);
6086 assign(res
, getQReg(mreg
));
6088 res
= newTemp(Ity_I64
);
6089 assign(res
, getDRegI64(mreg
));
6094 putQReg(dreg
, binop(add
, mkexpr(res
), getQReg(dreg
)),
6097 putDRegI64(dreg
, binop(add
, mkexpr(res
), getDRegI64(dreg
)),
6100 DIP("vrsra.%c%d %c%u, %c%u, #%u\n",
6101 U
? 'u' : 's', 8 << size
,
6102 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
, shift_imm
);
6105 putQReg(dreg
, mkexpr(res
), condT
);
6107 putDRegI64(dreg
, mkexpr(res
), condT
);
6109 DIP("vrshr.%c%d %c%u, %c%u, #%u\n", U
? 'u' : 's', 8 << size
,
6110 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
, shift_imm
);
6117 reg_m
= newTemp(Ity_V128
);
6118 assign(reg_m
, getQReg(mreg
));
6119 res
= newTemp(Ity_V128
);
6121 reg_m
= newTemp(Ity_I64
);
6122 assign(reg_m
, getDRegI64(mreg
));
6123 res
= newTemp(Ity_I64
);
6128 op
= U
? Iop_ShrN8x16
: Iop_SarN8x16
;
6132 op
= U
? Iop_ShrN16x8
: Iop_SarN16x8
;
6136 op
= U
? Iop_ShrN32x4
: Iop_SarN32x4
;
6140 op
= U
? Iop_ShrN64x2
: Iop_SarN64x2
;
6149 op
= U
? Iop_ShrN8x8
: Iop_SarN8x8
;
6153 op
= U
? Iop_ShrN16x4
: Iop_SarN16x4
;
6157 op
= U
? Iop_ShrN32x2
: Iop_SarN32x2
;
6161 op
= U
? Iop_Shr64
: Iop_Sar64
;
6168 assign(res
, binop(op
, mkexpr(reg_m
), mkU8(shift_imm
)));
6171 putQReg(dreg
, binop(add
, mkexpr(res
), getQReg(dreg
)),
6174 putDRegI64(dreg
, binop(add
, mkexpr(res
), getDRegI64(dreg
)),
6177 DIP("vsra.%c%d %c%u, %c%u, #%u\n", U
? 'u' : 's', 8 << size
,
6178 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
, shift_imm
);
6181 putQReg(dreg
, mkexpr(res
), condT
);
6183 putDRegI64(dreg
, mkexpr(res
), condT
);
6185 DIP("vshr.%c%d %c%u, %c%u, #%u\n", U
? 'u' : 's', 8 << size
,
6186 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
, shift_imm
);
6194 res
= newTemp(Ity_V128
);
6195 mask
= newTemp(Ity_V128
);
6197 res
= newTemp(Ity_I64
);
6198 mask
= newTemp(Ity_I64
);
6201 case 0: op
= Q
? Iop_ShrN8x16
: Iop_ShrN8x8
; break;
6202 case 1: op
= Q
? Iop_ShrN16x8
: Iop_ShrN16x4
; break;
6203 case 2: op
= Q
? Iop_ShrN32x4
: Iop_ShrN32x2
; break;
6204 case 3: op
= Q
? Iop_ShrN64x2
: Iop_Shr64
; break;
6205 default: vassert(0);
6208 assign(mask
, binop(op
, binop(Iop_64HLtoV128
,
6209 mkU64(0xFFFFFFFFFFFFFFFFLL
),
6210 mkU64(0xFFFFFFFFFFFFFFFFLL
)),
6212 assign(res
, binop(Iop_OrV128
,
6220 putQReg(dreg
, mkexpr(res
), condT
);
6222 assign(mask
, binop(op
, mkU64(0xFFFFFFFFFFFFFFFFLL
),
6224 assign(res
, binop(Iop_Or64
,
6232 putDRegI64(dreg
, mkexpr(res
), condT
);
6234 DIP("vsri.%d %c%u, %c%u, #%u\n",
6235 8 << size
, Q
? 'q' : 'd', dreg
,
6236 Q
? 'q' : 'd', mreg
, shift_imm
);
6241 shift_imm
= 8 * (1 << size
) - shift_imm
;
6243 res
= newTemp(Ity_V128
);
6244 mask
= newTemp(Ity_V128
);
6246 res
= newTemp(Ity_I64
);
6247 mask
= newTemp(Ity_I64
);
6250 case 0: op
= Q
? Iop_ShlN8x16
: Iop_ShlN8x8
; break;
6251 case 1: op
= Q
? Iop_ShlN16x8
: Iop_ShlN16x4
; break;
6252 case 2: op
= Q
? Iop_ShlN32x4
: Iop_ShlN32x2
; break;
6253 case 3: op
= Q
? Iop_ShlN64x2
: Iop_Shl64
; break;
6254 default: vassert(0);
6257 assign(mask
, binop(op
, binop(Iop_64HLtoV128
,
6258 mkU64(0xFFFFFFFFFFFFFFFFLL
),
6259 mkU64(0xFFFFFFFFFFFFFFFFLL
)),
6261 assign(res
, binop(Iop_OrV128
,
6269 putQReg(dreg
, mkexpr(res
), condT
);
6271 assign(mask
, binop(op
, mkU64(0xFFFFFFFFFFFFFFFFLL
),
6273 assign(res
, binop(Iop_Or64
,
6281 putDRegI64(dreg
, mkexpr(res
), condT
);
6283 DIP("vsli.%d %c%u, %c%u, #%u\n",
6284 8 << size
, Q
? 'q' : 'd', dreg
,
6285 Q
? 'q' : 'd', mreg
, shift_imm
);
6289 shift_imm
= 8 * (1 << size
) - shift_imm
;
6291 res
= newTemp(Ity_V128
);
6293 res
= newTemp(Ity_I64
);
6296 case 0: op
= Q
? Iop_ShlN8x16
: Iop_ShlN8x8
; break;
6297 case 1: op
= Q
? Iop_ShlN16x8
: Iop_ShlN16x4
; break;
6298 case 2: op
= Q
? Iop_ShlN32x4
: Iop_ShlN32x2
; break;
6299 case 3: op
= Q
? Iop_ShlN64x2
: Iop_Shl64
; break;
6300 default: vassert(0);
6302 assign(res
, binop(op
, Q
? getQReg(mreg
) : getDRegI64(mreg
),
6305 putQReg(dreg
, mkexpr(res
), condT
);
6307 putDRegI64(dreg
, mkexpr(res
), condT
);
6309 DIP("vshl.i%d %c%u, %c%u, #%u\n",
6310 8 << size
, Q
? 'q' : 'd', dreg
,
6311 Q
? 'q' : 'd', mreg
, shift_imm
);
6318 shift_imm
= 8 * (1 << size
) - shift_imm
;
6323 op
= Q
? Iop_QShlNsatUU8x16
: Iop_QShlNsatUU8x8
;
6324 op_rev
= Q
? Iop_ShrN8x16
: Iop_ShrN8x8
;
6327 op
= Q
? Iop_QShlNsatUU16x8
: Iop_QShlNsatUU16x4
;
6328 op_rev
= Q
? Iop_ShrN16x8
: Iop_ShrN16x4
;
6331 op
= Q
? Iop_QShlNsatUU32x4
: Iop_QShlNsatUU32x2
;
6332 op_rev
= Q
? Iop_ShrN32x4
: Iop_ShrN32x2
;
6335 op
= Q
? Iop_QShlNsatUU64x2
: Iop_QShlNsatUU64x1
;
6336 op_rev
= Q
? Iop_ShrN64x2
: Iop_Shr64
;
6341 DIP("vqshl.u%d %c%u, %c%u, #%u\n",
6343 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
, shift_imm
);
6347 op
= Q
? Iop_QShlNsatSU8x16
: Iop_QShlNsatSU8x8
;
6348 op_rev
= Q
? Iop_ShrN8x16
: Iop_ShrN8x8
;
6351 op
= Q
? Iop_QShlNsatSU16x8
: Iop_QShlNsatSU16x4
;
6352 op_rev
= Q
? Iop_ShrN16x8
: Iop_ShrN16x4
;
6355 op
= Q
? Iop_QShlNsatSU32x4
: Iop_QShlNsatSU32x2
;
6356 op_rev
= Q
? Iop_ShrN32x4
: Iop_ShrN32x2
;
6359 op
= Q
? Iop_QShlNsatSU64x2
: Iop_QShlNsatSU64x1
;
6360 op_rev
= Q
? Iop_ShrN64x2
: Iop_Shr64
;
6365 DIP("vqshlu.s%d %c%u, %c%u, #%u\n",
6367 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
, shift_imm
);
6374 op
= Q
? Iop_QShlNsatSS8x16
: Iop_QShlNsatSS8x8
;
6375 op_rev
= Q
? Iop_SarN8x16
: Iop_SarN8x8
;
6378 op
= Q
? Iop_QShlNsatSS16x8
: Iop_QShlNsatSS16x4
;
6379 op_rev
= Q
? Iop_SarN16x8
: Iop_SarN16x4
;
6382 op
= Q
? Iop_QShlNsatSS32x4
: Iop_QShlNsatSS32x2
;
6383 op_rev
= Q
? Iop_SarN32x4
: Iop_SarN32x2
;
6386 op
= Q
? Iop_QShlNsatSS64x2
: Iop_QShlNsatSS64x1
;
6387 op_rev
= Q
? Iop_SarN64x2
: Iop_Sar64
;
6392 DIP("vqshl.s%d %c%u, %c%u, #%u\n",
6394 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
, shift_imm
);
6397 tmp
= newTemp(Ity_V128
);
6398 res
= newTemp(Ity_V128
);
6399 reg_m
= newTemp(Ity_V128
);
6400 assign(reg_m
, getQReg(mreg
));
6402 tmp
= newTemp(Ity_I64
);
6403 res
= newTemp(Ity_I64
);
6404 reg_m
= newTemp(Ity_I64
);
6405 assign(reg_m
, getDRegI64(mreg
));
6407 assign(res
, binop(op
, mkexpr(reg_m
), mkU8(shift_imm
)));
6408 assign(tmp
, binop(op_rev
, mkexpr(res
), mkU8(shift_imm
)));
6409 setFlag_QC(mkexpr(tmp
), mkexpr(reg_m
), Q
, condT
);
6411 putQReg(dreg
, mkexpr(res
), condT
);
6413 putDRegI64(dreg
, mkexpr(res
), condT
);
6420 dreg
= ((theInstr
>> 18) & 0x10) | ((theInstr
>> 12) & 0xF);
6421 mreg
= ((theInstr
>> 1) & 0x10) | (theInstr
& 0xF);
6428 reg_m
= newTemp(Ity_V128
);
6429 assign(reg_m
, getQReg(mreg
));
6430 res
= newTemp(Ity_I64
);
6434 narOp
= Iop_NarrowUn16to8x8
;
6438 narOp
= Iop_NarrowUn32to16x4
;
6442 narOp
= Iop_NarrowUn64to32x2
;
6447 assign(res
, unop(narOp
,
6451 putDRegI64(dreg
, mkexpr(res
), condT
);
6452 DIP("vshrn.i%d d%u, q%u, #%u\n", 8 << size
, dreg
, mreg
,
6457 IROp addOp
, shOp
, narOp
;
6459 reg_m
= newTemp(Ity_V128
);
6460 assign(reg_m
, getQReg(mreg
));
6461 res
= newTemp(Ity_I64
);
6464 case 0: imm
= (imm
<< 8) | imm
; /* fall through */
6465 case 1: imm
= (imm
<< 16) | imm
; /* fall through */
6466 case 2: imm
= (imm
<< 32) | imm
; /* fall through */
6468 default: vassert(0);
6470 imm_val
= binop(Iop_64HLtoV128
, mkU64(imm
), mkU64(imm
));
6473 addOp
= Iop_Add16x8
;
6474 shOp
= Iop_ShrN16x8
;
6475 narOp
= Iop_NarrowUn16to8x8
;
6478 addOp
= Iop_Add32x4
;
6479 shOp
= Iop_ShrN32x4
;
6480 narOp
= Iop_NarrowUn32to16x4
;
6483 addOp
= Iop_Add64x2
;
6484 shOp
= Iop_ShrN64x2
;
6485 narOp
= Iop_NarrowUn64to32x2
;
6490 assign(res
, unop(narOp
,
6498 mkU8(shift_imm
- 1)),
6500 putDRegI64(dreg
, mkexpr(res
), condT
);
6501 if (shift_imm
== 0) {
6502 DIP("vmov%d d%u, q%u, #%u\n", 8 << size
, dreg
, mreg
,
6505 DIP("vrshrn.i%d d%u, q%u, #%u\n", 8 << size
, dreg
, mreg
,
6514 dreg
= ((theInstr
>> 18) & 0x10) | ((theInstr
>> 12) & 0xF);
6515 mreg
= ((theInstr
>> 1) & 0x10) | (theInstr
& 0xF);
6520 if ((theInstr
>> 8) & 1) {
6523 op
= U
? Iop_ShrN16x8
: Iop_SarN16x8
;
6524 cvt
= U
? Iop_QNarrowUn16Uto8Ux8
: Iop_QNarrowUn16Sto8Sx8
;
6525 cvt2
= U
? Iop_Widen8Uto16x8
: Iop_Widen8Sto16x8
;
6528 op
= U
? Iop_ShrN32x4
: Iop_SarN32x4
;
6529 cvt
= U
? Iop_QNarrowUn32Uto16Ux4
: Iop_QNarrowUn32Sto16Sx4
;
6530 cvt2
= U
? Iop_Widen16Uto32x4
: Iop_Widen16Sto32x4
;
6533 op
= U
? Iop_ShrN64x2
: Iop_SarN64x2
;
6534 cvt
= U
? Iop_QNarrowUn64Uto32Ux2
: Iop_QNarrowUn64Sto32Sx2
;
6535 cvt2
= U
? Iop_Widen32Uto64x2
: Iop_Widen32Sto64x2
;
6540 DIP("vq%sshrn.%c%d d%u, q%u, #%u\n", B
? "r" : "",
6541 U
? 'u' : 's', 8 << size
, dreg
, mreg
, shift_imm
);
6547 cvt
= Iop_QNarrowUn16Sto8Ux8
;
6548 cvt2
= Iop_Widen8Uto16x8
;
6552 cvt
= Iop_QNarrowUn32Sto16Ux4
;
6553 cvt2
= Iop_Widen16Uto32x4
;
6557 cvt
= Iop_QNarrowUn64Sto32Ux2
;
6558 cvt2
= Iop_Widen32Uto64x2
;
6563 DIP("vq%sshrun.s%d d%u, q%u, #%u\n", B
? "r" : "",
6564 8 << size
, dreg
, mreg
, shift_imm
);
6567 if (shift_imm
> 0) {
6570 case 1: imm
= (imm
<< 16) | imm
; /* fall through */
6571 case 2: imm
= (imm
<< 32) | imm
; /* fall through */
6573 case 0: default: vassert(0);
6576 case 1: add
= Iop_Add16x8
; break;
6577 case 2: add
= Iop_Add32x4
; break;
6578 case 3: add
= Iop_Add64x2
; break;
6579 case 0: default: vassert(0);
6583 reg_m
= newTemp(Ity_V128
);
6584 res
= newTemp(Ity_V128
);
6585 assign(reg_m
, getQReg(mreg
));
6587 /* VQRSHRN, VQRSHRUN */
6588 assign(res
, binop(add
,
6589 binop(op
, mkexpr(reg_m
), mkU8(shift_imm
)),
6593 mkU8(shift_imm
- 1)),
6596 /* VQSHRN, VQSHRUN */
6597 assign(res
, binop(op
, mkexpr(reg_m
), mkU8(shift_imm
)));
6599 setFlag_QC(unop(cvt2
, unop(cvt
, mkexpr(res
))), mkexpr(res
),
6601 putDRegI64(dreg
, unop(cvt
, mkexpr(res
)), condT
);
6605 VMOVL ::= VSHLL #0 */
6611 shift_imm
= (8 << size
) - shift_imm
;
6612 res
= newTemp(Ity_V128
);
6616 cvt
= U
? Iop_Widen8Uto16x8
: Iop_Widen8Sto16x8
;
6620 cvt
= U
? Iop_Widen16Uto32x4
: Iop_Widen16Sto32x4
;
6624 cvt
= U
? Iop_Widen32Uto64x2
: Iop_Widen32Sto64x2
;
6631 assign(res
, binop(op
, unop(cvt
, getDRegI64(mreg
)), mkU8(shift_imm
)));
6632 putQReg(dreg
, mkexpr(res
), condT
);
6633 if (shift_imm
== 0) {
6634 DIP("vmovl.%c%d q%u, d%u\n", U
? 'u' : 's', 8 << size
,
6637 DIP("vshll.%c%d q%u, d%u, #%u\n", U
? 'u' : 's', 8 << size
,
6638 dreg
, mreg
, shift_imm
);
6643 /* VCVT floating-point <-> fixed-point */
6644 if ((theInstr
>> 8) & 1) {
6646 op
= Q
? Iop_F32ToFixed32Ux4_RZ
: Iop_F32ToFixed32Ux2_RZ
;
6648 op
= Q
? Iop_F32ToFixed32Sx4_RZ
: Iop_F32ToFixed32Sx2_RZ
;
6650 DIP("vcvt.%c32.f32 %c%u, %c%u, #%u\n", U
? 'u' : 's',
6651 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
,
6652 64 - ((theInstr
>> 16) & 0x3f));
6655 op
= Q
? Iop_Fixed32UToF32x4_RN
: Iop_Fixed32UToF32x2_RN
;
6657 op
= Q
? Iop_Fixed32SToF32x4_RN
: Iop_Fixed32SToF32x2_RN
;
6659 DIP("vcvt.f32.%c32 %c%u, %c%u, #%u\n", U
? 'u' : 's',
6660 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
,
6661 64 - ((theInstr
>> 16) & 0x3f));
6663 if (((theInstr
>> 21) & 1) == 0)
6666 putQReg(dreg
, binop(op
, getQReg(mreg
),
6667 mkU8(64 - ((theInstr
>> 16) & 0x3f))), condT
);
6669 putDRegI64(dreg
, binop(op
, getDRegI64(mreg
),
6670 mkU8(64 - ((theInstr
>> 16) & 0x3f))), condT
);
6680 /* A7.4.5 Two registers, miscellaneous */
6682 Bool
dis_neon_data_2reg_misc ( UInt theInstr
, IRTemp condT
)
6684 UInt A
= (theInstr
>> 16) & 3;
6685 UInt B
= (theInstr
>> 6) & 0x1f;
6686 UInt Q
= (theInstr
>> 6) & 1;
6687 UInt U
= (theInstr
>> 24) & 1;
6688 UInt size
= (theInstr
>> 18) & 3;
6689 UInt dreg
= get_neon_d_regno(theInstr
);
6690 UInt mreg
= get_neon_m_regno(theInstr
);
6691 UInt F
= (theInstr
>> 10) & 1;
6692 IRTemp arg_d
= IRTemp_INVALID
;
6693 IRTemp arg_m
= IRTemp_INVALID
;
6694 IRTemp res
= IRTemp_INVALID
;
6698 arg_m
= newTemp(Ity_V128
);
6699 res
= newTemp(Ity_V128
);
6700 assign(arg_m
, getQReg(mreg
));
6702 arg_m
= newTemp(Ity_I64
);
6703 res
= newTemp(Ity_I64
);
6704 assign(arg_m
, getDRegI64(mreg
));
6712 op
= Q
? Iop_Reverse8sIn64_x2
: Iop_Reverse8sIn64_x1
;
6715 op
= Q
? Iop_Reverse16sIn64_x2
: Iop_Reverse16sIn64_x1
;
6718 op
= Q
? Iop_Reverse32sIn64_x2
: Iop_Reverse32sIn64_x1
;
6725 assign(res
, unop(op
, mkexpr(arg_m
)));
6726 DIP("vrev64.%d %c%u, %c%u\n", 8 << size
,
6727 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
6735 op
= Q
? Iop_Reverse8sIn32_x4
: Iop_Reverse8sIn32_x2
;
6738 op
= Q
? Iop_Reverse16sIn32_x4
: Iop_Reverse16sIn32_x2
;
6746 assign(res
, unop(op
, mkexpr(arg_m
)));
6747 DIP("vrev32.%d %c%u, %c%u\n", 8 << size
,
6748 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
6756 op
= Q
? Iop_Reverse8sIn16_x8
: Iop_Reverse8sIn16_x4
;
6765 assign(res
, unop(op
, mkexpr(arg_m
)));
6766 DIP("vrev16.%d %c%u, %c%u\n", 8 << size
,
6767 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
6776 U
= (theInstr
>> 7) & 1;
6779 case 0: op
= U
? Iop_PwAddL8Ux16
: Iop_PwAddL8Sx16
; break;
6780 case 1: op
= U
? Iop_PwAddL16Ux8
: Iop_PwAddL16Sx8
; break;
6781 case 2: op
= U
? Iop_PwAddL32Ux4
: Iop_PwAddL32Sx4
; break;
6782 case 3: return False
;
6783 default: vassert(0);
6787 case 0: op
= U
? Iop_PwAddL8Ux8
: Iop_PwAddL8Sx8
; break;
6788 case 1: op
= U
? Iop_PwAddL16Ux4
: Iop_PwAddL16Sx4
; break;
6789 case 2: op
= U
? Iop_PwAddL32Ux2
: Iop_PwAddL32Sx2
; break;
6790 case 3: return False
;
6791 default: vassert(0);
6794 assign(res
, unop(op
, mkexpr(arg_m
)));
6795 DIP("vpaddl.%c%d %c%u, %c%u\n", U
? 'u' : 's', 8 << size
,
6796 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
6806 case 0: op
= Q
? Iop_Cls8x16
: Iop_Cls8x8
; break;
6807 case 1: op
= Q
? Iop_Cls16x8
: Iop_Cls16x4
; break;
6808 case 2: op
= Q
? Iop_Cls32x4
: Iop_Cls32x2
; break;
6809 case 3: return False
;
6810 default: vassert(0);
6812 assign(res
, unop(op
, mkexpr(arg_m
)));
6813 DIP("vcls.s%d %c%u, %c%u\n", 8 << size
, Q
? 'q' : 'd', dreg
,
6814 Q
? 'q' : 'd', mreg
);
6821 case 0: op
= Q
? Iop_Clz8x16
: Iop_Clz8x8
; break;
6822 case 1: op
= Q
? Iop_Clz16x8
: Iop_Clz16x4
; break;
6823 case 2: op
= Q
? Iop_Clz32x4
: Iop_Clz32x2
; break;
6824 case 3: return False
;
6825 default: vassert(0);
6827 assign(res
, unop(op
, mkexpr(arg_m
)));
6828 DIP("vclz.i%d %c%u, %c%u\n", 8 << size
, Q
? 'q' : 'd', dreg
,
6829 Q
? 'q' : 'd', mreg
);
6834 assign(res
, unop(Q
? Iop_Cnt8x16
: Iop_Cnt8x8
, mkexpr(arg_m
)));
6835 DIP("vcnt.8 %c%u, %c%u\n", Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd',
6841 assign(res
, unop(Iop_NotV128
, mkexpr(arg_m
)));
6843 assign(res
, unop(Iop_Not64
, mkexpr(arg_m
)));
6844 DIP("vmvn %c%u, %c%u\n", Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd',
6851 U
= (theInstr
>> 7) & 1;
6855 op
= U
? Iop_PwAddL8Ux16
: Iop_PwAddL8Sx16
;
6856 add_op
= Iop_Add16x8
;
6859 op
= U
? Iop_PwAddL16Ux8
: Iop_PwAddL16Sx8
;
6860 add_op
= Iop_Add32x4
;
6863 op
= U
? Iop_PwAddL32Ux4
: Iop_PwAddL32Sx4
;
6864 add_op
= Iop_Add64x2
;
6874 op
= U
? Iop_PwAddL8Ux8
: Iop_PwAddL8Sx8
;
6875 add_op
= Iop_Add16x4
;
6878 op
= U
? Iop_PwAddL16Ux4
: Iop_PwAddL16Sx4
;
6879 add_op
= Iop_Add32x2
;
6882 op
= U
? Iop_PwAddL32Ux2
: Iop_PwAddL32Sx2
;
6892 arg_d
= newTemp(Ity_V128
);
6893 assign(arg_d
, getQReg(dreg
));
6895 arg_d
= newTemp(Ity_I64
);
6896 assign(arg_d
, getDRegI64(dreg
));
6898 assign(res
, binop(add_op
, unop(op
, mkexpr(arg_m
)),
6900 DIP("vpadal.%c%d %c%u, %c%u\n", U
? 'u' : 's', 8 << size
,
6901 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
6906 IROp op_sub
, op_qsub
, op_cmp
;
6908 IRExpr
*zero1
, *zero2
;
6911 zero1
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
6912 zero2
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
6913 mask
= newTemp(Ity_V128
);
6914 tmp
= newTemp(Ity_V128
);
6918 mask
= newTemp(Ity_I64
);
6919 tmp
= newTemp(Ity_I64
);
6923 op_sub
= Q
? Iop_Sub8x16
: Iop_Sub8x8
;
6924 op_qsub
= Q
? Iop_QSub8Sx16
: Iop_QSub8Sx8
;
6925 op_cmp
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
;
6928 op_sub
= Q
? Iop_Sub16x8
: Iop_Sub16x4
;
6929 op_qsub
= Q
? Iop_QSub16Sx8
: Iop_QSub16Sx4
;
6930 op_cmp
= Q
? Iop_CmpGT16Sx8
: Iop_CmpGT16Sx4
;
6933 op_sub
= Q
? Iop_Sub32x4
: Iop_Sub32x2
;
6934 op_qsub
= Q
? Iop_QSub32Sx4
: Iop_QSub32Sx2
;
6935 op_cmp
= Q
? Iop_CmpGT32Sx4
: Iop_CmpGT32Sx2
;
6942 assign(mask
, binop(op_cmp
, mkexpr(arg_m
), zero1
));
6943 neg
= binop(op_qsub
, zero2
, mkexpr(arg_m
));
6944 neg2
= binop(op_sub
, zero2
, mkexpr(arg_m
));
6945 assign(res
, binop(Q
? Iop_OrV128
: Iop_Or64
,
6946 binop(Q
? Iop_AndV128
: Iop_And64
,
6949 binop(Q
? Iop_AndV128
: Iop_And64
,
6950 unop(Q
? Iop_NotV128
: Iop_Not64
,
6953 assign(tmp
, binop(Q
? Iop_OrV128
: Iop_Or64
,
6954 binop(Q
? Iop_AndV128
: Iop_And64
,
6957 binop(Q
? Iop_AndV128
: Iop_And64
,
6958 unop(Q
? Iop_NotV128
: Iop_Not64
,
6961 setFlag_QC(mkexpr(res
), mkexpr(tmp
), Q
, condT
);
6962 DIP("vqabs.s%d %c%u, %c%u\n", 8 << size
, Q
? 'q' : 'd', dreg
,
6963 Q
? 'q' : 'd', mreg
);
6971 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
6977 op
= Q
? Iop_QSub8Sx16
: Iop_QSub8Sx8
;
6978 op2
= Q
? Iop_Sub8x16
: Iop_Sub8x8
;
6981 op
= Q
? Iop_QSub16Sx8
: Iop_QSub16Sx4
;
6982 op2
= Q
? Iop_Sub16x8
: Iop_Sub16x4
;
6985 op
= Q
? Iop_QSub32Sx4
: Iop_QSub32Sx2
;
6986 op2
= Q
? Iop_Sub32x4
: Iop_Sub32x2
;
6993 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
6994 setFlag_QC(mkexpr(res
), binop(op2
, zero
, mkexpr(arg_m
)),
6996 DIP("vqneg.s%d %c%u, %c%u\n", 8 << size
, Q
? 'q' : 'd', dreg
,
6997 Q
? 'q' : 'd', mreg
);
7004 putQReg(dreg
, mkexpr(res
), condT
);
7006 putDRegI64(dreg
, mkexpr(res
), condT
);
7011 arg_m
= newTemp(Ity_V128
);
7012 res
= newTemp(Ity_V128
);
7013 assign(arg_m
, getQReg(mreg
));
7015 arg_m
= newTemp(Ity_I64
);
7016 res
= newTemp(Ity_I64
);
7017 assign(arg_m
, getDRegI64(mreg
));
7019 switch ((B
>> 1) & 0x7) {
7025 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7031 case 0: case 1: case 3: return False
;
7032 case 2: op
= Q
? Iop_CmpGT32Fx4
: Iop_CmpGT32Fx2
; break;
7033 default: vassert(0);
7037 case 0: op
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
; break;
7038 case 1: op
= Q
? Iop_CmpGT16Sx8
: Iop_CmpGT16Sx4
; break;
7039 case 2: op
= Q
? Iop_CmpGT32Sx4
: Iop_CmpGT32Sx2
; break;
7040 case 3: return False
;
7041 default: vassert(0);
7044 assign(res
, binop(op
, mkexpr(arg_m
), zero
));
7045 DIP("vcgt.%c%d %c%u, %c%u, #0\n", F
? 'f' : 's', 8 << size
,
7046 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7054 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7060 case 0: case 1: case 3: return False
;
7061 case 2: op
= Q
? Iop_CmpGE32Fx4
: Iop_CmpGE32Fx2
; break;
7062 default: vassert(0);
7064 assign(res
, binop(op
, mkexpr(arg_m
), zero
));
7067 case 0: op
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
; break;
7068 case 1: op
= Q
? Iop_CmpGT16Sx8
: Iop_CmpGT16Sx4
; break;
7069 case 2: op
= Q
? Iop_CmpGT32Sx4
: Iop_CmpGT32Sx2
; break;
7070 case 3: return False
;
7071 default: vassert(0);
7073 assign(res
, unop(Q
? Iop_NotV128
: Iop_Not64
,
7074 binop(op
, zero
, mkexpr(arg_m
))));
7076 DIP("vcge.%c%d %c%u, %c%u, #0\n", F
? 'f' : 's', 8 << size
,
7077 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7086 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7091 case 0: case 1: case 3: return False
;
7092 case 2: op
= Q
? Iop_CmpEQ32Fx4
: Iop_CmpEQ32Fx2
; break;
7093 default: vassert(0);
7095 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
7098 case 0: op
= Q
? Iop_CmpNEZ8x16
: Iop_CmpNEZ8x8
; break;
7099 case 1: op
= Q
? Iop_CmpNEZ16x8
: Iop_CmpNEZ16x4
; break;
7100 case 2: op
= Q
? Iop_CmpNEZ32x4
: Iop_CmpNEZ32x2
; break;
7101 case 3: return False
;
7102 default: vassert(0);
7104 assign(res
, unop(Q
? Iop_NotV128
: Iop_Not64
,
7105 unop(op
, mkexpr(arg_m
))));
7107 DIP("vceq.%c%d %c%u, %c%u, #0\n", F
? 'f' : 'i', 8 << size
,
7108 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7116 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7122 case 0: case 1: case 3: return False
;
7123 case 2: op
= Q
? Iop_CmpGE32Fx4
: Iop_CmpGE32Fx2
; break;
7124 default: vassert(0);
7126 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
7129 case 0: op
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
; break;
7130 case 1: op
= Q
? Iop_CmpGT16Sx8
: Iop_CmpGT16Sx4
; break;
7131 case 2: op
= Q
? Iop_CmpGT32Sx4
: Iop_CmpGT32Sx2
; break;
7132 case 3: return False
;
7133 default: vassert(0);
7135 assign(res
, unop(Q
? Iop_NotV128
: Iop_Not64
,
7136 binop(op
, mkexpr(arg_m
), zero
)));
7138 DIP("vcle.%c%d %c%u, %c%u, #0\n", F
? 'f' : 's', 8 << size
,
7139 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7147 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7153 case 0: case 1: case 3: return False
;
7154 case 2: op
= Q
? Iop_CmpGT32Fx4
: Iop_CmpGT32Fx2
; break;
7155 default: vassert(0);
7157 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
7160 case 0: op
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
; break;
7161 case 1: op
= Q
? Iop_CmpGT16Sx8
: Iop_CmpGT16Sx4
; break;
7162 case 2: op
= Q
? Iop_CmpGT32Sx4
: Iop_CmpGT32Sx2
; break;
7163 case 3: return False
;
7164 default: vassert(0);
7166 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
7168 DIP("vclt.%c%d %c%u, %c%u, #0\n", F
? 'f' : 's', 8 << size
,
7169 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7179 case 0: op
= Q
? Iop_Abs8x16
: Iop_Abs8x8
; break;
7180 case 1: op
= Q
? Iop_Abs16x8
: Iop_Abs16x4
; break;
7181 case 2: op
= Q
? Iop_Abs32x4
: Iop_Abs32x2
; break;
7182 case 3: return False
;
7183 default: vassert(0);
7185 assign(res
, unop(op
, mkexpr(arg_m
)));
7187 assign(res
, unop(Q
? Iop_Abs32Fx4
: Iop_Abs32Fx2
,
7190 DIP("vabs.%c%d %c%u, %c%u\n",
7191 F
? 'f' : 's', 8 << size
, Q
? 'q' : 'd', dreg
,
7192 Q
? 'q' : 'd', mreg
);
7201 case 0: case 1: case 3: return False
;
7202 case 2: op
= Q
? Iop_Neg32Fx4
: Iop_Neg32Fx2
; break;
7203 default: vassert(0);
7205 assign(res
, unop(op
, mkexpr(arg_m
)));
7208 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7213 case 0: op
= Q
? Iop_Sub8x16
: Iop_Sub8x8
; break;
7214 case 1: op
= Q
? Iop_Sub16x8
: Iop_Sub16x4
; break;
7215 case 2: op
= Q
? Iop_Sub32x4
: Iop_Sub32x2
; break;
7216 case 3: return False
;
7217 default: vassert(0);
7219 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
7221 DIP("vneg.%c%d %c%u, %c%u\n",
7222 F
? 'f' : 's', 8 << size
, Q
? 'q' : 'd', dreg
,
7223 Q
? 'q' : 'd', mreg
);
7230 putQReg(dreg
, mkexpr(res
), condT
);
7232 putDRegI64(dreg
, mkexpr(res
), condT
);
7236 if ((B
>> 1) == 0) {
7239 arg_m
= newTemp(Ity_V128
);
7240 assign(arg_m
, getQReg(mreg
));
7241 putQReg(mreg
, getQReg(dreg
), condT
);
7242 putQReg(dreg
, mkexpr(arg_m
), condT
);
7244 arg_m
= newTemp(Ity_I64
);
7245 assign(arg_m
, getDRegI64(mreg
));
7246 putDRegI64(mreg
, getDRegI64(dreg
), condT
);
7247 putDRegI64(dreg
, mkexpr(arg_m
), condT
);
7249 DIP("vswp %c%u, %c%u\n",
7250 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7252 } else if ((B
>> 1) == 1) {
7254 IROp op_odd
= Iop_INVALID
, op_even
= Iop_INVALID
;
7255 IRTemp old_m
, old_d
, new_d
, new_m
;
7257 old_m
= newTemp(Ity_V128
);
7258 old_d
= newTemp(Ity_V128
);
7259 new_m
= newTemp(Ity_V128
);
7260 new_d
= newTemp(Ity_V128
);
7261 assign(old_m
, getQReg(mreg
));
7262 assign(old_d
, getQReg(dreg
));
7264 old_m
= newTemp(Ity_I64
);
7265 old_d
= newTemp(Ity_I64
);
7266 new_m
= newTemp(Ity_I64
);
7267 new_d
= newTemp(Ity_I64
);
7268 assign(old_m
, getDRegI64(mreg
));
7269 assign(old_d
, getDRegI64(dreg
));
7274 op_odd
= Iop_InterleaveOddLanes8x16
;
7275 op_even
= Iop_InterleaveEvenLanes8x16
;
7278 op_odd
= Iop_InterleaveOddLanes16x8
;
7279 op_even
= Iop_InterleaveEvenLanes16x8
;
7282 op_odd
= Iop_InterleaveOddLanes32x4
;
7283 op_even
= Iop_InterleaveEvenLanes32x4
;
7293 op_odd
= Iop_InterleaveOddLanes8x8
;
7294 op_even
= Iop_InterleaveEvenLanes8x8
;
7297 op_odd
= Iop_InterleaveOddLanes16x4
;
7298 op_even
= Iop_InterleaveEvenLanes16x4
;
7301 op_odd
= Iop_InterleaveHI32x2
;
7302 op_even
= Iop_InterleaveLO32x2
;
7310 assign(new_d
, binop(op_even
, mkexpr(old_m
), mkexpr(old_d
)));
7311 assign(new_m
, binop(op_odd
, mkexpr(old_m
), mkexpr(old_d
)));
7313 putQReg(dreg
, mkexpr(new_d
), condT
);
7314 putQReg(mreg
, mkexpr(new_m
), condT
);
7316 putDRegI64(dreg
, mkexpr(new_d
), condT
);
7317 putDRegI64(mreg
, mkexpr(new_m
), condT
);
7319 DIP("vtrn.%d %c%u, %c%u\n",
7320 8 << size
, Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7322 } else if ((B
>> 1) == 2) {
7324 IROp op_even
, op_odd
;
7325 IRTemp old_m
, old_d
, new_m
, new_d
;
7326 if (!Q
&& size
== 2)
7329 old_m
= newTemp(Ity_V128
);
7330 old_d
= newTemp(Ity_V128
);
7331 new_m
= newTemp(Ity_V128
);
7332 new_d
= newTemp(Ity_V128
);
7333 assign(old_m
, getQReg(mreg
));
7334 assign(old_d
, getQReg(dreg
));
7336 old_m
= newTemp(Ity_I64
);
7337 old_d
= newTemp(Ity_I64
);
7338 new_m
= newTemp(Ity_I64
);
7339 new_d
= newTemp(Ity_I64
);
7340 assign(old_m
, getDRegI64(mreg
));
7341 assign(old_d
, getDRegI64(dreg
));
7345 op_odd
= Q
? Iop_CatOddLanes8x16
: Iop_CatOddLanes8x8
;
7346 op_even
= Q
? Iop_CatEvenLanes8x16
: Iop_CatEvenLanes8x8
;
7349 op_odd
= Q
? Iop_CatOddLanes16x8
: Iop_CatOddLanes16x4
;
7350 op_even
= Q
? Iop_CatEvenLanes16x8
: Iop_CatEvenLanes16x4
;
7353 op_odd
= Iop_CatOddLanes32x4
;
7354 op_even
= Iop_CatEvenLanes32x4
;
7361 assign(new_d
, binop(op_even
, mkexpr(old_m
), mkexpr(old_d
)));
7362 assign(new_m
, binop(op_odd
, mkexpr(old_m
), mkexpr(old_d
)));
7364 putQReg(dreg
, mkexpr(new_d
), condT
);
7365 putQReg(mreg
, mkexpr(new_m
), condT
);
7367 putDRegI64(dreg
, mkexpr(new_d
), condT
);
7368 putDRegI64(mreg
, mkexpr(new_m
), condT
);
7370 DIP("vuzp.%d %c%u, %c%u\n",
7371 8 << size
, Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7373 } else if ((B
>> 1) == 3) {
7376 IRTemp old_m
, old_d
, new_m
, new_d
;
7377 if (!Q
&& size
== 2)
7380 old_m
= newTemp(Ity_V128
);
7381 old_d
= newTemp(Ity_V128
);
7382 new_m
= newTemp(Ity_V128
);
7383 new_d
= newTemp(Ity_V128
);
7384 assign(old_m
, getQReg(mreg
));
7385 assign(old_d
, getQReg(dreg
));
7387 old_m
= newTemp(Ity_I64
);
7388 old_d
= newTemp(Ity_I64
);
7389 new_m
= newTemp(Ity_I64
);
7390 new_d
= newTemp(Ity_I64
);
7391 assign(old_m
, getDRegI64(mreg
));
7392 assign(old_d
, getDRegI64(dreg
));
7396 op_hi
= Q
? Iop_InterleaveHI8x16
: Iop_InterleaveHI8x8
;
7397 op_lo
= Q
? Iop_InterleaveLO8x16
: Iop_InterleaveLO8x8
;
7400 op_hi
= Q
? Iop_InterleaveHI16x8
: Iop_InterleaveHI16x4
;
7401 op_lo
= Q
? Iop_InterleaveLO16x8
: Iop_InterleaveLO16x4
;
7404 op_hi
= Iop_InterleaveHI32x4
;
7405 op_lo
= Iop_InterleaveLO32x4
;
7412 assign(new_d
, binop(op_lo
, mkexpr(old_m
), mkexpr(old_d
)));
7413 assign(new_m
, binop(op_hi
, mkexpr(old_m
), mkexpr(old_d
)));
7415 putQReg(dreg
, mkexpr(new_d
), condT
);
7416 putQReg(mreg
, mkexpr(new_m
), condT
);
7418 putDRegI64(dreg
, mkexpr(new_d
), condT
);
7419 putDRegI64(mreg
, mkexpr(new_m
), condT
);
7421 DIP("vzip.%d %c%u, %c%u\n",
7422 8 << size
, Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7424 } else if (B
== 8) {
7429 case 0: op
= Iop_NarrowUn16to8x8
; break;
7430 case 1: op
= Iop_NarrowUn32to16x4
; break;
7431 case 2: op
= Iop_NarrowUn64to32x2
; break;
7432 case 3: return False
;
7433 default: vassert(0);
7435 putDRegI64(dreg
, unop(op
, getQReg(mreg
)), condT
);
7436 DIP("vmovn.i%d d%u, q%u\n", 16 << size
, dreg
, mreg
);
7438 } else if (B
== 9 || (B
>> 1) == 5) {
7439 /* VQMOVN, VQMOVUN */
7442 dreg
= ((theInstr
>> 18) & 0x10) | ((theInstr
>> 12) & 0xF);
7443 mreg
= ((theInstr
>> 1) & 0x10) | (theInstr
& 0xF);
7448 case 0: op2
= Iop_NarrowUn16to8x8
; break;
7449 case 1: op2
= Iop_NarrowUn32to16x4
; break;
7450 case 2: op2
= Iop_NarrowUn64to32x2
; break;
7451 case 3: return False
;
7452 default: vassert(0);
7459 case 0: op
= Iop_QNarrowUn16Sto8Ux8
; break;
7460 case 1: op
= Iop_QNarrowUn32Sto16Ux4
; break;
7461 case 2: op
= Iop_QNarrowUn64Sto32Ux2
; break;
7462 case 3: return False
;
7463 default: vassert(0);
7465 DIP("vqmovun.s%d d%u, q%u\n", 16 << size
, dreg
, mreg
);
7469 case 0: op
= Iop_QNarrowUn16Sto8Sx8
; break;
7470 case 1: op
= Iop_QNarrowUn32Sto16Sx4
; break;
7471 case 2: op
= Iop_QNarrowUn64Sto32Sx2
; break;
7472 case 3: return False
;
7473 default: vassert(0);
7475 DIP("vqmovn.s%d d%u, q%u\n", 16 << size
, dreg
, mreg
);
7479 case 0: op
= Iop_QNarrowUn16Uto8Ux8
; break;
7480 case 1: op
= Iop_QNarrowUn32Uto16Ux4
; break;
7481 case 2: op
= Iop_QNarrowUn64Uto32Ux2
; break;
7482 case 3: return False
;
7483 default: vassert(0);
7485 DIP("vqmovn.u%d d%u, q%u\n", 16 << size
, dreg
, mreg
);
7490 res
= newTemp(Ity_I64
);
7491 tmp
= newTemp(Ity_I64
);
7492 assign(res
, unop(op
, getQReg(mreg
)));
7493 assign(tmp
, unop(op2
, getQReg(mreg
)));
7494 setFlag_QC(mkexpr(res
), mkexpr(tmp
), False
, condT
);
7495 putDRegI64(dreg
, mkexpr(res
), condT
);
7497 } else if (B
== 12) {
7498 /* VSHLL (maximum shift) */
7506 shift_imm
= 8 << size
;
7507 res
= newTemp(Ity_V128
);
7509 case 0: op
= Iop_ShlN16x8
; cvt
= Iop_Widen8Uto16x8
; break;
7510 case 1: op
= Iop_ShlN32x4
; cvt
= Iop_Widen16Uto32x4
; break;
7511 case 2: op
= Iop_ShlN64x2
; cvt
= Iop_Widen32Uto64x2
; break;
7512 case 3: return False
;
7513 default: vassert(0);
7515 assign(res
, binop(op
, unop(cvt
, getDRegI64(mreg
)),
7517 putQReg(dreg
, mkexpr(res
), condT
);
7518 DIP("vshll.i%d q%u, d%u, #%d\n", 8 << size
, dreg
, mreg
, 8 << size
);
7520 } else if ((B
>> 3) == 3 && (B
& 3) == 0) {
7521 /* VCVT (half<->single) */
7522 /* Half-precision extensions are needed to run this */
7524 if (((theInstr
>> 18) & 3) != 1)
7526 if ((theInstr
>> 8) & 1) {
7530 putQReg(dreg
, unop(Iop_F16toF32x4
, getDRegI64(mreg
)),
7532 DIP("vcvt.f32.f16 q%u, d%u\n", dreg
, mreg
);
7537 putDRegI64(dreg
, unop(Iop_F32toF16x4
, getQReg(mreg
)),
7539 DIP("vcvt.f16.f32 d%u, q%u\n", dreg
, mreg
);
7548 if (((B
>> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,0)) {
7551 F
= (theInstr
>> 8) & 1;
7555 op
= F
? Iop_RecipEst32Fx4
: Iop_RecipEst32Ux4
;
7556 putQReg(dreg
, unop(op
, getQReg(mreg
)), condT
);
7557 DIP("vrecpe.%c32 q%u, q%u\n", F
? 'f' : 'u', dreg
, mreg
);
7559 op
= F
? Iop_RecipEst32Fx2
: Iop_RecipEst32Ux2
;
7560 putDRegI64(dreg
, unop(op
, getDRegI64(mreg
)), condT
);
7561 DIP("vrecpe.%c32 d%u, d%u\n", F
? 'f' : 'u', dreg
, mreg
);
7564 } else if (((B
>> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,1)) {
7572 op
= Q
? Iop_RSqrtEst32Fx4
: Iop_RSqrtEst32Fx2
;
7575 op
= Q
? Iop_RSqrtEst32Ux4
: Iop_RSqrtEst32Ux2
;
7578 putQReg(dreg
, unop(op
, getQReg(mreg
)), condT
);
7579 DIP("vrsqrte.%c32 q%u, q%u\n", F
? 'f' : 'u', dreg
, mreg
);
7581 putDRegI64(dreg
, unop(op
, getDRegI64(mreg
)), condT
);
7582 DIP("vrsqrte.%c32 d%u, d%u\n", F
? 'f' : 'u', dreg
, mreg
);
7585 } else if ((B
>> 3) == 3) {
7586 /* VCVT (fp<->integer) */
7590 switch ((B
>> 1) & 3) {
7592 op
= Q
? Iop_I32StoFx4
: Iop_I32StoFx2
;
7593 DIP("vcvt.f32.s32 %c%u, %c%u\n",
7594 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7597 op
= Q
? Iop_I32UtoFx4
: Iop_I32UtoFx2
;
7598 DIP("vcvt.f32.u32 %c%u, %c%u\n",
7599 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7602 op
= Q
? Iop_FtoI32Sx4_RZ
: Iop_FtoI32Sx2_RZ
;
7603 DIP("vcvt.s32.f32 %c%u, %c%u\n",
7604 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7607 op
= Q
? Iop_FtoI32Ux4_RZ
: Iop_FtoI32Ux2_RZ
;
7608 DIP("vcvt.u32.f32 %c%u, %c%u\n",
7609 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7615 putQReg(dreg
, unop(op
, getQReg(mreg
)), condT
);
7617 putDRegI64(dreg
, unop(op
, getDRegI64(mreg
)), condT
);
7631 /* A7.4.6 One register and a modified immediate value */
7633 void ppNeonImm(UInt imm
, UInt cmode
, UInt op
)
7637 case 0: case 1: case 8: case 9:
7638 vex_printf("0x%x", imm
);
7640 case 2: case 3: case 10: case 11:
7641 vex_printf("0x%x00", imm
);
7644 vex_printf("0x%x0000", imm
);
7647 vex_printf("0x%x000000", imm
);
7650 vex_printf("0x%xff", imm
);
7653 vex_printf("0x%xffff", imm
);
7658 for (i
= 7; i
>= 0; i
--)
7659 vex_printf("%s", (imm
& (1 << i
)) ? "ff" : "00");
7661 vex_printf("0x%x", imm
);
7665 vex_printf("0x%x", imm
);
7671 const char *ppNeonImmType(UInt cmode
, UInt op
)
7695 void DIPimm(UInt imm
, UInt cmode
, UInt op
,
7696 const char *instr
, UInt Q
, UInt dreg
)
7698 if (vex_traceflags
& VEX_TRACE_FE
) {
7699 vex_printf("%s.%s %c%u, #", instr
,
7700 ppNeonImmType(cmode
, op
), Q
? 'q' : 'd', dreg
);
7701 ppNeonImm(imm
, cmode
, op
);
7707 Bool
dis_neon_data_1reg_and_imm ( UInt theInstr
, IRTemp condT
)
7709 UInt dreg
= get_neon_d_regno(theInstr
);
7710 ULong imm_raw
= ((theInstr
>> 17) & 0x80) | ((theInstr
>> 12) & 0x70) |
7712 ULong imm_raw_pp
= imm_raw
;
7713 UInt cmode
= (theInstr
>> 8) & 0xf;
7714 UInt op_bit
= (theInstr
>> 5) & 1;
7716 UInt Q
= (theInstr
>> 6) & 1;
7724 imm_raw
= imm_raw
<< 8;
7727 imm_raw
= imm_raw
<< 8;
7730 imm_raw
= imm_raw
<< 8;
7733 imm
= (imm_raw
<< 32) | imm_raw
;
7736 imm_raw
= imm_raw
<< 8;
7739 imm_raw
= (imm_raw
<< 16) | imm_raw
;
7740 imm
= (imm_raw
<< 32) | imm_raw
;
7743 imm_raw
= (imm_raw
<< 8) | 0xff;
7746 imm_raw
= (imm_raw
<< 8) | 0xff;
7747 imm
= (imm_raw
<< 32) | imm_raw
;
7751 for(i
= 0; i
< 8; i
++) {
7752 imm
= (imm
<< 8) | imm_raw
;
7755 for(i
= 7; i
>= 0; i
--) {
7757 for(j
= 0; j
< 8; j
++) {
7758 tmp
= (tmp
<< 1) | ((imm_raw
>> i
) & 1);
7760 imm
= (imm
<< 8) | tmp
;
7765 imm
= (imm_raw
& 0x80) << 5;
7766 imm
|= ((~imm_raw
& 0x40) << 5);
7767 for(i
= 1; i
<= 4; i
++)
7768 imm
|= (imm_raw
& 0x40) << i
;
7769 imm
|= (imm_raw
& 0x7f);
7771 imm
= (imm
<< 32) | imm
;
7777 imm_val
= binop(Iop_64HLtoV128
, mkU64(imm
), mkU64(imm
));
7779 imm_val
= mkU64(imm
);
7781 if (((op_bit
== 0) &&
7782 (((cmode
& 9) == 0) || ((cmode
& 13) == 8) || ((cmode
& 12) == 12))) ||
7783 ((op_bit
== 1) && (cmode
== 14))) {
7784 /* VMOV (immediate) */
7786 putQReg(dreg
, imm_val
, condT
);
7788 putDRegI64(dreg
, imm_val
, condT
);
7790 DIPimm(imm_raw_pp
, cmode
, op_bit
, "vmov", Q
, dreg
);
7793 if ((op_bit
== 1) &&
7794 (((cmode
& 9) == 0) || ((cmode
& 13) == 8) || ((cmode
& 14) == 12))) {
7795 /* VMVN (immediate) */
7797 putQReg(dreg
, unop(Iop_NotV128
, imm_val
), condT
);
7799 putDRegI64(dreg
, unop(Iop_Not64
, imm_val
), condT
);
7801 DIPimm(imm_raw_pp
, cmode
, op_bit
, "vmvn", Q
, dreg
);
7805 tmp_var
= newTemp(Ity_V128
);
7806 assign(tmp_var
, getQReg(dreg
));
7808 tmp_var
= newTemp(Ity_I64
);
7809 assign(tmp_var
, getDRegI64(dreg
));
7811 if ((op_bit
== 0) && (((cmode
& 9) == 1) || ((cmode
& 13) == 9))) {
7812 /* VORR (immediate) */
7814 expr
= binop(Iop_OrV128
, mkexpr(tmp_var
), imm_val
);
7816 expr
= binop(Iop_Or64
, mkexpr(tmp_var
), imm_val
);
7817 DIPimm(imm_raw_pp
, cmode
, op_bit
, "vorr", Q
, dreg
);
7818 } else if ((op_bit
== 1) && (((cmode
& 9) == 1) || ((cmode
& 13) == 9))) {
7819 /* VBIC (immediate) */
7821 expr
= binop(Iop_AndV128
, mkexpr(tmp_var
),
7822 unop(Iop_NotV128
, imm_val
));
7824 expr
= binop(Iop_And64
, mkexpr(tmp_var
), unop(Iop_Not64
, imm_val
));
7825 DIPimm(imm_raw_pp
, cmode
, op_bit
, "vbic", Q
, dreg
);
7830 putQReg(dreg
, expr
, condT
);
7832 putDRegI64(dreg
, expr
, condT
);
7836 /* A7.4 Advanced SIMD data-processing instructions */
7838 Bool
dis_neon_data_processing ( UInt theInstr
, IRTemp condT
)
7840 UInt A
= (theInstr
>> 19) & 0x1F;
7841 UInt B
= (theInstr
>> 8) & 0xF;
7842 UInt C
= (theInstr
>> 4) & 0xF;
7843 UInt U
= (theInstr
>> 24) & 0x1;
7846 return dis_neon_data_3same(theInstr
, condT
);
7848 if (((A
& 0x17) == 0x10) && ((C
& 0x9) == 0x1)) {
7849 return dis_neon_data_1reg_and_imm(theInstr
, condT
);
7852 return dis_neon_data_2reg_and_shift(theInstr
, condT
);
7854 if (((C
& 5) == 0) && (((A
& 0x14) == 0x10) || ((A
& 0x16) == 0x14))) {
7855 return dis_neon_data_3diff(theInstr
, condT
);
7857 if (((C
& 5) == 4) && (((A
& 0x14) == 0x10) || ((A
& 0x16) == 0x14))) {
7858 return dis_neon_data_2reg_and_scalar(theInstr
, condT
);
7860 if ((A
& 0x16) == 0x16) {
7861 if ((U
== 0) && ((C
& 1) == 0)) {
7862 return dis_neon_vext(theInstr
, condT
);
7864 if ((U
!= 1) || ((C
& 1) == 1))
7867 return dis_neon_data_2reg_misc(theInstr
, condT
);
7869 if ((B
& 12) == 8) {
7870 return dis_neon_vtb(theInstr
, condT
);
7872 if ((B
== 12) && ((C
& 9) == 0)) {
7873 return dis_neon_vdup(theInstr
, condT
);
7880 /*------------------------------------------------------------*/
7881 /*--- NEON loads and stores ---*/
7882 /*------------------------------------------------------------*/
7884 /* For NEON memory operations, we use the standard scheme to handle
7885 conditionalisation: generate a jump around the instruction if the
7886 condition is false. That's only necessary in Thumb mode, however,
7887 since in ARM mode NEON instructions are unconditional. */
7889 /* A helper function for what follows. It assumes we already went
7890 uncond as per comments at the top of this section. */
7892 void mk_neon_elem_load_to_one_lane( UInt rD
, UInt inc
, UInt index
,
7893 UInt N
, UInt size
, IRTemp addr
)
7898 putDRegI64(rD
, triop(Iop_SetElem8x8
, getDRegI64(rD
), mkU8(index
),
7899 loadLE(Ity_I8
, mkexpr(addr
))), IRTemp_INVALID
);
7902 putDRegI64(rD
, triop(Iop_SetElem16x4
, getDRegI64(rD
), mkU8(index
),
7903 loadLE(Ity_I16
, mkexpr(addr
))), IRTemp_INVALID
);
7906 putDRegI64(rD
, triop(Iop_SetElem32x2
, getDRegI64(rD
), mkU8(index
),
7907 loadLE(Ity_I32
, mkexpr(addr
))), IRTemp_INVALID
);
7912 for (i
= 1; i
<= N
; i
++) {
7915 putDRegI64(rD
+ i
* inc
,
7916 triop(Iop_SetElem8x8
,
7917 getDRegI64(rD
+ i
* inc
),
7919 loadLE(Ity_I8
, binop(Iop_Add32
,
7925 putDRegI64(rD
+ i
* inc
,
7926 triop(Iop_SetElem16x4
,
7927 getDRegI64(rD
+ i
* inc
),
7929 loadLE(Ity_I16
, binop(Iop_Add32
,
7935 putDRegI64(rD
+ i
* inc
,
7936 triop(Iop_SetElem32x2
,
7937 getDRegI64(rD
+ i
* inc
),
7939 loadLE(Ity_I32
, binop(Iop_Add32
,
7950 /* A(nother) helper function for what follows. It assumes we already
7951 went uncond as per comments at the top of this section. */
7953 void mk_neon_elem_store_from_one_lane( UInt rD
, UInt inc
, UInt index
,
7954 UInt N
, UInt size
, IRTemp addr
)
7959 storeLE(mkexpr(addr
),
7960 binop(Iop_GetElem8x8
, getDRegI64(rD
), mkU8(index
)));
7963 storeLE(mkexpr(addr
),
7964 binop(Iop_GetElem16x4
, getDRegI64(rD
), mkU8(index
)));
7967 storeLE(mkexpr(addr
),
7968 binop(Iop_GetElem32x2
, getDRegI64(rD
), mkU8(index
)));
7973 for (i
= 1; i
<= N
; i
++) {
7976 storeLE(binop(Iop_Add32
, mkexpr(addr
), mkU32(i
* 1)),
7977 binop(Iop_GetElem8x8
, getDRegI64(rD
+ i
* inc
),
7981 storeLE(binop(Iop_Add32
, mkexpr(addr
), mkU32(i
* 2)),
7982 binop(Iop_GetElem16x4
, getDRegI64(rD
+ i
* inc
),
7986 storeLE(binop(Iop_Add32
, mkexpr(addr
), mkU32(i
* 4)),
7987 binop(Iop_GetElem32x2
, getDRegI64(rD
+ i
* inc
),
7996 /* Generate 2x64 -> 2x64 deinterleave code, for VLD2. Caller must
7997 make *u0 and *u1 be valid IRTemps before the call. */
7998 static void math_DEINTERLEAVE_2 (/*OUT*/IRTemp
* u0
, /*OUT*/IRTemp
* u1
,
7999 IRTemp i0
, IRTemp i1
, Int laneszB
)
8001 /* The following assumes that the guest is little endian, and hence
8002 that the memory-side (interleaved) data is stored
8005 /* This is pretty easy, since we have primitives directly to
8008 // memLE(128 bits) == A0 B0 A1 B1
8009 // i0 == B0 A0, i1 == B1 A1
8010 // u0 == A1 A0, u1 == B1 B0
8011 assign(*u0
, binop(Iop_InterleaveLO32x2
, mkexpr(i1
), mkexpr(i0
)));
8012 assign(*u1
, binop(Iop_InterleaveHI32x2
, mkexpr(i1
), mkexpr(i0
)));
8013 } else if (laneszB
== 2) {
8014 // memLE(128 bits) == A0 B0 A1 B1 A2 B2 A3 B3
8015 // i0 == B1 A1 B0 A0, i1 == B3 A3 B2 A2
8016 // u0 == A3 A2 A1 A0, u1 == B3 B2 B1 B0
8017 assign(*u0
, binop(Iop_CatEvenLanes16x4
, mkexpr(i1
), mkexpr(i0
)));
8018 assign(*u1
, binop(Iop_CatOddLanes16x4
, mkexpr(i1
), mkexpr(i0
)));
8019 } else if (laneszB
== 1) {
8020 // memLE(128 bits) == A0 B0 A1 B1 A2 B2 A3 B3 A4 B4 A5 B5 A6 B6 A7 B7
8021 // i0 == B3 A3 B2 A2 B1 A1 B0 A0, i1 == B7 A7 B6 A6 B5 A5 B4 A4
8022 // u0 == A7 A6 A5 A4 A3 A2 A1 A0, u1 == B7 B6 B5 B4 B3 B2 B1 B0
8023 assign(*u0
, binop(Iop_CatEvenLanes8x8
, mkexpr(i1
), mkexpr(i0
)));
8024 assign(*u1
, binop(Iop_CatOddLanes8x8
, mkexpr(i1
), mkexpr(i0
)));
8026 // Can never happen, since VLD2 only has valid lane widths of 32,
8028 vpanic("math_DEINTERLEAVE_2");
8032 /* Generate 2x64 -> 2x64 interleave code, for VST2. Caller must make
8033 *u0 and *u1 be valid IRTemps before the call. */
8034 static void math_INTERLEAVE_2 (/*OUT*/IRTemp
* i0
, /*OUT*/IRTemp
* i1
,
8035 IRTemp u0
, IRTemp u1
, Int laneszB
)
8037 /* The following assumes that the guest is little endian, and hence
8038 that the memory-side (interleaved) data is stored
8041 /* This is pretty easy, since we have primitives directly to
8044 // memLE(128 bits) == A0 B0 A1 B1
8045 // i0 == B0 A0, i1 == B1 A1
8046 // u0 == A1 A0, u1 == B1 B0
8047 assign(*i0
, binop(Iop_InterleaveLO32x2
, mkexpr(u1
), mkexpr(u0
)));
8048 assign(*i1
, binop(Iop_InterleaveHI32x2
, mkexpr(u1
), mkexpr(u0
)));
8049 } else if (laneszB
== 2) {
8050 // memLE(128 bits) == A0 B0 A1 B1 A2 B2 A3 B3
8051 // i0 == B1 A1 B0 A0, i1 == B3 A3 B2 A2
8052 // u0 == A3 A2 A1 A0, u1 == B3 B2 B1 B0
8053 assign(*i0
, binop(Iop_InterleaveLO16x4
, mkexpr(u1
), mkexpr(u0
)));
8054 assign(*i1
, binop(Iop_InterleaveHI16x4
, mkexpr(u1
), mkexpr(u0
)));
8055 } else if (laneszB
== 1) {
8056 // memLE(128 bits) == A0 B0 A1 B1 A2 B2 A3 B3 A4 B4 A5 B5 A6 B6 A7 B7
8057 // i0 == B3 A3 B2 A2 B1 A1 B0 A0, i1 == B7 A7 B6 A6 B5 A5 B4 A4
8058 // u0 == A7 A6 A5 A4 A3 A2 A1 A0, u1 == B7 B6 B5 B4 B3 B2 B1 B0
8059 assign(*i0
, binop(Iop_InterleaveLO8x8
, mkexpr(u1
), mkexpr(u0
)));
8060 assign(*i1
, binop(Iop_InterleaveHI8x8
, mkexpr(u1
), mkexpr(u0
)));
8062 // Can never happen, since VST2 only has valid lane widths of 32,
8064 vpanic("math_INTERLEAVE_2");
8068 // Helper function for generating arbitrary slicing 'n' dicing of
8069 // 3 8x8 vectors, as needed for VLD3.8 and VST3.8.
8070 static IRExpr
* math_PERM_8x8x3(const UChar
* desc
,
8071 IRTemp s0
, IRTemp s1
, IRTemp s2
)
8073 // desc is an array of 8 pairs, encoded as 16 bytes,
8074 // that describe how to assemble the result lanes, starting with
8075 // lane 7. Each pair is: first component (0..2) says which of
8076 // s0/s1/s2 to use. Second component (0..7) is the lane number
8077 // in the source to use.
8079 for (si
= 0; si
< 7; si
++) {
8080 vassert(desc
[2 * si
+ 0] <= 2);
8081 vassert(desc
[2 * si
+ 1] <= 7);
8083 IRTemp h3
= newTemp(Ity_I64
);
8084 IRTemp h2
= newTemp(Ity_I64
);
8085 IRTemp h1
= newTemp(Ity_I64
);
8086 IRTemp h0
= newTemp(Ity_I64
);
8087 IRTemp srcs
[3] = {s0
, s1
, s2
};
8088 # define SRC_VEC(_lane) mkexpr(srcs[desc[2 * (7-(_lane)) + 0]])
8089 # define SRC_SHIFT(_lane) mkU8(56-8*(desc[2 * (7-(_lane)) + 1]))
8090 assign(h3
, binop(Iop_InterleaveHI8x8
,
8091 binop(Iop_Shl64
, SRC_VEC(7), SRC_SHIFT(7)),
8092 binop(Iop_Shl64
, SRC_VEC(6), SRC_SHIFT(6))));
8093 assign(h2
, binop(Iop_InterleaveHI8x8
,
8094 binop(Iop_Shl64
, SRC_VEC(5), SRC_SHIFT(5)),
8095 binop(Iop_Shl64
, SRC_VEC(4), SRC_SHIFT(4))));
8096 assign(h1
, binop(Iop_InterleaveHI8x8
,
8097 binop(Iop_Shl64
, SRC_VEC(3), SRC_SHIFT(3)),
8098 binop(Iop_Shl64
, SRC_VEC(2), SRC_SHIFT(2))));
8099 assign(h0
, binop(Iop_InterleaveHI8x8
,
8100 binop(Iop_Shl64
, SRC_VEC(1), SRC_SHIFT(1)),
8101 binop(Iop_Shl64
, SRC_VEC(0), SRC_SHIFT(0))));
8104 // Now h3..h0 are 64 bit vectors with useful information only
8105 // in the top 16 bits. We now concatentate those four 16-bit
8106 // groups so as to produce the final result.
8107 IRTemp w1
= newTemp(Ity_I64
);
8108 IRTemp w0
= newTemp(Ity_I64
);
8109 assign(w1
, binop(Iop_InterleaveHI16x4
, mkexpr(h3
), mkexpr(h2
)));
8110 assign(w0
, binop(Iop_InterleaveHI16x4
, mkexpr(h1
), mkexpr(h0
)));
8111 return binop(Iop_InterleaveHI32x2
, mkexpr(w1
), mkexpr(w0
));
8114 /* Generate 3x64 -> 3x64 deinterleave code, for VLD3. Caller must
8115 make *u0, *u1 and *u2 be valid IRTemps before the call. */
8116 static void math_DEINTERLEAVE_3 (
8117 /*OUT*/IRTemp
* u0
, /*OUT*/IRTemp
* u1
, /*OUT*/IRTemp
* u2
,
8118 IRTemp i0
, IRTemp i1
, IRTemp i2
, Int laneszB
8121 # define IHI32x2(_e1, _e2) binop(Iop_InterleaveHI32x2, (_e1), (_e2))
8122 # define IHI16x4(_e1, _e2) binop(Iop_InterleaveHI16x4, (_e1), (_e2))
8123 # define SHL64(_tmp, _amt) binop(Iop_Shl64, mkexpr(_tmp), mkU8(_amt))
8124 /* The following assumes that the guest is little endian, and hence
8125 that the memory-side (interleaved) data is stored
8127 vassert(u0
&& u1
&& u2
);
8129 // memLE(192 bits) == A0 B0 C0 A1 B1 C1
8130 // i0 == B0 A0, i1 == A1 C0, i2 == C1 B1
8131 // u0 == A1 A0, u1 == B1 B0, u2 == C1 C0
8132 assign(*u0
, IHI32x2(SHL64(i1
, 0), SHL64(i0
, 32)));
8133 assign(*u1
, IHI32x2(SHL64(i2
, 32), SHL64(i0
, 0)));
8134 assign(*u2
, IHI32x2(SHL64(i2
, 0), SHL64(i1
, 32)));
8135 } else if (laneszB
== 2) {
8136 // memLE(192 bits) == A0 B0 C0 A1, B1 C1 A2 B2, C2 A3 B3 C3
8137 // i0 == A1 C0 B0 A0, i1 == B2 A2 C1 B1, i2 == C3 B3 A3 C2
8138 // u0 == A3 A2 A1 A0, u1 == B3 B2 B1 B0, u2 == C3 C2 C1 C0
8139 # define XXX(_tmp3,_la3,_tmp2,_la2,_tmp1,_la1,_tmp0,_la0) \
8141 IHI16x4(SHL64((_tmp3),48-16*(_la3)), \
8142 SHL64((_tmp2),48-16*(_la2))), \
8143 IHI16x4(SHL64((_tmp1),48-16*(_la1)), \
8144 SHL64((_tmp0),48-16*(_la0))))
8145 assign(*u0
, XXX(i2
,1, i1
,2, i0
,3, i0
,0));
8146 assign(*u1
, XXX(i2
,2, i1
,3, i1
,0, i0
,1));
8147 assign(*u2
, XXX(i2
,3, i2
,0, i1
,1, i0
,2));
8149 } else if (laneszB
== 1) {
8150 // These describe how the result vectors [7..0] are
8151 // assembled from the source vectors. Each pair is
8152 // (source vector number, lane number).
8153 static const UChar de0
[16] = {2,5, 2,2, 1,7, 1,4, 1,1, 0,6, 0,3, 0,0};
8154 static const UChar de1
[16] = {2,6, 2,3, 2,0, 1,5, 1,2, 0,7, 0,4, 0,1};
8155 static const UChar de2
[16] = {2,7, 2,4, 2,1, 1,6, 1,3, 1,0, 0,5, 0,2};
8156 assign(*u0
, math_PERM_8x8x3(de0
, i0
, i1
, i2
));
8157 assign(*u1
, math_PERM_8x8x3(de1
, i0
, i1
, i2
));
8158 assign(*u2
, math_PERM_8x8x3(de2
, i0
, i1
, i2
));
8160 // Can never happen, since VLD3 only has valid lane widths of 32,
8162 vpanic("math_DEINTERLEAVE_3");
8169 /* Generate 3x64 -> 3x64 interleave code, for VST3. Caller must
8170 make *i0, *i1 and *i2 be valid IRTemps before the call. */
8171 static void math_INTERLEAVE_3 (
8172 /*OUT*/IRTemp
* i0
, /*OUT*/IRTemp
* i1
, /*OUT*/IRTemp
* i2
,
8173 IRTemp u0
, IRTemp u1
, IRTemp u2
, Int laneszB
8176 # define IHI32x2(_e1, _e2) binop(Iop_InterleaveHI32x2, (_e1), (_e2))
8177 # define IHI16x4(_e1, _e2) binop(Iop_InterleaveHI16x4, (_e1), (_e2))
8178 # define SHL64(_tmp, _amt) binop(Iop_Shl64, mkexpr(_tmp), mkU8(_amt))
8179 /* The following assumes that the guest is little endian, and hence
8180 that the memory-side (interleaved) data is stored
8182 vassert(i0
&& i1
&& i2
);
8184 // memLE(192 bits) == A0 B0 C0 A1 B1 C1
8185 // i0 == B0 A0, i1 == A1 C0, i2 == C1 B1
8186 // u0 == A1 A0, u1 == B1 B0, u2 == C1 C0
8187 assign(*i0
, IHI32x2(SHL64(u1
, 32), SHL64(u0
, 32)));
8188 assign(*i1
, IHI32x2(SHL64(u0
, 0), SHL64(u2
, 32)));
8189 assign(*i2
, IHI32x2(SHL64(u2
, 0), SHL64(u1
, 0)));
8190 } else if (laneszB
== 2) {
8191 // memLE(192 bits) == A0 B0 C0 A1, B1 C1 A2 B2, C2 A3 B3 C3
8192 // i0 == A1 C0 B0 A0, i1 == B2 A2 C1 B1, i2 == C3 B3 A3 C2
8193 // u0 == A3 A2 A1 A0, u1 == B3 B2 B1 B0, u2 == C3 C2 C1 C0
8194 # define XXX(_tmp3,_la3,_tmp2,_la2,_tmp1,_la1,_tmp0,_la0) \
8196 IHI16x4(SHL64((_tmp3),48-16*(_la3)), \
8197 SHL64((_tmp2),48-16*(_la2))), \
8198 IHI16x4(SHL64((_tmp1),48-16*(_la1)), \
8199 SHL64((_tmp0),48-16*(_la0))))
8200 assign(*i0
, XXX(u0
,1, u2
,0, u1
,0, u0
,0));
8201 assign(*i1
, XXX(u1
,2, u0
,2, u2
,1, u1
,1));
8202 assign(*i2
, XXX(u2
,3, u1
,3, u0
,3, u2
,2));
8204 } else if (laneszB
== 1) {
8205 // These describe how the result vectors [7..0] are
8206 // assembled from the source vectors. Each pair is
8207 // (source vector number, lane number).
8208 static const UChar in0
[16] = {1,2, 0,2, 2,1, 1,1, 0,1, 2,0, 1,0, 0,0};
8209 static const UChar in1
[16] = {0,5, 2,4, 1,4, 0,4, 2,3, 1,3, 0,3, 2,2};
8210 static const UChar in2
[16] = {2,7, 1,7, 0,7, 2,6, 1,6, 0,6, 2,5, 1,5};
8211 assign(*i0
, math_PERM_8x8x3(in0
, u0
, u1
, u2
));
8212 assign(*i1
, math_PERM_8x8x3(in1
, u0
, u1
, u2
));
8213 assign(*i2
, math_PERM_8x8x3(in2
, u0
, u1
, u2
));
8215 // Can never happen, since VST3 only has valid lane widths of 32,
8217 vpanic("math_INTERLEAVE_3");
8224 /* Generate 4x64 -> 4x64 deinterleave code, for VLD4. Caller must
8225 make *u0, *u1, *u2 and *u3 be valid IRTemps before the call. */
8226 static void math_DEINTERLEAVE_4 (
8227 /*OUT*/IRTemp
* u0
, /*OUT*/IRTemp
* u1
,
8228 /*OUT*/IRTemp
* u2
, /*OUT*/IRTemp
* u3
,
8229 IRTemp i0
, IRTemp i1
, IRTemp i2
, IRTemp i3
, Int laneszB
8232 # define IHI32x2(_t1, _t2) \
8233 binop(Iop_InterleaveHI32x2, mkexpr(_t1), mkexpr(_t2))
8234 # define ILO32x2(_t1, _t2) \
8235 binop(Iop_InterleaveLO32x2, mkexpr(_t1), mkexpr(_t2))
8236 # define IHI16x4(_t1, _t2) \
8237 binop(Iop_InterleaveHI16x4, mkexpr(_t1), mkexpr(_t2))
8238 # define ILO16x4(_t1, _t2) \
8239 binop(Iop_InterleaveLO16x4, mkexpr(_t1), mkexpr(_t2))
8240 # define IHI8x8(_t1, _e2) \
8241 binop(Iop_InterleaveHI8x8, mkexpr(_t1), _e2)
8242 # define SHL64(_tmp, _amt) \
8243 binop(Iop_Shl64, mkexpr(_tmp), mkU8(_amt))
8244 /* The following assumes that the guest is little endian, and hence
8245 that the memory-side (interleaved) data is stored
8247 vassert(u0
&& u1
&& u2
&& u3
);
8249 assign(*u0
, ILO32x2(i2
, i0
));
8250 assign(*u1
, IHI32x2(i2
, i0
));
8251 assign(*u2
, ILO32x2(i3
, i1
));
8252 assign(*u3
, IHI32x2(i3
, i1
));
8253 } else if (laneszB
== 2) {
8254 IRTemp b1b0a1a0
= newTemp(Ity_I64
);
8255 IRTemp b3b2a3a2
= newTemp(Ity_I64
);
8256 IRTemp d1d0c1c0
= newTemp(Ity_I64
);
8257 IRTemp d3d2c3c2
= newTemp(Ity_I64
);
8258 assign(b1b0a1a0
, ILO16x4(i1
, i0
));
8259 assign(b3b2a3a2
, ILO16x4(i3
, i2
));
8260 assign(d1d0c1c0
, IHI16x4(i1
, i0
));
8261 assign(d3d2c3c2
, IHI16x4(i3
, i2
));
8262 // And now do what we did for the 32-bit case.
8263 assign(*u0
, ILO32x2(b3b2a3a2
, b1b0a1a0
));
8264 assign(*u1
, IHI32x2(b3b2a3a2
, b1b0a1a0
));
8265 assign(*u2
, ILO32x2(d3d2c3c2
, d1d0c1c0
));
8266 assign(*u3
, IHI32x2(d3d2c3c2
, d1d0c1c0
));
8267 } else if (laneszB
== 1) {
8268 // Deinterleave into 16-bit chunks, then do as the 16-bit case.
8269 IRTemp i0x
= newTemp(Ity_I64
);
8270 IRTemp i1x
= newTemp(Ity_I64
);
8271 IRTemp i2x
= newTemp(Ity_I64
);
8272 IRTemp i3x
= newTemp(Ity_I64
);
8273 assign(i0x
, IHI8x8(i0
, SHL64(i0
, 32)));
8274 assign(i1x
, IHI8x8(i1
, SHL64(i1
, 32)));
8275 assign(i2x
, IHI8x8(i2
, SHL64(i2
, 32)));
8276 assign(i3x
, IHI8x8(i3
, SHL64(i3
, 32)));
8277 // From here on is like the 16 bit case.
8278 IRTemp b1b0a1a0
= newTemp(Ity_I64
);
8279 IRTemp b3b2a3a2
= newTemp(Ity_I64
);
8280 IRTemp d1d0c1c0
= newTemp(Ity_I64
);
8281 IRTemp d3d2c3c2
= newTemp(Ity_I64
);
8282 assign(b1b0a1a0
, ILO16x4(i1x
, i0x
));
8283 assign(b3b2a3a2
, ILO16x4(i3x
, i2x
));
8284 assign(d1d0c1c0
, IHI16x4(i1x
, i0x
));
8285 assign(d3d2c3c2
, IHI16x4(i3x
, i2x
));
8286 // And now do what we did for the 32-bit case.
8287 assign(*u0
, ILO32x2(b3b2a3a2
, b1b0a1a0
));
8288 assign(*u1
, IHI32x2(b3b2a3a2
, b1b0a1a0
));
8289 assign(*u2
, ILO32x2(d3d2c3c2
, d1d0c1c0
));
8290 assign(*u3
, IHI32x2(d3d2c3c2
, d1d0c1c0
));
8292 // Can never happen, since VLD4 only has valid lane widths of 32,
8294 vpanic("math_DEINTERLEAVE_4");
8304 /* Generate 4x64 -> 4x64 interleave code, for VST4. Caller must
8305 make *i0, *i1, *i2 and *i3 be valid IRTemps before the call. */
8306 static void math_INTERLEAVE_4 (
8307 /*OUT*/IRTemp
* i0
, /*OUT*/IRTemp
* i1
,
8308 /*OUT*/IRTemp
* i2
, /*OUT*/IRTemp
* i3
,
8309 IRTemp u0
, IRTemp u1
, IRTemp u2
, IRTemp u3
, Int laneszB
8312 # define IHI32x2(_t1, _t2) \
8313 binop(Iop_InterleaveHI32x2, mkexpr(_t1), mkexpr(_t2))
8314 # define ILO32x2(_t1, _t2) \
8315 binop(Iop_InterleaveLO32x2, mkexpr(_t1), mkexpr(_t2))
8316 # define CEV16x4(_t1, _t2) \
8317 binop(Iop_CatEvenLanes16x4, mkexpr(_t1), mkexpr(_t2))
8318 # define COD16x4(_t1, _t2) \
8319 binop(Iop_CatOddLanes16x4, mkexpr(_t1), mkexpr(_t2))
8320 # define COD8x8(_t1, _e2) \
8321 binop(Iop_CatOddLanes8x8, mkexpr(_t1), _e2)
8322 # define SHL64(_tmp, _amt) \
8323 binop(Iop_Shl64, mkexpr(_tmp), mkU8(_amt))
8324 /* The following assumes that the guest is little endian, and hence
8325 that the memory-side (interleaved) data is stored
8327 vassert(u0
&& u1
&& u2
&& u3
);
8329 assign(*i0
, ILO32x2(u1
, u0
));
8330 assign(*i1
, ILO32x2(u3
, u2
));
8331 assign(*i2
, IHI32x2(u1
, u0
));
8332 assign(*i3
, IHI32x2(u3
, u2
));
8333 } else if (laneszB
== 2) {
8334 // First, interleave at the 32-bit lane size.
8335 IRTemp b1b0a1a0
= newTemp(Ity_I64
);
8336 IRTemp b3b2a3a2
= newTemp(Ity_I64
);
8337 IRTemp d1d0c1c0
= newTemp(Ity_I64
);
8338 IRTemp d3d2c3c2
= newTemp(Ity_I64
);
8339 assign(b1b0a1a0
, ILO32x2(u1
, u0
));
8340 assign(b3b2a3a2
, IHI32x2(u1
, u0
));
8341 assign(d1d0c1c0
, ILO32x2(u3
, u2
));
8342 assign(d3d2c3c2
, IHI32x2(u3
, u2
));
8343 // And interleave (cat) at the 16 bit size.
8344 assign(*i0
, CEV16x4(d1d0c1c0
, b1b0a1a0
));
8345 assign(*i1
, COD16x4(d1d0c1c0
, b1b0a1a0
));
8346 assign(*i2
, CEV16x4(d3d2c3c2
, b3b2a3a2
));
8347 assign(*i3
, COD16x4(d3d2c3c2
, b3b2a3a2
));
8348 } else if (laneszB
== 1) {
8349 // First, interleave at the 32-bit lane size.
8350 IRTemp b1b0a1a0
= newTemp(Ity_I64
);
8351 IRTemp b3b2a3a2
= newTemp(Ity_I64
);
8352 IRTemp d1d0c1c0
= newTemp(Ity_I64
);
8353 IRTemp d3d2c3c2
= newTemp(Ity_I64
);
8354 assign(b1b0a1a0
, ILO32x2(u1
, u0
));
8355 assign(b3b2a3a2
, IHI32x2(u1
, u0
));
8356 assign(d1d0c1c0
, ILO32x2(u3
, u2
));
8357 assign(d3d2c3c2
, IHI32x2(u3
, u2
));
8358 // And interleave (cat) at the 16 bit size.
8359 IRTemp i0x
= newTemp(Ity_I64
);
8360 IRTemp i1x
= newTemp(Ity_I64
);
8361 IRTemp i2x
= newTemp(Ity_I64
);
8362 IRTemp i3x
= newTemp(Ity_I64
);
8363 assign(i0x
, CEV16x4(d1d0c1c0
, b1b0a1a0
));
8364 assign(i1x
, COD16x4(d1d0c1c0
, b1b0a1a0
));
8365 assign(i2x
, CEV16x4(d3d2c3c2
, b3b2a3a2
));
8366 assign(i3x
, COD16x4(d3d2c3c2
, b3b2a3a2
));
8367 // And rearrange within each word, to get the right 8 bit lanes.
8368 assign(*i0
, COD8x8(i0x
, SHL64(i0x
, 8)));
8369 assign(*i1
, COD8x8(i1x
, SHL64(i1x
, 8)));
8370 assign(*i2
, COD8x8(i2x
, SHL64(i2x
, 8)));
8371 assign(*i3
, COD8x8(i3x
, SHL64(i3x
, 8)));
8373 // Can never happen, since VLD4 only has valid lane widths of 32,
8375 vpanic("math_DEINTERLEAVE_4");
8385 /* A7.7 Advanced SIMD element or structure load/store instructions */
8387 Bool
dis_neon_load_or_store ( UInt theInstr
,
8388 Bool isT
, IRTemp condT
)
8390 # define INSN(_bMax,_bMin) SLICE_UInt(theInstr, (_bMax), (_bMin))
8391 UInt bA
= INSN(23,23);
8392 UInt fB
= INSN(11,8);
8393 UInt bL
= INSN(21,21);
8394 UInt rD
= (INSN(22,22) << 4) | INSN(15,12);
8395 UInt rN
= INSN(19,16);
8396 UInt rM
= INSN(3,0);
8402 vassert(condT
!= IRTemp_INVALID
);
8404 vassert(condT
== IRTemp_INVALID
);
8406 /* So now, if condT is not IRTemp_INVALID, we know we're
8407 dealing with Thumb code. */
8409 if (INSN(20,20) != 0)
8412 IRTemp initialRn
= newTemp(Ity_I32
);
8413 assign(initialRn
, isT
? getIRegT(rN
) : getIRegA(rN
));
8415 IRTemp initialRm
= newTemp(Ity_I32
);
8416 assign(initialRm
, isT
? getIRegT(rM
) : getIRegA(rM
));
8418 /* There are 3 cases:
8419 (1) VSTn / VLDn (n-element structure from/to one lane)
8420 (2) VLDn (single element to all lanes)
8421 (3) VSTn / VLDn (multiple n-element structures)
8425 if ((fB
>> 2) < 3) {
8426 /* ------------ Case (1) ------------
8427 VSTn / VLDn (n-element structure from/to one lane) */
8432 case 0: i
= INSN(7,5); inc
= 1; break;
8433 case 1: i
= INSN(7,6); inc
= INSN(5,5) ? 2 : 1; break;
8434 case 2: i
= INSN(7,7); inc
= INSN(6,6) ? 2 : 1; break;
8435 case 3: return False
;
8436 default: vassert(0);
8439 IRTemp addr
= newTemp(Ity_I32
);
8440 assign(addr
, mkexpr(initialRn
));
8443 if (condT
!= IRTemp_INVALID
)
8444 mk_skip_over_T32_if_cond_is_false(condT
);
8448 mk_neon_elem_load_to_one_lane(rD
, inc
, i
, N
, size
, addr
);
8450 mk_neon_elem_store_from_one_lane(rD
, inc
, i
, N
, size
, addr
);
8451 DIP("v%s%u.%d {", bL
? "ld" : "st", N
+ 1, 8 << size
);
8452 for (j
= 0; j
<= N
; j
++) {
8455 DIP("d%u[%u]", rD
+ j
* inc
, i
);
8457 DIP("}, [r%u]", rN
);
8458 if (rM
!= 13 && rM
!= 15) {
8461 DIP("%s\n", (rM
!= 15) ? "!" : "");
8464 /* ------------ Case (2) ------------
8465 VLDn (single element to all lanes) */
8470 inc
= INSN(5,5) + 1;
8473 /* size == 3 and size == 2 cases differ in alignment constraints */
8474 if (size
== 3 && N
== 3 && INSN(4,4) == 1)
8477 if (size
== 0 && N
== 0 && INSN(4,4) == 1)
8479 if (N
== 2 && INSN(4,4) == 1)
8485 if (condT
!= IRTemp_INVALID
)
8486 mk_skip_over_T32_if_cond_is_false(condT
);
8489 IRTemp addr
= newTemp(Ity_I32
);
8490 assign(addr
, mkexpr(initialRn
));
8492 if (N
== 0 && INSN(5,5))
8495 for (r
= 0; r
< regs
; r
++) {
8498 putDRegI64(rD
+ r
, unop(Iop_Dup8x8
,
8499 loadLE(Ity_I8
, mkexpr(addr
))),
8503 putDRegI64(rD
+ r
, unop(Iop_Dup16x4
,
8504 loadLE(Ity_I16
, mkexpr(addr
))),
8508 putDRegI64(rD
+ r
, unop(Iop_Dup32x2
,
8509 loadLE(Ity_I32
, mkexpr(addr
))),
8515 for (i
= 1; i
<= N
; i
++) {
8518 putDRegI64(rD
+ r
+ i
* inc
,
8520 loadLE(Ity_I8
, binop(Iop_Add32
,
8526 putDRegI64(rD
+ r
+ i
* inc
,
8528 loadLE(Ity_I16
, binop(Iop_Add32
,
8534 putDRegI64(rD
+ r
+ i
* inc
,
8536 loadLE(Ity_I32
, binop(Iop_Add32
,
8546 DIP("vld%u.%d {", N
+ 1, 8 << size
);
8547 for (r
= 0; r
< regs
; r
++) {
8548 for (i
= 0; i
<= N
; i
++) {
8551 DIP("d%u[]", rD
+ r
+ i
* inc
);
8554 DIP("}, [r%u]", rN
);
8555 if (rM
!= 13 && rM
!= 15) {
8558 DIP("%s\n", (rM
!= 15) ? "!" : "");
8561 /* Writeback. We're uncond here, so no condT-ing. */
8564 IRExpr
* e
= binop(Iop_Add32
,
8566 mkU32((1 << size
) * (N
+ 1)));
8568 putIRegT(rN
, e
, IRTemp_INVALID
);
8570 putIRegA(rN
, e
, IRTemp_INVALID
, Ijk_Boring
);
8572 IRExpr
* e
= binop(Iop_Add32
,
8576 putIRegT(rN
, e
, IRTemp_INVALID
);
8578 putIRegA(rN
, e
, IRTemp_INVALID
, Ijk_Boring
);
8583 /* ------------ Case (3) ------------
8584 VSTn / VLDn (multiple n-element structures) */
8587 if (fB
== BITS4(0,0,1,0) // Dd, Dd+1, Dd+2, Dd+3 inc = 1 regs = 4
8588 || fB
== BITS4(0,1,1,0) // Dd, Dd+1, Dd+2 inc = 1 regs = 3
8589 || fB
== BITS4(0,1,1,1) // Dd inc = 2 regs = 1
8590 || fB
== BITS4(1,0,1,0)) { // Dd, Dd+1 inc = 1 regs = 2
8591 N
= 0; // VLD1/VST1. 'inc' does not appear to have any
8592 // meaning for the VLD1/VST1 cases. 'regs' is the number of
8593 // registers involved.
8594 if (rD
+ regs
> 32) return False
;
8597 if (fB
== BITS4(0,0,1,1) // Dd, Dd+1, Dd+2, Dd+3 inc=2 regs = 2
8598 || fB
== BITS4(1,0,0,0) // Dd, Dd+1 inc=1 regs = 1
8599 || fB
== BITS4(1,0,0,1)) { // Dd, Dd+2 inc=2 regs = 1
8600 N
= 1; // VLD2/VST2. 'regs' is the number of register-pairs involved
8601 if (regs
== 1 && inc
== 1 && rD
+ 1 >= 32) return False
;
8602 if (regs
== 1 && inc
== 2 && rD
+ 2 >= 32) return False
;
8603 if (regs
== 2 && inc
== 2 && rD
+ 3 >= 32) return False
;
8604 } else if (fB
== BITS4(0,1,0,0) || fB
== BITS4(0,1,0,1)) {
8606 if (inc
== 1 && rD
+ 2 >= 32) return False
;
8607 if (inc
== 2 && rD
+ 4 >= 32) return False
;
8608 } else if (fB
== BITS4(0,0,0,0) || fB
== BITS4(0,0,0,1)) {
8610 if (inc
== 1 && rD
+ 3 >= 32) return False
;
8611 if (inc
== 2 && rD
+ 6 >= 32) return False
;
8616 if (N
== 1 && fB
== BITS4(0,0,1,1)) {
8618 } else if (N
== 0) {
8619 if (fB
== BITS4(1,0,1,0)) {
8621 } else if (fB
== BITS4(0,1,1,0)) {
8623 } else if (fB
== BITS4(0,0,1,0)) {
8629 if (N
== 0 && size
== 3)
8635 if (condT
!= IRTemp_INVALID
)
8636 mk_skip_over_T32_if_cond_is_false(condT
);
8639 IRTemp addr
= newTemp(Ity_I32
);
8640 assign(addr
, mkexpr(initialRn
));
8642 if (N
== 0 /* No interleaving -- VLD1/VST1 */) {
8644 vassert(regs
== 1 || regs
== 2 || regs
== 3 || regs
== 4);
8645 /* inc has no relevance here */
8646 for (r
= 0; r
< regs
; r
++) {
8648 putDRegI64(rD
+r
, loadLE(Ity_I64
, mkexpr(addr
)), IRTemp_INVALID
);
8650 storeLE(mkexpr(addr
), getDRegI64(rD
+r
));
8651 IRTemp tmp
= newTemp(Ity_I32
);
8652 assign(tmp
, binop(Iop_Add32
, mkexpr(addr
), mkU32(8)));
8657 if (N
== 1 /* 2-interleaving -- VLD2/VST2 */) {
8658 vassert( (regs
== 1 && (inc
== 1 || inc
== 2))
8659 || (regs
== 2 && inc
== 2) );
8660 // Make 'nregs' be the number of registers and 'regstep'
8661 // equal the actual register-step. The ARM encoding, using 'regs'
8662 // and 'inc', is bizarre. After this, we have:
8663 // Dd, Dd+1 regs = 1, inc = 1, nregs = 2, regstep = 1
8664 // Dd, Dd+2 regs = 1, inc = 2, nregs = 2, regstep = 2
8665 // Dd, Dd+1, Dd+2, Dd+3 regs = 2, inc = 2, nregs = 4, regstep = 1
8668 if (regs
== 1 && inc
== 1) {
8670 } else if (regs
== 1 && inc
== 2) {
8672 } else if (regs
== 2 && inc
== 2) {
8678 // 'di' is interleaved data, 'du' is uninterleaved data
8680 IRExpr
* a0
= binop(Iop_Add32
, mkexpr(addr
), mkU32(0));
8681 IRExpr
* a1
= binop(Iop_Add32
, mkexpr(addr
), mkU32(8));
8682 IRTemp di0
= newTemp(Ity_I64
);
8683 IRTemp di1
= newTemp(Ity_I64
);
8684 IRTemp du0
= newTemp(Ity_I64
);
8685 IRTemp du1
= newTemp(Ity_I64
);
8687 assign(di0
, loadLE(Ity_I64
, a0
));
8688 assign(di1
, loadLE(Ity_I64
, a1
));
8689 math_DEINTERLEAVE_2(&du0
, &du1
, di0
, di1
, 1 << size
);
8690 putDRegI64(rD
+ 0 * regstep
, mkexpr(du0
), IRTemp_INVALID
);
8691 putDRegI64(rD
+ 1 * regstep
, mkexpr(du1
), IRTemp_INVALID
);
8693 assign(du0
, getDRegI64(rD
+ 0 * regstep
));
8694 assign(du1
, getDRegI64(rD
+ 1 * regstep
));
8695 math_INTERLEAVE_2(&di0
, &di1
, du0
, du1
, 1 << size
);
8696 storeLE(a0
, mkexpr(di0
));
8697 storeLE(a1
, mkexpr(di1
));
8699 IRTemp tmp
= newTemp(Ity_I32
);
8700 assign(tmp
, binop(Iop_Add32
, mkexpr(addr
), mkU32(16)));
8703 vassert(nregs
== 4);
8704 vassert(regstep
== 1);
8705 IRExpr
* a0
= binop(Iop_Add32
, mkexpr(addr
), mkU32(0));
8706 IRExpr
* a1
= binop(Iop_Add32
, mkexpr(addr
), mkU32(8));
8707 IRExpr
* a2
= binop(Iop_Add32
, mkexpr(addr
), mkU32(16));
8708 IRExpr
* a3
= binop(Iop_Add32
, mkexpr(addr
), mkU32(24));
8709 IRTemp di0
= newTemp(Ity_I64
);
8710 IRTemp di1
= newTemp(Ity_I64
);
8711 IRTemp di2
= newTemp(Ity_I64
);
8712 IRTemp di3
= newTemp(Ity_I64
);
8713 IRTemp du0
= newTemp(Ity_I64
);
8714 IRTemp du1
= newTemp(Ity_I64
);
8715 IRTemp du2
= newTemp(Ity_I64
);
8716 IRTemp du3
= newTemp(Ity_I64
);
8718 assign(di0
, loadLE(Ity_I64
, a0
));
8719 assign(di1
, loadLE(Ity_I64
, a1
));
8720 assign(di2
, loadLE(Ity_I64
, a2
));
8721 assign(di3
, loadLE(Ity_I64
, a3
));
8722 // Note spooky interleaving: du0, du2, di0, di1 etc
8723 math_DEINTERLEAVE_2(&du0
, &du2
, di0
, di1
, 1 << size
);
8724 math_DEINTERLEAVE_2(&du1
, &du3
, di2
, di3
, 1 << size
);
8725 putDRegI64(rD
+ 0 * regstep
, mkexpr(du0
), IRTemp_INVALID
);
8726 putDRegI64(rD
+ 1 * regstep
, mkexpr(du1
), IRTemp_INVALID
);
8727 putDRegI64(rD
+ 2 * regstep
, mkexpr(du2
), IRTemp_INVALID
);
8728 putDRegI64(rD
+ 3 * regstep
, mkexpr(du3
), IRTemp_INVALID
);
8730 assign(du0
, getDRegI64(rD
+ 0 * regstep
));
8731 assign(du1
, getDRegI64(rD
+ 1 * regstep
));
8732 assign(du2
, getDRegI64(rD
+ 2 * regstep
));
8733 assign(du3
, getDRegI64(rD
+ 3 * regstep
));
8734 // Note spooky interleaving: du0, du2, di0, di1 etc
8735 math_INTERLEAVE_2(&di0
, &di1
, du0
, du2
, 1 << size
);
8736 math_INTERLEAVE_2(&di2
, &di3
, du1
, du3
, 1 << size
);
8737 storeLE(a0
, mkexpr(di0
));
8738 storeLE(a1
, mkexpr(di1
));
8739 storeLE(a2
, mkexpr(di2
));
8740 storeLE(a3
, mkexpr(di3
));
8743 IRTemp tmp
= newTemp(Ity_I32
);
8744 assign(tmp
, binop(Iop_Add32
, mkexpr(addr
), mkU32(32)));
8749 if (N
== 2 /* 3-interleaving -- VLD3/VST3 */) {
8750 // Dd, Dd+1, Dd+2 regs = 1, inc = 1
8751 // Dd, Dd+2, Dd+4 regs = 1, inc = 2
8752 vassert(regs
== 1 && (inc
== 1 || inc
== 2));
8753 IRExpr
* a0
= binop(Iop_Add32
, mkexpr(addr
), mkU32(0));
8754 IRExpr
* a1
= binop(Iop_Add32
, mkexpr(addr
), mkU32(8));
8755 IRExpr
* a2
= binop(Iop_Add32
, mkexpr(addr
), mkU32(16));
8756 IRTemp di0
= newTemp(Ity_I64
);
8757 IRTemp di1
= newTemp(Ity_I64
);
8758 IRTemp di2
= newTemp(Ity_I64
);
8759 IRTemp du0
= newTemp(Ity_I64
);
8760 IRTemp du1
= newTemp(Ity_I64
);
8761 IRTemp du2
= newTemp(Ity_I64
);
8763 assign(di0
, loadLE(Ity_I64
, a0
));
8764 assign(di1
, loadLE(Ity_I64
, a1
));
8765 assign(di2
, loadLE(Ity_I64
, a2
));
8766 math_DEINTERLEAVE_3(&du0
, &du1
, &du2
, di0
, di1
, di2
, 1 << size
);
8767 putDRegI64(rD
+ 0 * inc
, mkexpr(du0
), IRTemp_INVALID
);
8768 putDRegI64(rD
+ 1 * inc
, mkexpr(du1
), IRTemp_INVALID
);
8769 putDRegI64(rD
+ 2 * inc
, mkexpr(du2
), IRTemp_INVALID
);
8771 assign(du0
, getDRegI64(rD
+ 0 * inc
));
8772 assign(du1
, getDRegI64(rD
+ 1 * inc
));
8773 assign(du2
, getDRegI64(rD
+ 2 * inc
));
8774 math_INTERLEAVE_3(&di0
, &di1
, &di2
, du0
, du1
, du2
, 1 << size
);
8775 storeLE(a0
, mkexpr(di0
));
8776 storeLE(a1
, mkexpr(di1
));
8777 storeLE(a2
, mkexpr(di2
));
8779 IRTemp tmp
= newTemp(Ity_I32
);
8780 assign(tmp
, binop(Iop_Add32
, mkexpr(addr
), mkU32(24)));
8784 if (N
== 3 /* 4-interleaving -- VLD4/VST4 */) {
8785 // Dd, Dd+1, Dd+2, Dd+3 regs = 1, inc = 1
8786 // Dd, Dd+2, Dd+4, Dd+6 regs = 1, inc = 2
8787 vassert(regs
== 1 && (inc
== 1 || inc
== 2));
8788 IRExpr
* a0
= binop(Iop_Add32
, mkexpr(addr
), mkU32(0));
8789 IRExpr
* a1
= binop(Iop_Add32
, mkexpr(addr
), mkU32(8));
8790 IRExpr
* a2
= binop(Iop_Add32
, mkexpr(addr
), mkU32(16));
8791 IRExpr
* a3
= binop(Iop_Add32
, mkexpr(addr
), mkU32(24));
8792 IRTemp di0
= newTemp(Ity_I64
);
8793 IRTemp di1
= newTemp(Ity_I64
);
8794 IRTemp di2
= newTemp(Ity_I64
);
8795 IRTemp di3
= newTemp(Ity_I64
);
8796 IRTemp du0
= newTemp(Ity_I64
);
8797 IRTemp du1
= newTemp(Ity_I64
);
8798 IRTemp du2
= newTemp(Ity_I64
);
8799 IRTemp du3
= newTemp(Ity_I64
);
8801 assign(di0
, loadLE(Ity_I64
, a0
));
8802 assign(di1
, loadLE(Ity_I64
, a1
));
8803 assign(di2
, loadLE(Ity_I64
, a2
));
8804 assign(di3
, loadLE(Ity_I64
, a3
));
8805 math_DEINTERLEAVE_4(&du0
, &du1
, &du2
, &du3
,
8806 di0
, di1
, di2
, di3
, 1 << size
);
8807 putDRegI64(rD
+ 0 * inc
, mkexpr(du0
), IRTemp_INVALID
);
8808 putDRegI64(rD
+ 1 * inc
, mkexpr(du1
), IRTemp_INVALID
);
8809 putDRegI64(rD
+ 2 * inc
, mkexpr(du2
), IRTemp_INVALID
);
8810 putDRegI64(rD
+ 3 * inc
, mkexpr(du3
), IRTemp_INVALID
);
8812 assign(du0
, getDRegI64(rD
+ 0 * inc
));
8813 assign(du1
, getDRegI64(rD
+ 1 * inc
));
8814 assign(du2
, getDRegI64(rD
+ 2 * inc
));
8815 assign(du3
, getDRegI64(rD
+ 3 * inc
));
8816 math_INTERLEAVE_4(&di0
, &di1
, &di2
, &di3
,
8817 du0
, du1
, du2
, du3
, 1 << size
);
8818 storeLE(a0
, mkexpr(di0
));
8819 storeLE(a1
, mkexpr(di1
));
8820 storeLE(a2
, mkexpr(di2
));
8821 storeLE(a3
, mkexpr(di3
));
8823 IRTemp tmp
= newTemp(Ity_I32
);
8824 assign(tmp
, binop(Iop_Add32
, mkexpr(addr
), mkU32(32)));
8835 e
= binop(Iop_Add32
, mkexpr(initialRn
),
8836 mkU32(8 * (N
+ 1) * regs
));
8838 e
= binop(Iop_Add32
, mkexpr(initialRn
),
8842 putIRegT(rN
, e
, IRTemp_INVALID
);
8844 putIRegA(rN
, e
, IRTemp_INVALID
, Ijk_Boring
);
8847 DIP("v%s%u.%d {", bL
? "ld" : "st", N
+ 1, 8 << INSN(7,6));
8848 if ((inc
== 1 && regs
* (N
+ 1) > 1)
8849 || (inc
== 2 && regs
> 1 && N
> 0)) {
8850 DIP("d%u-d%u", rD
, rD
+ regs
* (N
+ 1) - 1);
8853 for (r
= 0; r
< regs
; r
++) {
8854 for (i
= 0; i
<= N
; i
++) {
8857 DIP("d%u", rD
+ r
+ i
* inc
);
8861 DIP("}, [r%u]", rN
);
8862 if (rM
!= 13 && rM
!= 15) {
8865 DIP("%s\n", (rM
!= 15) ? "!" : "");
8873 /*------------------------------------------------------------*/
8874 /*--- NEON, top level control ---*/
8875 /*------------------------------------------------------------*/
8877 /* Both ARM and Thumb */
8879 /* Translate a NEON instruction. If successful, returns
8880 True and *dres may or may not be updated. If failure, returns
8881 False and doesn't change *dres nor create any IR.
8883 The Thumb and ARM encodings are similar for the 24 bottom bits, but
8884 the top 8 bits are slightly different. In both cases, the caller
8885 must pass the entire 32 bits. Callers may pass any instruction;
8886 this ignores non-NEON ones.
8888 Caller must supply an IRTemp 'condT' holding the gating condition,
8889 or IRTemp_INVALID indicating the insn is always executed. In ARM
8890 code, this must always be IRTemp_INVALID because NEON insns are
8891 unconditional for ARM.
8893 Finally, the caller must indicate whether this occurs in ARM or in
8896 This only handles NEON for ARMv7 and below. The NEON extensions
8897 for v8 are handled by decode_V8_instruction.
8899 static Bool
decode_NEON_instruction_ARMv7_and_below (
8900 /*MOD*/DisResult
* dres
,
8906 # define INSN(_bMax,_bMin) SLICE_UInt(insn32, (_bMax), (_bMin))
8908 /* There are two kinds of instruction to deal with: load/store and
8909 data processing. In each case, in ARM mode we merely identify
8910 the kind, and pass it on to the relevant sub-handler. In Thumb
8911 mode we identify the kind, swizzle the bits around to make it
8912 have the same encoding as in ARM, and hand it on to the
8916 /* In ARM mode, NEON instructions can't be conditional. */
8918 vassert(condT
== IRTemp_INVALID
);
8921 Thumb: 111U 1111 AAAA Axxx xxxx BBBB CCCC xxxx
8922 ARM: 1111 001U AAAA Axxx xxxx BBBB CCCC xxxx
8924 if (!isT
&& INSN(31,25) == BITS7(1,1,1,1,0,0,1)) {
8926 return dis_neon_data_processing(INSN(31,0), condT
);
8928 if (isT
&& INSN(31,29) == BITS3(1,1,1)
8929 && INSN(27,24) == BITS4(1,1,1,1)) {
8931 UInt reformatted
= INSN(23,0);
8932 reformatted
|= (((UInt
)INSN(28,28)) << 24); // U bit
8933 reformatted
|= (((UInt
)BITS7(1,1,1,1,0,0,1)) << 25);
8934 return dis_neon_data_processing(reformatted
, condT
);
8938 Thumb: 1111 1001 AxL0 xxxx xxxx BBBB xxxx xxxx
8939 ARM: 1111 0100 AxL0 xxxx xxxx BBBB xxxx xxxx
8941 if (!isT
&& INSN(31,24) == BITS8(1,1,1,1,0,1,0,0)) {
8943 return dis_neon_load_or_store(INSN(31,0), isT
, condT
);
8945 if (isT
&& INSN(31,24) == BITS8(1,1,1,1,1,0,0,1)) {
8946 UInt reformatted
= INSN(23,0);
8947 reformatted
|= (((UInt
)BITS8(1,1,1,1,0,1,0,0)) << 24);
8948 return dis_neon_load_or_store(reformatted
, isT
, condT
);
8951 /* Doesn't match. */
8958 /*------------------------------------------------------------*/
8959 /*--- V6 MEDIA instructions ---*/
8960 /*------------------------------------------------------------*/
8962 /* Both ARM and Thumb */
8964 /* Translate a V6 media instruction. If successful, returns
8965 True and *dres may or may not be updated. If failure, returns
8966 False and doesn't change *dres nor create any IR.
8968 The Thumb and ARM encodings are completely different. In Thumb
8969 mode, the caller must pass the entire 32 bits. In ARM mode it must
8970 pass the lower 28 bits. Apart from that, callers may pass any
8971 instruction; this function ignores anything it doesn't recognise.
8973 Caller must supply an IRTemp 'condT' holding the gating condition,
8974 or IRTemp_INVALID indicating the insn is always executed.
8976 Caller must also supply an ARMCondcode 'conq'. This is only used
8977 for debug printing, no other purpose. For ARM, this is simply the
8978 top 4 bits of the original instruction. For Thumb, the condition
8979 is not (really) known until run time, and so ARMCondAL should be
8980 passed, only so that printing of these instructions does not show
8983 Finally, the caller must indicate whether this occurs in ARM or in
8986 static Bool
decode_V6MEDIA_instruction (
8987 /*MOD*/DisResult
* dres
,
8994 # define INSNA(_bMax,_bMin) SLICE_UInt(insnv6m, (_bMax), (_bMin))
8995 # define INSNT0(_bMax,_bMin) SLICE_UInt( ((insnv6m >> 16) & 0xFFFF), \
8997 # define INSNT1(_bMax,_bMin) SLICE_UInt( ((insnv6m >> 0) & 0xFFFF), \
9003 vassert(conq
== ARMCondAL
);
9005 vassert(INSNA(31,28) == BITS4(0,0,0,0)); // caller's obligation
9006 vassert(conq
>= ARMCondEQ
&& conq
<= ARMCondAL
);
9009 /* ----------- smulbb, smulbt, smultb, smultt ----------- */
9011 UInt regD
= 99, regM
= 99, regN
= 99, bitM
= 0, bitN
= 0;
9015 if (INSNT0(15,4) == 0xFB1 && INSNT1(15,12) == BITS4(1,1,1,1)
9016 && INSNT1(7,6) == BITS2(0,0)) {
9017 regD
= INSNT1(11,8);
9022 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9026 if (BITS8(0,0,0,1,0,1,1,0) == INSNA(27,20) &&
9027 BITS4(0,0,0,0) == INSNA(15,12) &&
9028 BITS4(1,0,0,0) == (INSNA(7,4) & BITS4(1,0,0,1)) ) {
9029 regD
= INSNA(19,16);
9034 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9040 IRTemp srcN
= newTemp(Ity_I32
);
9041 IRTemp srcM
= newTemp(Ity_I32
);
9042 IRTemp res
= newTemp(Ity_I32
);
9044 assign( srcN
, binop(Iop_Sar32
,
9046 isT
? getIRegT(regN
) : getIRegA(regN
),
9047 mkU8(bitN
? 0 : 16)), mkU8(16)) );
9048 assign( srcM
, binop(Iop_Sar32
,
9050 isT
? getIRegT(regM
) : getIRegA(regM
),
9051 mkU8(bitM
? 0 : 16)), mkU8(16)) );
9052 assign( res
, binop(Iop_Mul32
, mkexpr(srcN
), mkexpr(srcM
)) );
9055 putIRegT( regD
, mkexpr(res
), condT
);
9057 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9059 DIP( "smul%c%c%s r%u, r%u, r%u\n", bitN
? 't' : 'b', bitM
? 't' : 'b',
9060 nCC(conq
), regD
, regN
, regM
);
9066 /* ------------ smulwb<y><c> <Rd>,<Rn>,<Rm> ------------- */
9067 /* ------------ smulwt<y><c> <Rd>,<Rn>,<Rm> ------------- */
9069 UInt regD
= 99, regN
= 99, regM
= 99, bitM
= 0;
9073 if (INSNT0(15,4) == 0xFB3 && INSNT1(15,12) == BITS4(1,1,1,1)
9074 && INSNT1(7,5) == BITS3(0,0,0)) {
9076 regD
= INSNT1(11,8);
9079 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9083 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
9084 INSNA(15,12) == BITS4(0,0,0,0) &&
9085 (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,1,0)) {
9086 regD
= INSNA(19,16);
9090 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9096 IRTemp irt_prod
= newTemp(Ity_I64
);
9100 isT
? getIRegT(regN
) : getIRegA(regN
),
9103 isT
? getIRegT(regM
) : getIRegA(regM
),
9104 mkU8(bitM
? 0 : 16)),
9107 IRExpr
* ire_result
= binop(Iop_Or32
,
9109 unop(Iop_64HIto32
, mkexpr(irt_prod
)),
9112 unop(Iop_64to32
, mkexpr(irt_prod
)),
9116 putIRegT( regD
, ire_result
, condT
);
9118 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
9120 DIP("smulw%c%s r%u, r%u, r%u\n",
9121 bitM
? 't' : 'b', nCC(conq
),regD
,regN
,regM
);
9127 /* ------------ pkhbt<c> Rd, Rn, Rm {,LSL #imm} ------------- */
9128 /* ------------ pkhtb<c> Rd, Rn, Rm {,ASR #imm} ------------- */
9130 UInt regD
= 99, regN
= 99, regM
= 99, imm5
= 99, shift_type
= 99;
9131 Bool tbform
= False
;
9135 if (INSNT0(15,4) == 0xEAC
9136 && INSNT1(15,15) == 0 && INSNT1(4,4) == 0) {
9138 regD
= INSNT1(11,8);
9140 imm5
= (INSNT1(14,12) << 2) | INSNT1(7,6);
9141 shift_type
= (INSNT1(5,5) << 1) | 0;
9142 tbform
= (INSNT1(5,5) == 0) ? False
: True
;
9143 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9147 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
9148 INSNA(5,4) == BITS2(0,1) /* &&
9149 (INSNA(6,6) == 0 || INSNA(6,6) == 1)
9150 This last bit with INSNA(6,6) is correct, but gcc 8 complains
9151 (correctly) that it is always true. So I commented it out
9152 to keep gcc quiet. */ ) {
9153 regD
= INSNA(15,12);
9154 regN
= INSNA(19,16);
9157 shift_type
= (INSNA(6,6) << 1) | 0;
9158 tbform
= (INSNA(6,6) == 0) ? False
: True
;
9159 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9165 IRTemp irt_regM
= newTemp(Ity_I32
);
9166 IRTemp irt_regM_shift
= newTemp(Ity_I32
);
9167 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9168 compute_result_and_C_after_shift_by_imm5(
9169 dis_buf
, &irt_regM_shift
, NULL
, irt_regM
, shift_type
, imm5
, regM
);
9171 UInt mask
= (tbform
== True
) ? 0x0000FFFF : 0xFFFF0000;
9174 binop(Iop_And32
, mkexpr(irt_regM_shift
), mkU32(mask
)),
9175 binop(Iop_And32
, isT
? getIRegT(regN
) : getIRegA(regN
),
9176 unop(Iop_Not32
, mkU32(mask
))) );
9179 putIRegT( regD
, ire_result
, condT
);
9181 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
9183 DIP( "pkh%s%s r%u, r%u, r%u %s\n", tbform
? "tb" : "bt",
9184 nCC(conq
), regD
, regN
, regM
, dis_buf
);
9191 /* ---------- usat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
9193 UInt regD
= 99, regN
= 99, shift_type
= 99, imm5
= 99, sat_imm
= 99;
9197 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,1,0)
9199 && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
9200 regD
= INSNT1(11,8);
9202 shift_type
= (INSNT0(5,5) << 1) | 0;
9203 imm5
= (INSNT1(14,12) << 2) | INSNT1(7,6);
9204 sat_imm
= INSNT1(4,0);
9205 if (!isBadRegT(regD
) && !isBadRegT(regN
))
9207 if (shift_type
== BITS2(1,0) && imm5
== 0)
9211 if (INSNA(27,21) == BITS7(0,1,1,0,1,1,1) &&
9212 INSNA(5,4) == BITS2(0,1)) {
9213 regD
= INSNA(15,12);
9215 shift_type
= (INSNA(6,6) << 1) | 0;
9217 sat_imm
= INSNA(20,16);
9218 if (regD
!= 15 && regN
!= 15)
9224 IRTemp irt_regN
= newTemp(Ity_I32
);
9225 IRTemp irt_regN_shift
= newTemp(Ity_I32
);
9226 IRTemp irt_sat_Q
= newTemp(Ity_I32
);
9227 IRTemp irt_result
= newTemp(Ity_I32
);
9229 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9230 compute_result_and_C_after_shift_by_imm5(
9231 dis_buf
, &irt_regN_shift
, NULL
,
9232 irt_regN
, shift_type
, imm5
, regN
);
9234 armUnsignedSatQ( &irt_result
, &irt_sat_Q
, irt_regN_shift
, sat_imm
);
9235 or_into_QFLAG32( mkexpr(irt_sat_Q
), condT
);
9238 putIRegT( regD
, mkexpr(irt_result
), condT
);
9240 putIRegA( regD
, mkexpr(irt_result
), condT
, Ijk_Boring
);
9242 DIP("usat%s r%u, #0x%04x, %s\n",
9243 nCC(conq
), regD
, imm5
, dis_buf
);
9249 /* ----------- ssat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
9251 UInt regD
= 99, regN
= 99, shift_type
= 99, imm5
= 99, sat_imm
= 99;
9255 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0)
9257 && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
9258 regD
= INSNT1(11,8);
9260 shift_type
= (INSNT0(5,5) << 1) | 0;
9261 imm5
= (INSNT1(14,12) << 2) | INSNT1(7,6);
9262 sat_imm
= INSNT1(4,0) + 1;
9263 if (!isBadRegT(regD
) && !isBadRegT(regN
))
9265 if (shift_type
== BITS2(1,0) && imm5
== 0)
9269 if (INSNA(27,21) == BITS7(0,1,1,0,1,0,1) &&
9270 INSNA(5,4) == BITS2(0,1)) {
9271 regD
= INSNA(15,12);
9273 shift_type
= (INSNA(6,6) << 1) | 0;
9275 sat_imm
= INSNA(20,16) + 1;
9276 if (regD
!= 15 && regN
!= 15)
9282 IRTemp irt_regN
= newTemp(Ity_I32
);
9283 IRTemp irt_regN_shift
= newTemp(Ity_I32
);
9284 IRTemp irt_sat_Q
= newTemp(Ity_I32
);
9285 IRTemp irt_result
= newTemp(Ity_I32
);
9287 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9288 compute_result_and_C_after_shift_by_imm5(
9289 dis_buf
, &irt_regN_shift
, NULL
,
9290 irt_regN
, shift_type
, imm5
, regN
);
9292 armSignedSatQ( irt_regN_shift
, sat_imm
, &irt_result
, &irt_sat_Q
);
9293 or_into_QFLAG32( mkexpr(irt_sat_Q
), condT
);
9296 putIRegT( regD
, mkexpr(irt_result
), condT
);
9298 putIRegA( regD
, mkexpr(irt_result
), condT
, Ijk_Boring
);
9300 DIP( "ssat%s r%u, #0x%04x, %s\n",
9301 nCC(conq
), regD
, imm5
, dis_buf
);
9307 /* ----------- ssat16<c> <Rd>,#<imm>,<Rn> ----------- */
9309 UInt regD
= 99, regN
= 99, sat_imm
= 99;
9313 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0)
9314 && INSNT0(5,4) == BITS2(1,0)
9315 && INSNT1(15,12) == BITS4(0,0,0,0)
9316 && INSNT1(7,4) == BITS4(0,0,0,0)) {
9317 regD
= INSNT1(11,8);
9319 sat_imm
= INSNT1(3,0) + 1;
9320 if (!isBadRegT(regD
) && !isBadRegT(regN
))
9324 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,1,0) &&
9325 INSNA(11,4) == BITS8(1,1,1,1,0,0,1,1)) {
9326 regD
= INSNA(15,12);
9328 sat_imm
= INSNA(19,16) + 1;
9329 if (regD
!= 15 && regN
!= 15)
9335 IRTemp irt_regN
= newTemp(Ity_I32
);
9336 IRTemp irt_regN_lo
= newTemp(Ity_I32
);
9337 IRTemp irt_regN_hi
= newTemp(Ity_I32
);
9338 IRTemp irt_Q_lo
= newTemp(Ity_I32
);
9339 IRTemp irt_Q_hi
= newTemp(Ity_I32
);
9340 IRTemp irt_res_lo
= newTemp(Ity_I32
);
9341 IRTemp irt_res_hi
= newTemp(Ity_I32
);
9343 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9344 assign( irt_regN_lo
,
9346 binop(Iop_Shl32
, mkexpr(irt_regN
), mkU8(16)),
9348 assign( irt_regN_hi
, binop(Iop_Sar32
, mkexpr(irt_regN
), mkU8(16)) );
9350 armSignedSatQ( irt_regN_lo
, sat_imm
, &irt_res_lo
, &irt_Q_lo
);
9351 or_into_QFLAG32( mkexpr(irt_Q_lo
), condT
);
9353 armSignedSatQ( irt_regN_hi
, sat_imm
, &irt_res_hi
, &irt_Q_hi
);
9354 or_into_QFLAG32( mkexpr(irt_Q_hi
), condT
);
9358 binop(Iop_And32
, mkexpr(irt_res_lo
), mkU32(0xFFFF)),
9359 binop(Iop_Shl32
, mkexpr(irt_res_hi
), mkU8(16)));
9361 putIRegT( regD
, ire_result
, condT
);
9363 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
9365 DIP( "ssat16%s r%u, #0x%04x, r%u\n", nCC(conq
), regD
, sat_imm
, regN
);
9371 /* -------------- usat16<c> <Rd>,#<imm4>,<Rn> --------------- */
9373 UInt regD
= 99, regN
= 99, sat_imm
= 99;
9377 if (INSNT0(15,4) == 0xF3A && (INSNT1(15,0) & 0xF0F0) == 0x0000) {
9379 regD
= INSNT1(11,8);
9380 sat_imm
= INSNT1(3,0);
9381 if (!isBadRegT(regD
) && !isBadRegT(regN
))
9385 if (INSNA(27,20) == BITS8(0,1,1,0,1,1,1,0) &&
9386 INSNA(11,8) == BITS4(1,1,1,1) &&
9387 INSNA(7,4) == BITS4(0,0,1,1)) {
9388 regD
= INSNA(15,12);
9390 sat_imm
= INSNA(19,16);
9391 if (regD
!= 15 && regN
!= 15)
9397 IRTemp irt_regN
= newTemp(Ity_I32
);
9398 IRTemp irt_regN_lo
= newTemp(Ity_I32
);
9399 IRTemp irt_regN_hi
= newTemp(Ity_I32
);
9400 IRTemp irt_Q_lo
= newTemp(Ity_I32
);
9401 IRTemp irt_Q_hi
= newTemp(Ity_I32
);
9402 IRTemp irt_res_lo
= newTemp(Ity_I32
);
9403 IRTemp irt_res_hi
= newTemp(Ity_I32
);
9405 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9406 assign( irt_regN_lo
, binop( Iop_Sar32
,
9407 binop(Iop_Shl32
, mkexpr(irt_regN
), mkU8(16)),
9409 assign( irt_regN_hi
, binop(Iop_Sar32
, mkexpr(irt_regN
), mkU8(16)) );
9411 armUnsignedSatQ( &irt_res_lo
, &irt_Q_lo
, irt_regN_lo
, sat_imm
);
9412 or_into_QFLAG32( mkexpr(irt_Q_lo
), condT
);
9414 armUnsignedSatQ( &irt_res_hi
, &irt_Q_hi
, irt_regN_hi
, sat_imm
);
9415 or_into_QFLAG32( mkexpr(irt_Q_hi
), condT
);
9417 IRExpr
* ire_result
= binop( Iop_Or32
,
9418 binop(Iop_Shl32
, mkexpr(irt_res_hi
), mkU8(16)),
9419 mkexpr(irt_res_lo
) );
9422 putIRegT( regD
, ire_result
, condT
);
9424 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
9426 DIP( "usat16%s r%u, #0x%04x, r%u\n", nCC(conq
), regD
, sat_imm
, regN
);
9432 /* -------------- uadd16<c> <Rd>,<Rn>,<Rm> -------------- */
9434 UInt regD
= 99, regN
= 99, regM
= 99;
9438 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
9440 regD
= INSNT1(11,8);
9442 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9446 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9447 INSNA(11,8) == BITS4(1,1,1,1) &&
9448 INSNA(7,4) == BITS4(0,0,0,1)) {
9449 regD
= INSNA(15,12);
9450 regN
= INSNA(19,16);
9452 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9458 IRTemp rNt
= newTemp(Ity_I32
);
9459 IRTemp rMt
= newTemp(Ity_I32
);
9460 IRTemp res
= newTemp(Ity_I32
);
9461 IRTemp reso
= newTemp(Ity_I32
);
9463 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9464 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9466 assign(res
, binop(Iop_Add16x2
, mkexpr(rNt
), mkexpr(rMt
)));
9468 putIRegT( regD
, mkexpr(res
), condT
);
9470 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9472 assign(reso
, binop(Iop_HAdd16Ux2
, mkexpr(rNt
), mkexpr(rMt
)));
9473 set_GE_32_10_from_bits_31_15(reso
, condT
);
9475 DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9481 /* -------------- sadd16<c> <Rd>,<Rn>,<Rm> -------------- */
9483 UInt regD
= 99, regN
= 99, regM
= 99;
9487 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9489 regD
= INSNT1(11,8);
9491 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9495 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9496 INSNA(11,8) == BITS4(1,1,1,1) &&
9497 INSNA(7,4) == BITS4(0,0,0,1)) {
9498 regD
= INSNA(15,12);
9499 regN
= INSNA(19,16);
9501 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9507 IRTemp rNt
= newTemp(Ity_I32
);
9508 IRTemp rMt
= newTemp(Ity_I32
);
9509 IRTemp res
= newTemp(Ity_I32
);
9510 IRTemp reso
= newTemp(Ity_I32
);
9512 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9513 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9515 assign(res
, binop(Iop_Add16x2
, mkexpr(rNt
), mkexpr(rMt
)));
9517 putIRegT( regD
, mkexpr(res
), condT
);
9519 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9521 assign(reso
, unop(Iop_Not32
,
9522 binop(Iop_HAdd16Sx2
, mkexpr(rNt
), mkexpr(rMt
))));
9523 set_GE_32_10_from_bits_31_15(reso
, condT
);
9525 DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9531 /* ---------------- usub16<c> <Rd>,<Rn>,<Rm> ---------------- */
9533 UInt regD
= 99, regN
= 99, regM
= 99;
9537 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
9539 regD
= INSNT1(11,8);
9541 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9545 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9546 INSNA(11,8) == BITS4(1,1,1,1) &&
9547 INSNA(7,4) == BITS4(0,1,1,1)) {
9548 regD
= INSNA(15,12);
9549 regN
= INSNA(19,16);
9551 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9557 IRTemp rNt
= newTemp(Ity_I32
);
9558 IRTemp rMt
= newTemp(Ity_I32
);
9559 IRTemp res
= newTemp(Ity_I32
);
9560 IRTemp reso
= newTemp(Ity_I32
);
9562 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9563 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9565 assign(res
, binop(Iop_Sub16x2
, mkexpr(rNt
), mkexpr(rMt
)));
9567 putIRegT( regD
, mkexpr(res
), condT
);
9569 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9571 assign(reso
, unop(Iop_Not32
,
9572 binop(Iop_HSub16Ux2
, mkexpr(rNt
), mkexpr(rMt
))));
9573 set_GE_32_10_from_bits_31_15(reso
, condT
);
9575 DIP("usub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9581 /* -------------- ssub16<c> <Rd>,<Rn>,<Rm> -------------- */
9583 UInt regD
= 99, regN
= 99, regM
= 99;
9587 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9589 regD
= INSNT1(11,8);
9591 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9595 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9596 INSNA(11,8) == BITS4(1,1,1,1) &&
9597 INSNA(7,4) == BITS4(0,1,1,1)) {
9598 regD
= INSNA(15,12);
9599 regN
= INSNA(19,16);
9601 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9607 IRTemp rNt
= newTemp(Ity_I32
);
9608 IRTemp rMt
= newTemp(Ity_I32
);
9609 IRTemp res
= newTemp(Ity_I32
);
9610 IRTemp reso
= newTemp(Ity_I32
);
9612 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9613 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9615 assign(res
, binop(Iop_Sub16x2
, mkexpr(rNt
), mkexpr(rMt
)));
9617 putIRegT( regD
, mkexpr(res
), condT
);
9619 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9621 assign(reso
, unop(Iop_Not32
,
9622 binop(Iop_HSub16Sx2
, mkexpr(rNt
), mkexpr(rMt
))));
9623 set_GE_32_10_from_bits_31_15(reso
, condT
);
9625 DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9631 /* ----------------- uadd8<c> <Rd>,<Rn>,<Rm> ---------------- */
9633 UInt regD
= 99, regN
= 99, regM
= 99;
9637 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
9639 regD
= INSNT1(11,8);
9641 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9645 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9646 INSNA(11,8) == BITS4(1,1,1,1) &&
9647 (INSNA(7,4) == BITS4(1,0,0,1))) {
9648 regD
= INSNA(15,12);
9649 regN
= INSNA(19,16);
9651 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9657 IRTemp rNt
= newTemp(Ity_I32
);
9658 IRTemp rMt
= newTemp(Ity_I32
);
9659 IRTemp res
= newTemp(Ity_I32
);
9660 IRTemp reso
= newTemp(Ity_I32
);
9662 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9663 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9665 assign(res
, binop(Iop_Add8x4
, mkexpr(rNt
), mkexpr(rMt
)));
9667 putIRegT( regD
, mkexpr(res
), condT
);
9669 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9671 assign(reso
, binop(Iop_HAdd8Ux4
, mkexpr(rNt
), mkexpr(rMt
)));
9672 set_GE_3_2_1_0_from_bits_31_23_15_7(reso
, condT
);
9674 DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9680 /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
9682 UInt regD
= 99, regN
= 99, regM
= 99;
9686 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9688 regD
= INSNT1(11,8);
9690 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9694 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9695 INSNA(11,8) == BITS4(1,1,1,1) &&
9696 (INSNA(7,4) == BITS4(1,0,0,1))) {
9697 regD
= INSNA(15,12);
9698 regN
= INSNA(19,16);
9700 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9706 IRTemp rNt
= newTemp(Ity_I32
);
9707 IRTemp rMt
= newTemp(Ity_I32
);
9708 IRTemp res
= newTemp(Ity_I32
);
9709 IRTemp reso
= newTemp(Ity_I32
);
9711 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9712 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9714 assign(res
, binop(Iop_Add8x4
, mkexpr(rNt
), mkexpr(rMt
)));
9716 putIRegT( regD
, mkexpr(res
), condT
);
9718 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9720 assign(reso
, unop(Iop_Not32
,
9721 binop(Iop_HAdd8Sx4
, mkexpr(rNt
), mkexpr(rMt
))));
9722 set_GE_3_2_1_0_from_bits_31_23_15_7(reso
, condT
);
9724 DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9730 /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9732 UInt regD
= 99, regN
= 99, regM
= 99;
9736 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
9738 regD
= INSNT1(11,8);
9740 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9744 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9745 INSNA(11,8) == BITS4(1,1,1,1) &&
9746 (INSNA(7,4) == BITS4(1,1,1,1))) {
9747 regD
= INSNA(15,12);
9748 regN
= INSNA(19,16);
9750 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9756 IRTemp rNt
= newTemp(Ity_I32
);
9757 IRTemp rMt
= newTemp(Ity_I32
);
9758 IRTemp res
= newTemp(Ity_I32
);
9759 IRTemp reso
= newTemp(Ity_I32
);
9761 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9762 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9764 assign(res
, binop(Iop_Sub8x4
, mkexpr(rNt
), mkexpr(rMt
)));
9766 putIRegT( regD
, mkexpr(res
), condT
);
9768 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9770 assign(reso
, unop(Iop_Not32
,
9771 binop(Iop_HSub8Ux4
, mkexpr(rNt
), mkexpr(rMt
))));
9772 set_GE_3_2_1_0_from_bits_31_23_15_7(reso
, condT
);
9774 DIP("usub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9780 /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9782 UInt regD
= 99, regN
= 99, regM
= 99;
9786 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9788 regD
= INSNT1(11,8);
9790 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9794 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9795 INSNA(11,8) == BITS4(1,1,1,1) &&
9796 INSNA(7,4) == BITS4(1,1,1,1)) {
9797 regD
= INSNA(15,12);
9798 regN
= INSNA(19,16);
9800 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9806 IRTemp rNt
= newTemp(Ity_I32
);
9807 IRTemp rMt
= newTemp(Ity_I32
);
9808 IRTemp res
= newTemp(Ity_I32
);
9809 IRTemp reso
= newTemp(Ity_I32
);
9811 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9812 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9814 assign(res
, binop(Iop_Sub8x4
, mkexpr(rNt
), mkexpr(rMt
)));
9816 putIRegT( regD
, mkexpr(res
), condT
);
9818 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9820 assign(reso
, unop(Iop_Not32
,
9821 binop(Iop_HSub8Sx4
, mkexpr(rNt
), mkexpr(rMt
))));
9822 set_GE_3_2_1_0_from_bits_31_23_15_7(reso
, condT
);
9824 DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9830 /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9832 UInt regD
= 99, regN
= 99, regM
= 99;
9836 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9838 regD
= INSNT1(11,8);
9840 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9844 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9845 INSNA(11,8) == BITS4(1,1,1,1) &&
9846 INSNA(7,4) == BITS4(1,0,0,1)) {
9847 regD
= INSNA(15,12);
9848 regN
= INSNA(19,16);
9850 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9856 IRTemp rNt
= newTemp(Ity_I32
);
9857 IRTemp rMt
= newTemp(Ity_I32
);
9858 IRTemp res_q
= newTemp(Ity_I32
);
9860 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9861 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9863 assign(res_q
, binop(Iop_QAdd8Sx4
, mkexpr(rNt
), mkexpr(rMt
)));
9865 putIRegT( regD
, mkexpr(res_q
), condT
);
9867 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
9869 DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9875 /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
9877 UInt regD
= 99, regN
= 99, regM
= 99;
9881 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9883 regD
= INSNT1(11,8);
9885 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9889 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9890 INSNA(11,8) == BITS4(1,1,1,1) &&
9891 INSNA(7,4) == BITS4(1,1,1,1)) {
9892 regD
= INSNA(15,12);
9893 regN
= INSNA(19,16);
9895 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9901 IRTemp rNt
= newTemp(Ity_I32
);
9902 IRTemp rMt
= newTemp(Ity_I32
);
9903 IRTemp res_q
= newTemp(Ity_I32
);
9905 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9906 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9908 assign(res_q
, binop(Iop_QSub8Sx4
, mkexpr(rNt
), mkexpr(rMt
)));
9910 putIRegT( regD
, mkexpr(res_q
), condT
);
9912 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
9914 DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9920 /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
9922 UInt regD
= 99, regN
= 99, regM
= 99;
9926 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9928 regD
= INSNT1(11,8);
9930 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9934 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9935 INSNA(11,8) == BITS4(1,1,1,1) &&
9936 (INSNA(7,4) == BITS4(1,0,0,1))) {
9937 regD
= INSNA(15,12);
9938 regN
= INSNA(19,16);
9940 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9946 IRTemp rNt
= newTemp(Ity_I32
);
9947 IRTemp rMt
= newTemp(Ity_I32
);
9948 IRTemp res_q
= newTemp(Ity_I32
);
9950 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9951 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9953 assign(res_q
, binop(Iop_QAdd8Ux4
, mkexpr(rNt
), mkexpr(rMt
)));
9955 putIRegT( regD
, mkexpr(res_q
), condT
);
9957 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
9959 DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9965 /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9967 UInt regD
= 99, regN
= 99, regM
= 99;
9971 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9973 regD
= INSNT1(11,8);
9975 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9979 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9980 INSNA(11,8) == BITS4(1,1,1,1) &&
9981 (INSNA(7,4) == BITS4(1,1,1,1))) {
9982 regD
= INSNA(15,12);
9983 regN
= INSNA(19,16);
9985 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9991 IRTemp rNt
= newTemp(Ity_I32
);
9992 IRTemp rMt
= newTemp(Ity_I32
);
9993 IRTemp res_q
= newTemp(Ity_I32
);
9995 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9996 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9998 assign(res_q
, binop(Iop_QSub8Ux4
, mkexpr(rNt
), mkexpr(rMt
)));
10000 putIRegT( regD
, mkexpr(res_q
), condT
);
10002 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10004 DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10010 /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
10012 UInt regD
= 99, regN
= 99, regM
= 99;
10016 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
10017 regN
= INSNT0(3,0);
10018 regD
= INSNT1(11,8);
10019 regM
= INSNT1(3,0);
10020 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10024 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
10025 INSNA(11,8) == BITS4(1,1,1,1) &&
10026 INSNA(7,4) == BITS4(1,0,0,1)) {
10027 regD
= INSNA(15,12);
10028 regN
= INSNA(19,16);
10030 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10036 IRTemp rNt
= newTemp(Ity_I32
);
10037 IRTemp rMt
= newTemp(Ity_I32
);
10038 IRTemp res_q
= newTemp(Ity_I32
);
10040 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10041 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10043 assign(res_q
, binop(Iop_HAdd8Ux4
, mkexpr(rNt
), mkexpr(rMt
)));
10045 putIRegT( regD
, mkexpr(res_q
), condT
);
10047 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10049 DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10055 /* ----------------- uhadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
10057 UInt regD
= 99, regN
= 99, regM
= 99;
10061 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
10062 regN
= INSNT0(3,0);
10063 regD
= INSNT1(11,8);
10064 regM
= INSNT1(3,0);
10065 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10069 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
10070 INSNA(11,8) == BITS4(1,1,1,1) &&
10071 INSNA(7,4) == BITS4(0,0,0,1)) {
10072 regD
= INSNA(15,12);
10073 regN
= INSNA(19,16);
10075 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10081 IRTemp rNt
= newTemp(Ity_I32
);
10082 IRTemp rMt
= newTemp(Ity_I32
);
10083 IRTemp res_q
= newTemp(Ity_I32
);
10085 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10086 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10088 assign(res_q
, binop(Iop_HAdd16Ux2
, mkexpr(rNt
), mkexpr(rMt
)));
10090 putIRegT( regD
, mkexpr(res_q
), condT
);
10092 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10094 DIP("uhadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10100 /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
10102 UInt regD
= 99, regN
= 99, regM
= 99;
10106 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
10107 regN
= INSNT0(3,0);
10108 regD
= INSNT1(11,8);
10109 regM
= INSNT1(3,0);
10110 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10114 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
10115 INSNA(11,8) == BITS4(1,1,1,1) &&
10116 INSNA(7,4) == BITS4(1,0,0,1)) {
10117 regD
= INSNA(15,12);
10118 regN
= INSNA(19,16);
10120 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10126 IRTemp rNt
= newTemp(Ity_I32
);
10127 IRTemp rMt
= newTemp(Ity_I32
);
10128 IRTemp res_q
= newTemp(Ity_I32
);
10130 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10131 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10133 assign(res_q
, binop(Iop_HAdd8Sx4
, mkexpr(rNt
), mkexpr(rMt
)));
10135 putIRegT( regD
, mkexpr(res_q
), condT
);
10137 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10139 DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10145 /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
10147 UInt regD
= 99, regN
= 99, regM
= 99;
10151 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
10152 regN
= INSNT0(3,0);
10153 regD
= INSNT1(11,8);
10154 regM
= INSNT1(3,0);
10155 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10159 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
10160 INSNA(11,8) == BITS4(1,1,1,1) &&
10161 INSNA(7,4) == BITS4(0,0,0,1)) {
10162 regD
= INSNA(15,12);
10163 regN
= INSNA(19,16);
10165 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10171 IRTemp rNt
= newTemp(Ity_I32
);
10172 IRTemp rMt
= newTemp(Ity_I32
);
10173 IRTemp res_q
= newTemp(Ity_I32
);
10175 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10176 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10178 assign(res_q
, binop(Iop_QAdd16Sx2
, mkexpr(rNt
), mkexpr(rMt
)));
10180 putIRegT( regD
, mkexpr(res_q
), condT
);
10182 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10184 DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10190 /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
10192 UInt regD
= 99, regN
= 99, regM
= 99;
10196 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
10197 regN
= INSNT0(3,0);
10198 regD
= INSNT1(11,8);
10199 regM
= INSNT1(3,0);
10200 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10204 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
10205 INSNA(11,8) == BITS4(1,1,1,1) &&
10206 INSNA(7,4) == BITS4(0,1,1,1)) {
10207 regD
= INSNA(15,12);
10208 regN
= INSNA(19,16);
10210 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10216 IRTemp rNt
= newTemp(Ity_I32
);
10217 IRTemp rMt
= newTemp(Ity_I32
);
10218 IRTemp res_q
= newTemp(Ity_I32
);
10220 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10221 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10223 assign(res_q
, binop(Iop_QSub16Sx2
, mkexpr(rNt
), mkexpr(rMt
)));
10225 putIRegT( regD
, mkexpr(res_q
), condT
);
10227 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10229 DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10235 /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
10236 /* note: the hardware seems to construct the result differently
10237 from wot the manual says. */
10239 UInt regD
= 99, regN
= 99, regM
= 99;
10243 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
10244 regN
= INSNT0(3,0);
10245 regD
= INSNT1(11,8);
10246 regM
= INSNT1(3,0);
10247 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10251 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
10252 INSNA(11,8) == BITS4(1,1,1,1) &&
10253 INSNA(7,4) == BITS4(0,1,0,1)) {
10254 regD
= INSNA(15,12);
10255 regN
= INSNA(19,16);
10257 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10263 IRTemp irt_regN
= newTemp(Ity_I32
);
10264 IRTemp irt_regM
= newTemp(Ity_I32
);
10265 IRTemp irt_sum
= newTemp(Ity_I32
);
10266 IRTemp irt_diff
= newTemp(Ity_I32
);
10267 IRTemp irt_sum_res
= newTemp(Ity_I32
);
10268 IRTemp irt_diff_res
= newTemp(Ity_I32
);
10270 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10271 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10275 binop( Iop_Sar32
, mkexpr(irt_regN
), mkU8(16) ),
10277 binop(Iop_Shl32
, mkexpr(irt_regM
), mkU8(16)),
10279 armSignedSatQ( irt_diff
, 0x10, &irt_diff_res
, NULL
);
10284 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
10286 binop( Iop_Sar32
, mkexpr(irt_regM
), mkU8(16) )) );
10287 armSignedSatQ( irt_sum
, 0x10, &irt_sum_res
, NULL
);
10289 IRExpr
* ire_result
= binop( Iop_Or32
,
10290 binop( Iop_Shl32
, mkexpr(irt_diff_res
),
10292 binop( Iop_And32
, mkexpr(irt_sum_res
),
10296 putIRegT( regD
, ire_result
, condT
);
10298 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10300 DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
10306 /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */
10308 UInt regD
= 99, regN
= 99, regM
= 99;
10312 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
10313 regN
= INSNT0(3,0);
10314 regD
= INSNT1(11,8);
10315 regM
= INSNT1(3,0);
10316 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10320 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
10321 INSNA(11,8) == BITS4(1,1,1,1) &&
10322 INSNA(7,4) == BITS4(0,0,1,1)) {
10323 regD
= INSNA(15,12);
10324 regN
= INSNA(19,16);
10326 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10332 IRTemp irt_regN
= newTemp(Ity_I32
);
10333 IRTemp irt_regM
= newTemp(Ity_I32
);
10334 IRTemp irt_sum
= newTemp(Ity_I32
);
10335 IRTemp irt_diff
= newTemp(Ity_I32
);
10336 IRTemp irt_res_sum
= newTemp(Ity_I32
);
10337 IRTemp irt_res_diff
= newTemp(Ity_I32
);
10339 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10340 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10345 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
10347 binop( Iop_Sar32
, mkexpr(irt_regM
), mkU8(16) ) ) );
10348 armSignedSatQ( irt_diff
, 0x10, &irt_res_diff
, NULL
);
10352 binop( Iop_Sar32
, mkexpr(irt_regN
), mkU8(16) ),
10354 binop( Iop_Shl32
, mkexpr(irt_regM
), mkU8(16) ),
10356 armSignedSatQ( irt_sum
, 0x10, &irt_res_sum
, NULL
);
10360 binop( Iop_Shl32
, mkexpr(irt_res_sum
), mkU8(16) ),
10361 binop( Iop_And32
, mkexpr(irt_res_diff
), mkU32(0xFFFF) ) );
10364 putIRegT( regD
, ire_result
, condT
);
10366 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10368 DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
10374 /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */
10376 UInt regD
= 99, regN
= 99, regM
= 99;
10380 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
10381 regN
= INSNT0(3,0);
10382 regD
= INSNT1(11,8);
10383 regM
= INSNT1(3,0);
10384 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10388 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
10389 INSNA(11,8) == BITS4(1,1,1,1) &&
10390 INSNA(7,4) == BITS4(0,0,1,1)) {
10391 regD
= INSNA(15,12);
10392 regN
= INSNA(19,16);
10394 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10400 IRTemp irt_regN
= newTemp(Ity_I32
);
10401 IRTemp irt_regM
= newTemp(Ity_I32
);
10402 IRTemp irt_sum
= newTemp(Ity_I32
);
10403 IRTemp irt_diff
= newTemp(Ity_I32
);
10405 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10406 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10411 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
10413 binop( Iop_Sar32
, mkexpr(irt_regM
), mkU8(16) ) ) );
10417 binop( Iop_Sar32
, mkexpr(irt_regN
), mkU8(16) ),
10419 binop( Iop_Shl32
, mkexpr(irt_regM
), mkU8(16) ),
10424 binop( Iop_Shl32
, mkexpr(irt_sum
), mkU8(16) ),
10425 binop( Iop_And32
, mkexpr(irt_diff
), mkU32(0xFFFF) ) );
10427 IRTemp ge10
= newTemp(Ity_I32
);
10428 assign(ge10
, unop(Iop_Not32
, mkexpr(irt_diff
)));
10429 put_GEFLAG32( 0, 31, mkexpr(ge10
), condT
);
10430 put_GEFLAG32( 1, 31, mkexpr(ge10
), condT
);
10432 IRTemp ge32
= newTemp(Ity_I32
);
10433 assign(ge32
, unop(Iop_Not32
, mkexpr(irt_sum
)));
10434 put_GEFLAG32( 2, 31, mkexpr(ge32
), condT
);
10435 put_GEFLAG32( 3, 31, mkexpr(ge32
), condT
);
10438 putIRegT( regD
, ire_result
, condT
);
10440 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10442 DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
10448 /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */
10449 /* --------------- smsad, smsadx<c><Rd>,<Rn>,<Rm> --------------- */
10451 UInt regD
= 99, regN
= 99, regM
= 99, bitM
= 99;
10452 Bool gate
= False
, isAD
= False
;
10455 if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
10456 && (INSNT1(15,0) & 0xF0E0) == 0xF000) {
10457 regN
= INSNT0(3,0);
10458 regD
= INSNT1(11,8);
10459 regM
= INSNT1(3,0);
10460 bitM
= INSNT1(4,4);
10461 isAD
= INSNT0(15,4) == 0xFB2;
10462 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10466 if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
10467 INSNA(15,12) == BITS4(1,1,1,1) &&
10468 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1) ) {
10469 regD
= INSNA(19,16);
10471 regM
= INSNA(11,8);
10473 isAD
= INSNA(6,6) == 0;
10474 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10480 IRTemp irt_regN
= newTemp(Ity_I32
);
10481 IRTemp irt_regM
= newTemp(Ity_I32
);
10482 IRTemp irt_prod_lo
= newTemp(Ity_I32
);
10483 IRTemp irt_prod_hi
= newTemp(Ity_I32
);
10484 IRTemp tmpM
= newTemp(Ity_I32
);
10486 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10488 assign( tmpM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10489 assign( irt_regM
, genROR32(tmpM
, (bitM
& 1) ? 16 : 0) );
10491 assign( irt_prod_lo
,
10494 binop(Iop_Shl32
, mkexpr(irt_regN
), mkU8(16)),
10497 binop(Iop_Shl32
, mkexpr(irt_regM
), mkU8(16)),
10499 assign( irt_prod_hi
, binop(Iop_Mul32
,
10500 binop(Iop_Sar32
, mkexpr(irt_regN
), mkU8(16)),
10501 binop(Iop_Sar32
, mkexpr(irt_regM
), mkU8(16))) );
10503 = binop( isAD
? Iop_Add32
: Iop_Sub32
,
10504 mkexpr(irt_prod_lo
), mkexpr(irt_prod_hi
) );
10507 putIRegT( regD
, ire_result
, condT
);
10509 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10513 signed_overflow_after_Add32( ire_result
,
10514 irt_prod_lo
, irt_prod_hi
),
10519 DIP("smu%cd%s%s r%u, r%u, r%u\n",
10521 bitM
? "x" : "", nCC(conq
), regD
, regN
, regM
);
10527 /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
10528 /* --------------- smlsd{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
10530 UInt regD
= 99, regN
= 99, regM
= 99, regA
= 99, bitM
= 99;
10531 Bool gate
= False
, isAD
= False
;
10534 if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
10535 && INSNT1(7,5) == BITS3(0,0,0)) {
10536 regN
= INSNT0(3,0);
10537 regD
= INSNT1(11,8);
10538 regM
= INSNT1(3,0);
10539 regA
= INSNT1(15,12);
10540 bitM
= INSNT1(4,4);
10541 isAD
= INSNT0(15,4) == 0xFB2;
10542 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
)
10543 && !isBadRegT(regA
))
10547 if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
10548 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
10549 regD
= INSNA(19,16);
10550 regA
= INSNA(15,12);
10552 regM
= INSNA(11,8);
10554 isAD
= INSNA(6,6) == 0;
10555 if (regD
!= 15 && regN
!= 15 && regM
!= 15 && regA
!= 15)
10561 IRTemp irt_regN
= newTemp(Ity_I32
);
10562 IRTemp irt_regM
= newTemp(Ity_I32
);
10563 IRTemp irt_regA
= newTemp(Ity_I32
);
10564 IRTemp irt_prod_lo
= newTemp(Ity_I32
);
10565 IRTemp irt_prod_hi
= newTemp(Ity_I32
);
10566 IRTemp irt_sum
= newTemp(Ity_I32
);
10567 IRTemp tmpM
= newTemp(Ity_I32
);
10569 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10570 assign( irt_regA
, isT
? getIRegT(regA
) : getIRegA(regA
) );
10572 assign( tmpM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10573 assign( irt_regM
, genROR32(tmpM
, (bitM
& 1) ? 16 : 0) );
10575 assign( irt_prod_lo
,
10578 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
10581 binop( Iop_Shl32
, mkexpr(irt_regM
), mkU8(16) ),
10583 assign( irt_prod_hi
,
10585 binop( Iop_Sar32
, mkexpr(irt_regN
), mkU8(16) ),
10586 binop( Iop_Sar32
, mkexpr(irt_regM
), mkU8(16) ) ) );
10587 assign( irt_sum
, binop( isAD
? Iop_Add32
: Iop_Sub32
,
10588 mkexpr(irt_prod_lo
), mkexpr(irt_prod_hi
) ) );
10590 IRExpr
* ire_result
= binop(Iop_Add32
, mkexpr(irt_sum
), mkexpr(irt_regA
));
10593 putIRegT( regD
, ire_result
, condT
);
10595 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10599 signed_overflow_after_Add32( mkexpr(irt_sum
),
10600 irt_prod_lo
, irt_prod_hi
),
10606 signed_overflow_after_Add32( ire_result
, irt_sum
, irt_regA
),
10610 DIP("sml%cd%s%s r%u, r%u, r%u, r%u\n",
10612 bitM
? "x" : "", nCC(conq
), regD
, regN
, regM
, regA
);
10618 /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */
10620 UInt regD
= 99, regN
= 99, regM
= 99, regA
= 99, bitM
= 99, bitN
= 99;
10624 if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) {
10625 regN
= INSNT0(3,0);
10626 regD
= INSNT1(11,8);
10627 regM
= INSNT1(3,0);
10628 regA
= INSNT1(15,12);
10629 bitM
= INSNT1(4,4);
10630 bitN
= INSNT1(5,5);
10631 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
)
10632 && !isBadRegT(regA
))
10636 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
10637 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
10638 regD
= INSNA(19,16);
10640 regM
= INSNA(11,8);
10641 regA
= INSNA(15,12);
10644 if (regD
!= 15 && regN
!= 15 && regM
!= 15 && regA
!= 15)
10650 IRTemp irt_regA
= newTemp(Ity_I32
);
10651 IRTemp irt_prod
= newTemp(Ity_I32
);
10657 isT
? getIRegT(regN
) : getIRegA(regN
),
10658 mkU8(bitN
? 0 : 16)),
10662 isT
? getIRegT(regM
) : getIRegA(regM
),
10663 mkU8(bitM
? 0 : 16)),
10666 assign( irt_regA
, isT
? getIRegT(regA
) : getIRegA(regA
) );
10668 IRExpr
* ire_result
= binop(Iop_Add32
, mkexpr(irt_prod
), mkexpr(irt_regA
));
10671 putIRegT( regD
, ire_result
, condT
);
10673 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10676 signed_overflow_after_Add32( ire_result
, irt_prod
, irt_regA
),
10680 DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n",
10681 bitN
? 't' : 'b', bitM
? 't' : 'b',
10682 nCC(conq
), regD
, regN
, regM
, regA
);
10688 /* ----- smlalbb, smlalbt, smlaltb, smlaltt <Rd>,<Rn>,<Rm>,<Ra> ----- */
10690 UInt regDHi
= 99, regN
= 99, regM
= 99, regDLo
= 99, bitM
= 99, bitN
= 99;
10694 if (INSNT0(15,4) == 0xFBC && INSNT1(7,6) == BITS2(1,0)) {
10695 regN
= INSNT0(3,0);
10696 regDHi
= INSNT1(11,8);
10697 regM
= INSNT1(3,0);
10698 regDLo
= INSNT1(15,12);
10699 bitM
= INSNT1(4,4);
10700 bitN
= INSNT1(5,5);
10701 if (!isBadRegT(regDHi
) && !isBadRegT(regN
) && !isBadRegT(regM
)
10702 && !isBadRegT(regDLo
) && regDHi
!= regDLo
)
10706 if (INSNA(27,20) == BITS8(0,0,0,1,0,1,0,0) &&
10707 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
10708 regDHi
= INSNA(19,16);
10710 regM
= INSNA(11,8);
10711 regDLo
= INSNA(15,12);
10714 if (regDHi
!= 15 && regN
!= 15 && regM
!= 15 && regDLo
!= 15 &&
10721 IRTemp irt_regD
= newTemp(Ity_I64
);
10722 IRTemp irt_prod
= newTemp(Ity_I64
);
10723 IRTemp irt_res
= newTemp(Ity_I64
);
10724 IRTemp irt_resHi
= newTemp(Ity_I32
);
10725 IRTemp irt_resLo
= newTemp(Ity_I32
);
10731 isT
? getIRegT(regN
) : getIRegA(regN
),
10732 mkU8(bitN
? 0 : 16)),
10736 isT
? getIRegT(regM
) : getIRegA(regM
),
10737 mkU8(bitM
? 0 : 16)),
10740 assign( irt_regD
, binop(Iop_32HLto64
,
10741 isT
? getIRegT(regDHi
) : getIRegA(regDHi
),
10742 isT
? getIRegT(regDLo
) : getIRegA(regDLo
)) );
10743 assign( irt_res
, binop(Iop_Add64
, mkexpr(irt_regD
), mkexpr(irt_prod
)) );
10744 assign( irt_resHi
, unop(Iop_64HIto32
, mkexpr(irt_res
)) );
10745 assign( irt_resLo
, unop(Iop_64to32
, mkexpr(irt_res
)) );
10748 putIRegT( regDHi
, mkexpr(irt_resHi
), condT
);
10749 putIRegT( regDLo
, mkexpr(irt_resLo
), condT
);
10751 putIRegA( regDHi
, mkexpr(irt_resHi
), condT
, Ijk_Boring
);
10752 putIRegA( regDLo
, mkexpr(irt_resLo
), condT
, Ijk_Boring
);
10755 DIP( "smlal%c%c%s r%u, r%u, r%u, r%u\n",
10756 bitN
? 't' : 'b', bitM
? 't' : 'b',
10757 nCC(conq
), regDHi
, regN
, regM
, regDLo
);
10763 /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */
10765 UInt regD
= 99, regN
= 99, regM
= 99, regA
= 99, bitM
= 99;
10769 if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) {
10770 regN
= INSNT0(3,0);
10771 regD
= INSNT1(11,8);
10772 regM
= INSNT1(3,0);
10773 regA
= INSNT1(15,12);
10774 bitM
= INSNT1(4,4);
10775 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
)
10776 && !isBadRegT(regA
))
10780 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
10781 (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) {
10782 regD
= INSNA(19,16);
10784 regM
= INSNA(11,8);
10785 regA
= INSNA(15,12);
10787 if (regD
!= 15 && regN
!= 15 && regM
!= 15 && regA
!= 15)
10793 IRTemp irt_regA
= newTemp(Ity_I32
);
10794 IRTemp irt_prod
= newTemp(Ity_I64
);
10798 isT
? getIRegT(regN
) : getIRegA(regN
),
10801 isT
? getIRegT(regM
) : getIRegA(regM
),
10802 mkU8(bitM
? 0 : 16)),
10805 assign( irt_regA
, isT
? getIRegT(regA
) : getIRegA(regA
) );
10807 IRTemp prod32
= newTemp(Ity_I32
);
10810 binop(Iop_Shl32
, unop(Iop_64HIto32
, mkexpr(irt_prod
)), mkU8(16)),
10811 binop(Iop_Shr32
, unop(Iop_64to32
, mkexpr(irt_prod
)), mkU8(16))
10814 IRExpr
* ire_result
= binop(Iop_Add32
, mkexpr(prod32
), mkexpr(irt_regA
));
10817 putIRegT( regD
, ire_result
, condT
);
10819 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10822 signed_overflow_after_Add32( ire_result
, prod32
, irt_regA
),
10826 DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n",
10828 nCC(conq
), regD
, regN
, regM
, regA
);
10834 /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */
10835 /* fixme: fix up the test in v6media.c so that we can pass the ge
10836 flags as part of the test. */
10838 UInt regD
= 99, regN
= 99, regM
= 99;
10842 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
10843 regN
= INSNT0(3,0);
10844 regD
= INSNT1(11,8);
10845 regM
= INSNT1(3,0);
10846 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10850 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
10851 INSNA(11,8) == BITS4(1,1,1,1) &&
10852 INSNA(7,4) == BITS4(1,0,1,1)) {
10853 regD
= INSNA(15,12);
10854 regN
= INSNA(19,16);
10856 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10862 IRTemp irt_ge_flag0
= newTemp(Ity_I32
);
10863 IRTemp irt_ge_flag1
= newTemp(Ity_I32
);
10864 IRTemp irt_ge_flag2
= newTemp(Ity_I32
);
10865 IRTemp irt_ge_flag3
= newTemp(Ity_I32
);
10867 assign( irt_ge_flag0
, get_GEFLAG32(0) );
10868 assign( irt_ge_flag1
, get_GEFLAG32(1) );
10869 assign( irt_ge_flag2
, get_GEFLAG32(2) );
10870 assign( irt_ge_flag3
, get_GEFLAG32(3) );
10872 IRExpr
* ire_ge_flag0_or
10873 = binop(Iop_Or32
, mkexpr(irt_ge_flag0
),
10874 binop(Iop_Sub32
, mkU32(0), mkexpr(irt_ge_flag0
)));
10875 IRExpr
* ire_ge_flag1_or
10876 = binop(Iop_Or32
, mkexpr(irt_ge_flag1
),
10877 binop(Iop_Sub32
, mkU32(0), mkexpr(irt_ge_flag1
)));
10878 IRExpr
* ire_ge_flag2_or
10879 = binop(Iop_Or32
, mkexpr(irt_ge_flag2
),
10880 binop(Iop_Sub32
, mkU32(0), mkexpr(irt_ge_flag2
)));
10881 IRExpr
* ire_ge_flag3_or
10882 = binop(Iop_Or32
, mkexpr(irt_ge_flag3
),
10883 binop(Iop_Sub32
, mkU32(0), mkexpr(irt_ge_flag3
)));
10885 IRExpr
* ire_ge_flags
10889 binop(Iop_Sar32
, ire_ge_flag0_or
, mkU8(31)),
10890 mkU32(0x000000ff)),
10892 binop(Iop_Sar32
, ire_ge_flag1_or
, mkU8(31)),
10893 mkU32(0x0000ff00))),
10896 binop(Iop_Sar32
, ire_ge_flag2_or
, mkU8(31)),
10897 mkU32(0x00ff0000)),
10899 binop(Iop_Sar32
, ire_ge_flag3_or
, mkU8(31)),
10900 mkU32(0xff000000))) );
10905 isT
? getIRegT(regN
) : getIRegA(regN
),
10908 isT
? getIRegT(regM
) : getIRegA(regM
),
10909 unop(Iop_Not32
, ire_ge_flags
)));
10912 putIRegT( regD
, ire_result
, condT
);
10914 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10916 DIP("sel%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
10922 /* ----------------- uxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
10924 UInt regD
= 99, regN
= 99, regM
= 99, rotate
= 99;
10928 if (INSNT0(15,4) == 0xFA3 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
10929 regN
= INSNT0(3,0);
10930 regD
= INSNT1(11,8);
10931 regM
= INSNT1(3,0);
10932 rotate
= INSNT1(5,4);
10933 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10937 if (INSNA(27,20) == BITS8(0,1,1,0,1,1,0,0) &&
10938 INSNA(9,4) == BITS6(0,0,0,1,1,1) ) {
10939 regD
= INSNA(15,12);
10940 regN
= INSNA(19,16);
10942 rotate
= INSNA(11,10);
10943 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10949 IRTemp irt_regN
= newTemp(Ity_I32
);
10950 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10952 IRTemp irt_regM
= newTemp(Ity_I32
);
10953 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10955 IRTemp irt_rot
= newTemp(Ity_I32
);
10956 assign( irt_rot
, binop(Iop_And32
,
10957 genROR32(irt_regM
, 8 * rotate
),
10958 mkU32(0x00FF00FF)) );
10962 binop(Iop_Add32
, mkexpr(irt_regN
), mkexpr(irt_rot
)),
10963 mkU32(0x0000FFFF));
10967 binop(Iop_And32
, mkexpr(irt_regN
), mkU32(0xFFFF0000)),
10968 binop(Iop_And32
, mkexpr(irt_rot
), mkU32(0xFFFF0000)));
10971 = binop( Iop_Or32
, resHi
, resLo
);
10974 putIRegT( regD
, ire_result
, condT
);
10976 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10978 DIP( "uxtab16%s r%u, r%u, r%u, ROR #%u\n",
10979 nCC(conq
), regD
, regN
, regM
, 8 * rotate
);
10985 /* --------------- usad8 Rd,Rn,Rm ---------------- */
10986 /* --------------- usada8 Rd,Rn,Rm,Ra ---------------- */
10988 UInt rD
= 99, rN
= 99, rM
= 99, rA
= 99;
10992 if (INSNT0(15,4) == 0xFB7 && INSNT1(7,4) == BITS4(0,0,0,0)) {
10994 rA
= INSNT1(15,12);
10997 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
) && rA
!= 13)
11001 if (INSNA(27,20) == BITS8(0,1,1,1,1,0,0,0) &&
11002 INSNA(7,4) == BITS4(0,0,0,1) ) {
11007 if (rD
!= 15 && rN
!= 15 && rM
!= 15 /* but rA can be 15 */)
11011 /* We allow rA == 15, to denote the usad8 (no accumulator) case. */
11014 IRExpr
* rNe
= isT
? getIRegT(rN
) : getIRegA(rN
);
11015 IRExpr
* rMe
= isT
? getIRegT(rM
) : getIRegA(rM
);
11016 IRExpr
* rAe
= rA
== 15 ? mkU32(0)
11017 : (isT
? getIRegT(rA
) : getIRegA(rA
));
11018 IRExpr
* res
= binop(Iop_Add32
,
11019 binop(Iop_Sad8Ux4
, rNe
, rMe
),
11022 putIRegT( rD
, res
, condT
);
11024 putIRegA( rD
, res
, condT
, Ijk_Boring
);
11027 DIP( "usad8%s r%u, r%u, r%u\n",
11028 nCC(conq
), rD
, rN
, rM
);
11030 DIP( "usada8%s r%u, r%u, r%u, r%u\n",
11031 nCC(conq
), rD
, rN
, rM
, rA
);
11038 /* ------------------ qadd<c> <Rd>,<Rn>,<Rm> ------------------- */
11040 UInt regD
= 99, regN
= 99, regM
= 99;
11044 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
11045 regN
= INSNT0(3,0);
11046 regD
= INSNT1(11,8);
11047 regM
= INSNT1(3,0);
11048 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11052 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
11053 INSNA(11,8) == BITS4(0,0,0,0) &&
11054 INSNA(7,4) == BITS4(0,1,0,1)) {
11055 regD
= INSNA(15,12);
11056 regN
= INSNA(19,16);
11058 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11064 IRTemp rNt
= newTemp(Ity_I32
);
11065 IRTemp rMt
= newTemp(Ity_I32
);
11066 IRTemp res_q
= newTemp(Ity_I32
);
11068 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11069 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11071 assign(res_q
, binop(Iop_QAdd32S
, mkexpr(rMt
), mkexpr(rNt
)));
11073 putIRegT( regD
, mkexpr(res_q
), condT
);
11075 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11078 signed_overflow_after_Add32(
11079 binop(Iop_Add32
, mkexpr(rMt
), mkexpr(rNt
)), rMt
, rNt
),
11083 DIP("qadd%s r%u, r%u, r%u\n", nCC(conq
),regD
,regM
,regN
);
11089 /* ------------------ qdadd<c> <Rd>,<Rm>,<Rn> ------------------- */
11091 UInt regD
= 99, regN
= 99, regM
= 99;
11095 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF090) {
11096 regN
= INSNT0(3,0);
11097 regD
= INSNT1(11,8);
11098 regM
= INSNT1(3,0);
11099 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11103 if (INSNA(27,20) == BITS8(0,0,0,1,0,1,0,0) &&
11104 INSNA(11,8) == BITS4(0,0,0,0) &&
11105 INSNA(7,4) == BITS4(0,1,0,1)) {
11106 regD
= INSNA(15,12);
11107 regN
= INSNA(19,16);
11109 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11115 IRTemp rNt
= newTemp(Ity_I32
);
11116 IRTemp rMt
= newTemp(Ity_I32
);
11117 IRTemp rN_d
= newTemp(Ity_I32
);
11118 IRTemp res_q
= newTemp(Ity_I32
);
11120 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11121 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11124 signed_overflow_after_Add32(
11125 binop(Iop_Add32
, mkexpr(rNt
), mkexpr(rNt
)), rNt
, rNt
),
11129 assign(rN_d
, binop(Iop_QAdd32S
, mkexpr(rNt
), mkexpr(rNt
)));
11130 assign(res_q
, binop(Iop_QAdd32S
, mkexpr(rMt
), mkexpr(rN_d
)));
11132 putIRegT( regD
, mkexpr(res_q
), condT
);
11134 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11137 signed_overflow_after_Add32(
11138 binop(Iop_Add32
, mkexpr(rMt
), mkexpr(rN_d
)), rMt
, rN_d
),
11142 DIP("qdadd%s r%u, r%u, r%u\n", nCC(conq
),regD
,regM
,regN
);
11148 /* ------------------ qsub<c> <Rd>,<Rn>,<Rm> ------------------- */
11150 UInt regD
= 99, regN
= 99, regM
= 99;
11154 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0A0) {
11155 regN
= INSNT0(3,0);
11156 regD
= INSNT1(11,8);
11157 regM
= INSNT1(3,0);
11158 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11162 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
11163 INSNA(11,8) == BITS4(0,0,0,0) &&
11164 INSNA(7,4) == BITS4(0,1,0,1)) {
11165 regD
= INSNA(15,12);
11166 regN
= INSNA(19,16);
11168 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11174 IRTemp rNt
= newTemp(Ity_I32
);
11175 IRTemp rMt
= newTemp(Ity_I32
);
11176 IRTemp res_q
= newTemp(Ity_I32
);
11178 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11179 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11181 assign(res_q
, binop(Iop_QSub32S
, mkexpr(rMt
), mkexpr(rNt
)));
11183 putIRegT( regD
, mkexpr(res_q
), condT
);
11185 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11188 signed_overflow_after_Sub32(
11189 binop(Iop_Sub32
, mkexpr(rMt
), mkexpr(rNt
)), rMt
, rNt
),
11193 DIP("qsub%s r%u, r%u, r%u\n", nCC(conq
),regD
,regM
,regN
);
11199 /* ------------------ qdsub<c> <Rd>,<Rm>,<Rn> ------------------- */
11201 UInt regD
= 99, regN
= 99, regM
= 99;
11205 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0B0) {
11206 regN
= INSNT0(3,0);
11207 regD
= INSNT1(11,8);
11208 regM
= INSNT1(3,0);
11209 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11213 if (INSNA(27,20) == BITS8(0,0,0,1,0,1,1,0) &&
11214 INSNA(11,8) == BITS4(0,0,0,0) &&
11215 INSNA(7,4) == BITS4(0,1,0,1)) {
11216 regD
= INSNA(15,12);
11217 regN
= INSNA(19,16);
11219 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11225 IRTemp rNt
= newTemp(Ity_I32
);
11226 IRTemp rMt
= newTemp(Ity_I32
);
11227 IRTemp rN_d
= newTemp(Ity_I32
);
11228 IRTemp res_q
= newTemp(Ity_I32
);
11230 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11231 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11234 signed_overflow_after_Add32(
11235 binop(Iop_Add32
, mkexpr(rNt
), mkexpr(rNt
)), rNt
, rNt
),
11239 assign(rN_d
, binop(Iop_QAdd32S
, mkexpr(rNt
), mkexpr(rNt
)));
11240 assign(res_q
, binop(Iop_QSub32S
, mkexpr(rMt
), mkexpr(rN_d
)));
11242 putIRegT( regD
, mkexpr(res_q
), condT
);
11244 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11247 signed_overflow_after_Sub32(
11248 binop(Iop_Sub32
, mkexpr(rMt
), mkexpr(rN_d
)), rMt
, rN_d
),
11252 DIP("qdsub%s r%u, r%u, r%u\n", nCC(conq
),regD
,regM
,regN
);
11258 /* ------------------ uqsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
11260 UInt regD
= 99, regN
= 99, regM
= 99;
11264 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
11265 regN
= INSNT0(3,0);
11266 regD
= INSNT1(11,8);
11267 regM
= INSNT1(3,0);
11268 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11272 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
11273 INSNA(11,8) == BITS4(1,1,1,1) &&
11274 INSNA(7,4) == BITS4(0,1,1,1)) {
11275 regD
= INSNA(15,12);
11276 regN
= INSNA(19,16);
11278 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11284 IRTemp rNt
= newTemp(Ity_I32
);
11285 IRTemp rMt
= newTemp(Ity_I32
);
11286 IRTemp res_q
= newTemp(Ity_I32
);
11288 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11289 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11291 assign(res_q
, binop(Iop_QSub16Ux2
, mkexpr(rNt
), mkexpr(rMt
)));
11293 putIRegT( regD
, mkexpr(res_q
), condT
);
11295 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11297 DIP("uqsub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11303 /* ----------------- shadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
11305 UInt regD
= 99, regN
= 99, regM
= 99;
11309 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
11310 regN
= INSNT0(3,0);
11311 regD
= INSNT1(11,8);
11312 regM
= INSNT1(3,0);
11313 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11317 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
11318 INSNA(11,8) == BITS4(1,1,1,1) &&
11319 INSNA(7,4) == BITS4(0,0,0,1)) {
11320 regD
= INSNA(15,12);
11321 regN
= INSNA(19,16);
11323 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11329 IRTemp rNt
= newTemp(Ity_I32
);
11330 IRTemp rMt
= newTemp(Ity_I32
);
11331 IRTemp res_q
= newTemp(Ity_I32
);
11333 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11334 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11336 assign(res_q
, binop(Iop_HAdd16Sx2
, mkexpr(rNt
), mkexpr(rMt
)));
11338 putIRegT( regD
, mkexpr(res_q
), condT
);
11340 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11342 DIP("shadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11348 /* ----------------- uhsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
11350 UInt regD
= 99, regN
= 99, regM
= 99;
11354 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
11355 regN
= INSNT0(3,0);
11356 regD
= INSNT1(11,8);
11357 regM
= INSNT1(3,0);
11358 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11362 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
11363 INSNA(11,8) == BITS4(1,1,1,1) &&
11364 INSNA(7,4) == BITS4(1,1,1,1)) {
11365 regD
= INSNA(15,12);
11366 regN
= INSNA(19,16);
11368 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11374 IRTemp rNt
= newTemp(Ity_I32
);
11375 IRTemp rMt
= newTemp(Ity_I32
);
11376 IRTemp res_q
= newTemp(Ity_I32
);
11378 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11379 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11381 assign(res_q
, binop(Iop_HSub8Ux4
, mkexpr(rNt
), mkexpr(rMt
)));
11383 putIRegT( regD
, mkexpr(res_q
), condT
);
11385 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11387 DIP("uhsub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11393 /* ----------------- uhsub16<c> <Rd>,<Rn>,<Rm> ------------------- */
11395 UInt regD
= 99, regN
= 99, regM
= 99;
11399 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
11400 regN
= INSNT0(3,0);
11401 regD
= INSNT1(11,8);
11402 regM
= INSNT1(3,0);
11403 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11407 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
11408 INSNA(11,8) == BITS4(1,1,1,1) &&
11409 INSNA(7,4) == BITS4(0,1,1,1)) {
11410 regD
= INSNA(15,12);
11411 regN
= INSNA(19,16);
11413 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11419 IRTemp rNt
= newTemp(Ity_I32
);
11420 IRTemp rMt
= newTemp(Ity_I32
);
11421 IRTemp res_q
= newTemp(Ity_I32
);
11423 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11424 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11426 assign(res_q
, binop(Iop_HSub16Ux2
, mkexpr(rNt
), mkexpr(rMt
)));
11428 putIRegT( regD
, mkexpr(res_q
), condT
);
11430 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11432 DIP("uhsub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11438 /* ------------------ uqadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
11440 UInt regD
= 99, regN
= 99, regM
= 99;
11444 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
11445 regN
= INSNT0(3,0);
11446 regD
= INSNT1(11,8);
11447 regM
= INSNT1(3,0);
11448 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11452 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
11453 INSNA(11,8) == BITS4(1,1,1,1) &&
11454 INSNA(7,4) == BITS4(0,0,0,1)) {
11455 regD
= INSNA(15,12);
11456 regN
= INSNA(19,16);
11458 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11464 IRTemp rNt
= newTemp(Ity_I32
);
11465 IRTemp rMt
= newTemp(Ity_I32
);
11466 IRTemp res_q
= newTemp(Ity_I32
);
11468 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11469 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11471 assign(res_q
, binop(Iop_QAdd16Ux2
, mkexpr(rNt
), mkexpr(rMt
)));
11473 putIRegT( regD
, mkexpr(res_q
), condT
);
11475 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11477 DIP("uqadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11483 /* ------------------- uqsax<c> <Rd>,<Rn>,<Rm> ------------------- */
11485 UInt regD
= 99, regN
= 99, regM
= 99;
11489 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
11490 regN
= INSNT0(3,0);
11491 regD
= INSNT1(11,8);
11492 regM
= INSNT1(3,0);
11493 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11497 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
11498 INSNA(11,8) == BITS4(1,1,1,1) &&
11499 INSNA(7,4) == BITS4(0,1,0,1)) {
11500 regD
= INSNA(15,12);
11501 regN
= INSNA(19,16);
11503 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11509 IRTemp irt_regN
= newTemp(Ity_I32
);
11510 IRTemp irt_regM
= newTemp(Ity_I32
);
11511 IRTemp irt_sum
= newTemp(Ity_I32
);
11512 IRTemp irt_diff
= newTemp(Ity_I32
);
11513 IRTemp irt_sum_res
= newTemp(Ity_I32
);
11514 IRTemp irt_diff_res
= newTemp(Ity_I32
);
11516 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11517 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11521 binop( Iop_Shr32
, mkexpr(irt_regN
), mkU8(16) ),
11523 binop(Iop_Shl32
, mkexpr(irt_regM
), mkU8(16)),
11525 armUnsignedSatQ( &irt_diff_res
, NULL
, irt_diff
, 0x10);
11530 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
11532 binop( Iop_Shr32
, mkexpr(irt_regM
), mkU8(16) )) );
11533 armUnsignedSatQ( &irt_sum_res
, NULL
, irt_sum
, 0x10 );
11535 IRExpr
* ire_result
= binop( Iop_Or32
,
11536 binop( Iop_Shl32
, mkexpr(irt_diff_res
),
11538 binop( Iop_And32
, mkexpr(irt_sum_res
),
11542 putIRegT( regD
, ire_result
, condT
);
11544 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11546 DIP( "uqsax%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
11552 /* ------------------- uqasx<c> <Rd>,<Rn>,<Rm> ------------------- */
11554 UInt regD
= 99, regN
= 99, regM
= 99;
11558 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
11559 regN
= INSNT0(3,0);
11560 regD
= INSNT1(11,8);
11561 regM
= INSNT1(3,0);
11562 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11566 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
11567 INSNA(11,8) == BITS4(1,1,1,1) &&
11568 INSNA(7,4) == BITS4(0,0,1,1)) {
11569 regD
= INSNA(15,12);
11570 regN
= INSNA(19,16);
11572 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11578 IRTemp irt_regN
= newTemp(Ity_I32
);
11579 IRTemp irt_regM
= newTemp(Ity_I32
);
11580 IRTemp irt_sum
= newTemp(Ity_I32
);
11581 IRTemp irt_diff
= newTemp(Ity_I32
);
11582 IRTemp irt_res_sum
= newTemp(Ity_I32
);
11583 IRTemp irt_res_diff
= newTemp(Ity_I32
);
11585 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11586 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11591 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
11593 binop( Iop_Shr32
, mkexpr(irt_regM
), mkU8(16) ) ) );
11594 armUnsignedSatQ( &irt_res_diff
, NULL
, irt_diff
, 0x10 );
11598 binop( Iop_Shr32
, mkexpr(irt_regN
), mkU8(16) ),
11600 binop( Iop_Shl32
, mkexpr(irt_regM
), mkU8(16) ),
11602 armUnsignedSatQ( &irt_res_sum
, NULL
, irt_sum
, 0x10 );
11606 binop( Iop_Shl32
, mkexpr(irt_res_sum
), mkU8(16) ),
11607 binop( Iop_And32
, mkexpr(irt_res_diff
), mkU32(0xFFFF) ) );
11610 putIRegT( regD
, ire_result
, condT
);
11612 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11614 DIP( "uqasx%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
11620 /* ------------------- usax<c> <Rd>,<Rn>,<Rm> ------------------- */
11622 UInt regD
= 99, regN
= 99, regM
= 99;
11626 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
11627 regN
= INSNT0(3,0);
11628 regD
= INSNT1(11,8);
11629 regM
= INSNT1(3,0);
11630 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11634 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
11635 INSNA(11,8) == BITS4(1,1,1,1) &&
11636 INSNA(7,4) == BITS4(0,1,0,1)) {
11637 regD
= INSNA(15,12);
11638 regN
= INSNA(19,16);
11640 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11646 IRTemp irt_regN
= newTemp(Ity_I32
);
11647 IRTemp irt_regM
= newTemp(Ity_I32
);
11648 IRTemp irt_sum
= newTemp(Ity_I32
);
11649 IRTemp irt_diff
= newTemp(Ity_I32
);
11651 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11652 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11657 unop( Iop_32to16
, mkexpr(irt_regN
) )
11659 binop( Iop_Shr32
, mkexpr(irt_regM
), mkU8(16) ) ) );
11663 binop( Iop_Shr32
, mkexpr(irt_regN
), mkU8(16) ),
11665 unop( Iop_32to16
, mkexpr(irt_regM
) )
11672 binop( Iop_Shl32
, mkexpr(irt_diff
), mkU8(16) ),
11673 binop( Iop_And32
, mkexpr(irt_sum
), mkU32(0xFFFF) ) );
11675 IRTemp ge10
= newTemp(Ity_I32
);
11676 assign( ge10
, IRExpr_ITE( binop( Iop_CmpLE32U
,
11677 mkU32(0x10000), mkexpr(irt_sum
) ),
11678 mkU32(1), mkU32(0) ) );
11679 put_GEFLAG32( 0, 0, mkexpr(ge10
), condT
);
11680 put_GEFLAG32( 1, 0, mkexpr(ge10
), condT
);
11682 IRTemp ge32
= newTemp(Ity_I32
);
11683 assign(ge32
, unop(Iop_Not32
, mkexpr(irt_diff
)));
11684 put_GEFLAG32( 2, 31, mkexpr(ge32
), condT
);
11685 put_GEFLAG32( 3, 31, mkexpr(ge32
), condT
);
11688 putIRegT( regD
, ire_result
, condT
);
11690 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11692 DIP( "usax%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
11698 /* ------------------- uasx<c> <Rd>,<Rn>,<Rm> ------------------- */
11700 UInt regD
= 99, regN
= 99, regM
= 99;
11704 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
11705 regN
= INSNT0(3,0);
11706 regD
= INSNT1(11,8);
11707 regM
= INSNT1(3,0);
11708 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11712 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
11713 INSNA(11,8) == BITS4(1,1,1,1) &&
11714 INSNA(7,4) == BITS4(0,0,1,1)) {
11715 regD
= INSNA(15,12);
11716 regN
= INSNA(19,16);
11718 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11724 IRTemp irt_regN
= newTemp(Ity_I32
);
11725 IRTemp irt_regM
= newTemp(Ity_I32
);
11726 IRTemp irt_sum
= newTemp(Ity_I32
);
11727 IRTemp irt_diff
= newTemp(Ity_I32
);
11729 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11730 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11735 unop( Iop_32to16
, mkexpr(irt_regN
) )
11737 binop( Iop_Shr32
, mkexpr(irt_regM
), mkU8(16) ) ) );
11741 binop( Iop_Shr32
, mkexpr(irt_regN
), mkU8(16) ),
11743 unop( Iop_32to16
, mkexpr(irt_regM
) )
11748 binop( Iop_Shl32
, mkexpr(irt_sum
), mkU8(16) ),
11749 binop( Iop_And32
, mkexpr(irt_diff
), mkU32(0xFFFF) ) );
11751 IRTemp ge10
= newTemp(Ity_I32
);
11752 assign(ge10
, unop(Iop_Not32
, mkexpr(irt_diff
)));
11753 put_GEFLAG32( 0, 31, mkexpr(ge10
), condT
);
11754 put_GEFLAG32( 1, 31, mkexpr(ge10
), condT
);
11756 IRTemp ge32
= newTemp(Ity_I32
);
11757 assign( ge32
, IRExpr_ITE( binop( Iop_CmpLE32U
,
11758 mkU32(0x10000), mkexpr(irt_sum
) ),
11759 mkU32(1), mkU32(0) ) );
11760 put_GEFLAG32( 2, 0, mkexpr(ge32
), condT
);
11761 put_GEFLAG32( 3, 0, mkexpr(ge32
), condT
);
11764 putIRegT( regD
, ire_result
, condT
);
11766 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11768 DIP( "uasx%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
11774 /* ------------------- ssax<c> <Rd>,<Rn>,<Rm> ------------------- */
11776 UInt regD
= 99, regN
= 99, regM
= 99;
11780 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
11781 regN
= INSNT0(3,0);
11782 regD
= INSNT1(11,8);
11783 regM
= INSNT1(3,0);
11784 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11788 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
11789 INSNA(11,8) == BITS4(1,1,1,1) &&
11790 INSNA(7,4) == BITS4(0,1,0,1)) {
11791 regD
= INSNA(15,12);
11792 regN
= INSNA(19,16);
11794 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11800 IRTemp irt_regN
= newTemp(Ity_I32
);
11801 IRTemp irt_regM
= newTemp(Ity_I32
);
11802 IRTemp irt_sum
= newTemp(Ity_I32
);
11803 IRTemp irt_diff
= newTemp(Ity_I32
);
11805 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11806 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11811 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
11813 binop( Iop_Sar32
, mkexpr(irt_regM
), mkU8(16) ) ) );
11817 binop( Iop_Sar32
, mkexpr(irt_regN
), mkU8(16) ),
11819 binop( Iop_Shl32
, mkexpr(irt_regM
), mkU8(16) ),
11824 binop( Iop_Shl32
, mkexpr(irt_diff
), mkU8(16) ),
11825 binop( Iop_And32
, mkexpr(irt_sum
), mkU32(0xFFFF) ) );
11827 IRTemp ge10
= newTemp(Ity_I32
);
11828 assign(ge10
, unop(Iop_Not32
, mkexpr(irt_sum
)));
11829 put_GEFLAG32( 0, 31, mkexpr(ge10
), condT
);
11830 put_GEFLAG32( 1, 31, mkexpr(ge10
), condT
);
11832 IRTemp ge32
= newTemp(Ity_I32
);
11833 assign(ge32
, unop(Iop_Not32
, mkexpr(irt_diff
)));
11834 put_GEFLAG32( 2, 31, mkexpr(ge32
), condT
);
11835 put_GEFLAG32( 3, 31, mkexpr(ge32
), condT
);
11838 putIRegT( regD
, ire_result
, condT
);
11840 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11842 DIP( "ssax%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
11848 /* ----------------- shsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
11850 UInt regD
= 99, regN
= 99, regM
= 99;
11854 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
11855 regN
= INSNT0(3,0);
11856 regD
= INSNT1(11,8);
11857 regM
= INSNT1(3,0);
11858 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11862 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
11863 INSNA(11,8) == BITS4(1,1,1,1) &&
11864 INSNA(7,4) == BITS4(1,1,1,1)) {
11865 regD
= INSNA(15,12);
11866 regN
= INSNA(19,16);
11868 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11874 IRTemp rNt
= newTemp(Ity_I32
);
11875 IRTemp rMt
= newTemp(Ity_I32
);
11876 IRTemp res_q
= newTemp(Ity_I32
);
11878 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11879 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11881 assign(res_q
, binop(Iop_HSub8Sx4
, mkexpr(rNt
), mkexpr(rMt
)));
11883 putIRegT( regD
, mkexpr(res_q
), condT
);
11885 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11887 DIP("shsub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11893 /* ----------------- sxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
11895 UInt regD
= 99, regN
= 99, regM
= 99, rotate
= 99;
11899 if (INSNT0(15,4) == 0xFA2 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
11900 regN
= INSNT0(3,0);
11901 regD
= INSNT1(11,8);
11902 regM
= INSNT1(3,0);
11903 rotate
= INSNT1(5,4);
11904 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11908 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
11909 INSNA(9,4) == BITS6(0,0,0,1,1,1) ) {
11910 regD
= INSNA(15,12);
11911 regN
= INSNA(19,16);
11913 rotate
= INSNA(11,10);
11914 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11920 IRTemp irt_regN
= newTemp(Ity_I32
);
11921 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11923 IRTemp irt_regM
= newTemp(Ity_I32
);
11924 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11926 IRTemp irt_rot
= newTemp(Ity_I32
);
11927 assign( irt_rot
, genROR32(irt_regM
, 8 * rotate
) );
11929 /* FIXME Maybe we can write this arithmetic in shorter form. */
11936 unop(Iop_32to8
, mkexpr(irt_rot
))))),
11937 mkU32(0x0000FFFF));
11951 mkU32(0xFFFF0000));
11954 = binop( Iop_Or32
, resHi
, resLo
);
11957 putIRegT( regD
, ire_result
, condT
);
11959 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11961 DIP( "sxtab16%s r%u, r%u, r%u, ROR #%u\n",
11962 nCC(conq
), regD
, regN
, regM
, 8 * rotate
);
11968 /* ----------------- shasx<c> <Rd>,<Rn>,<Rm> ------------------- */
11970 UInt regD
= 99, regN
= 99, regM
= 99;
11974 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
11975 regN
= INSNT0(3,0);
11976 regD
= INSNT1(11,8);
11977 regM
= INSNT1(3,0);
11978 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11982 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
11983 INSNA(11,8) == BITS4(1,1,1,1) &&
11984 INSNA(7,4) == BITS4(0,0,1,1)) {
11985 regD
= INSNA(15,12);
11986 regN
= INSNA(19,16);
11988 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11994 IRTemp rNt
= newTemp(Ity_I32
);
11995 IRTemp rMt
= newTemp(Ity_I32
);
11996 IRTemp irt_diff
= newTemp(Ity_I32
);
11997 IRTemp irt_sum
= newTemp(Ity_I32
);
11998 IRTemp res_q
= newTemp(Ity_I32
);
12000 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
12001 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
12013 mkexpr(rMt
), mkU8(16)
12025 mkexpr(rNt
), mkU8(16)
12030 unop(Iop_32to16
, mkexpr(rMt
)
12041 mkexpr(irt_diff
), mkU8(1)
12047 mkexpr(irt_sum
), mkU8(1)
12055 putIRegT( regD
, mkexpr(res_q
), condT
);
12057 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
12059 DIP("shasx%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
12065 /* ----------------- uhasx<c> <Rd>,<Rn>,<Rm> ------------------- */
12067 UInt regD
= 99, regN
= 99, regM
= 99;
12071 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
12072 regN
= INSNT0(3,0);
12073 regD
= INSNT1(11,8);
12074 regM
= INSNT1(3,0);
12075 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
12079 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
12080 INSNA(11,8) == BITS4(1,1,1,1) &&
12081 INSNA(7,4) == BITS4(0,0,1,1)) {
12082 regD
= INSNA(15,12);
12083 regN
= INSNA(19,16);
12085 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
12091 IRTemp rNt
= newTemp(Ity_I32
);
12092 IRTemp rMt
= newTemp(Ity_I32
);
12093 IRTemp irt_diff
= newTemp(Ity_I32
);
12094 IRTemp irt_sum
= newTemp(Ity_I32
);
12095 IRTemp res_q
= newTemp(Ity_I32
);
12097 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
12098 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
12110 mkexpr(rMt
), mkU8(16)
12122 mkexpr(rNt
), mkU8(16)
12127 unop(Iop_32to16
, mkexpr(rMt
)
12138 mkexpr(irt_diff
), mkU8(1)
12144 mkexpr(irt_sum
), mkU8(1)
12152 putIRegT( regD
, mkexpr(res_q
), condT
);
12154 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
12156 DIP("uhasx%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
12162 /* ----------------- shsax<c> <Rd>,<Rn>,<Rm> ------------------- */
12164 UInt regD
= 99, regN
= 99, regM
= 99;
12168 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
12169 regN
= INSNT0(3,0);
12170 regD
= INSNT1(11,8);
12171 regM
= INSNT1(3,0);
12172 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
12176 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
12177 INSNA(11,8) == BITS4(1,1,1,1) &&
12178 INSNA(7,4) == BITS4(0,1,0,1)) {
12179 regD
= INSNA(15,12);
12180 regN
= INSNA(19,16);
12182 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
12188 IRTemp rNt
= newTemp(Ity_I32
);
12189 IRTemp rMt
= newTemp(Ity_I32
);
12190 IRTemp irt_diff
= newTemp(Ity_I32
);
12191 IRTemp irt_sum
= newTemp(Ity_I32
);
12192 IRTemp res_q
= newTemp(Ity_I32
);
12194 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
12195 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
12207 mkexpr(rMt
), mkU8(16)
12219 mkexpr(rNt
), mkU8(16)
12224 unop(Iop_32to16
, mkexpr(rMt
)
12235 mkexpr(irt_sum
), mkU8(1)
12241 mkexpr(irt_diff
), mkU8(1)
12249 putIRegT( regD
, mkexpr(res_q
), condT
);
12251 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
12253 DIP("shsax%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
12259 /* ----------------- uhsax<c> <Rd>,<Rn>,<Rm> ------------------- */
12261 UInt regD
= 99, regN
= 99, regM
= 99;
12265 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
12266 regN
= INSNT0(3,0);
12267 regD
= INSNT1(11,8);
12268 regM
= INSNT1(3,0);
12269 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
12273 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
12274 INSNA(11,8) == BITS4(1,1,1,1) &&
12275 INSNA(7,4) == BITS4(0,1,0,1)) {
12276 regD
= INSNA(15,12);
12277 regN
= INSNA(19,16);
12279 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
12285 IRTemp rNt
= newTemp(Ity_I32
);
12286 IRTemp rMt
= newTemp(Ity_I32
);
12287 IRTemp irt_diff
= newTemp(Ity_I32
);
12288 IRTemp irt_sum
= newTemp(Ity_I32
);
12289 IRTemp res_q
= newTemp(Ity_I32
);
12291 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
12292 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
12304 mkexpr(rMt
), mkU8(16)
12316 mkexpr(rNt
), mkU8(16)
12321 unop(Iop_32to16
, mkexpr(rMt
)
12332 mkexpr(irt_sum
), mkU8(1)
12338 mkexpr(irt_diff
), mkU8(1)
12346 putIRegT( regD
, mkexpr(res_q
), condT
);
12348 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
12350 DIP("uhsax%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
12356 /* ----------------- shsub16<c> <Rd>,<Rn>,<Rm> ------------------- */
12358 UInt regD
= 99, regN
= 99, regM
= 99;
12362 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
12363 regN
= INSNT0(3,0);
12364 regD
= INSNT1(11,8);
12365 regM
= INSNT1(3,0);
12366 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
12370 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
12371 INSNA(11,8) == BITS4(1,1,1,1) &&
12372 INSNA(7,4) == BITS4(0,1,1,1)) {
12373 regD
= INSNA(15,12);
12374 regN
= INSNA(19,16);
12376 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
12382 IRTemp rNt
= newTemp(Ity_I32
);
12383 IRTemp rMt
= newTemp(Ity_I32
);
12384 IRTemp res_q
= newTemp(Ity_I32
);
12386 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
12387 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
12389 assign(res_q
, binop(Iop_HSub16Sx2
, mkexpr(rNt
), mkexpr(rMt
)));
12391 putIRegT( regD
, mkexpr(res_q
), condT
);
12393 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
12395 DIP("shsub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
12401 /* ----------------- smmls{r}<c> <Rd>,<Rn>,<Rm>,<Ra> ------------------- */
12403 UInt rD
= 99, rN
= 99, rM
= 99, rA
= 99;
12404 Bool round
= False
;
12408 if (INSNT0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
12409 && INSNT0(6,4) == BITS3(1,1,0)
12410 && INSNT1(7,5) == BITS3(0,0,0)) {
12411 round
= INSNT1(4,4);
12412 rA
= INSNT1(15,12);
12417 && !isBadRegT(rN
) && !isBadRegT(rM
) && !isBadRegT(rA
))
12421 if (INSNA(27,20) == BITS8(0,1,1,1,0,1,0,1)
12422 && INSNA(15,12) != BITS4(1,1,1,1)
12423 && (INSNA(7,4) & BITS4(1,1,0,1)) == BITS4(1,1,0,1)) {
12424 round
= INSNA(5,5);
12429 if (rD
!= 15 && rM
!= 15 && rN
!= 15)
12434 IRTemp irt_rA
= newTemp(Ity_I32
);
12435 IRTemp irt_rN
= newTemp(Ity_I32
);
12436 IRTemp irt_rM
= newTemp(Ity_I32
);
12437 assign( irt_rA
, isT
? getIRegT(rA
) : getIRegA(rA
) );
12438 assign( irt_rN
, isT
? getIRegT(rN
) : getIRegA(rN
) );
12439 assign( irt_rM
, isT
? getIRegT(rM
) : getIRegA(rM
) );
12441 = unop(Iop_64HIto32
,
12444 binop(Iop_32HLto64
, mkexpr(irt_rA
), mkU32(0)),
12445 binop(Iop_MullS32
, mkexpr(irt_rN
), mkexpr(irt_rM
))),
12446 mkU64(round
? 0x80000000ULL
: 0ULL)));
12448 putIRegT( rD
, res
, condT
);
12450 putIRegA(rD
, res
, condT
, Ijk_Boring
);
12451 DIP("smmls%s%s r%u, r%u, r%u, r%u\n",
12452 round
? "r" : "", nCC(conq
), rD
, rN
, rM
, rA
);
12458 /* -------------- smlald{x}<c> <RdLo>,<RdHi>,<Rn>,<Rm> ---------------- */
12460 UInt rN
= 99, rDlo
= 99, rDhi
= 99, rM
= 99;
12461 Bool m_swap
= False
;
12465 if (INSNT0(15,4) == 0xFBC &&
12466 (INSNT1(7,4) & BITS4(1,1,1,0)) == BITS4(1,1,0,0)) {
12468 rDlo
= INSNT1(15,12);
12469 rDhi
= INSNT1(11,8);
12471 m_swap
= (INSNT1(4,4) & 1) == 1;
12472 if (!isBadRegT(rDlo
) && !isBadRegT(rDhi
) && !isBadRegT(rN
)
12473 && !isBadRegT(rM
) && rDhi
!= rDlo
)
12477 if (INSNA(27,20) == BITS8(0,1,1,1,0,1,0,0)
12478 && (INSNA(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
12480 rDlo
= INSNA(15,12);
12481 rDhi
= INSNA(19,16);
12483 m_swap
= ( INSNA(5,5) & 1 ) == 1;
12484 if (rDlo
!= 15 && rDhi
!= 15
12485 && rN
!= 15 && rM
!= 15 && rDlo
!= rDhi
)
12491 IRTemp irt_rM
= newTemp(Ity_I32
);
12492 IRTemp irt_rN
= newTemp(Ity_I32
);
12493 IRTemp irt_rDhi
= newTemp(Ity_I32
);
12494 IRTemp irt_rDlo
= newTemp(Ity_I32
);
12495 IRTemp op_2
= newTemp(Ity_I32
);
12496 IRTemp pr_1
= newTemp(Ity_I64
);
12497 IRTemp pr_2
= newTemp(Ity_I64
);
12498 IRTemp result
= newTemp(Ity_I64
);
12499 IRTemp resHi
= newTemp(Ity_I32
);
12500 IRTemp resLo
= newTemp(Ity_I32
);
12501 assign( irt_rM
, isT
? getIRegT(rM
) : getIRegA(rM
));
12502 assign( irt_rN
, isT
? getIRegT(rN
) : getIRegA(rN
));
12503 assign( irt_rDhi
, isT
? getIRegT(rDhi
) : getIRegA(rDhi
));
12504 assign( irt_rDlo
, isT
? getIRegT(rDlo
) : getIRegA(rDlo
));
12505 assign( op_2
, genROR32(irt_rM
, m_swap
? 16 : 0) );
12506 assign( pr_1
, binop(Iop_MullS32
,
12508 unop(Iop_32to16
, mkexpr(irt_rN
))
12511 unop(Iop_32to16
, mkexpr(op_2
))
12515 assign( pr_2
, binop(Iop_MullS32
,
12516 binop(Iop_Sar32
, mkexpr(irt_rN
), mkU8(16)),
12517 binop(Iop_Sar32
, mkexpr(op_2
), mkU8(16))
12520 assign( result
, binop(Iop_Add64
,
12525 binop(Iop_32HLto64
,
12531 assign( resHi
, unop(Iop_64HIto32
, mkexpr(result
)) );
12532 assign( resLo
, unop(Iop_64to32
, mkexpr(result
)) );
12534 putIRegT( rDhi
, mkexpr(resHi
), condT
);
12535 putIRegT( rDlo
, mkexpr(resLo
), condT
);
12537 putIRegA( rDhi
, mkexpr(resHi
), condT
, Ijk_Boring
);
12538 putIRegA( rDlo
, mkexpr(resLo
), condT
, Ijk_Boring
);
12540 DIP("smlald%c%s r%u, r%u, r%u, r%u\n",
12541 m_swap
? 'x' : ' ', nCC(conq
), rDlo
, rDhi
, rN
, rM
);
12547 /* -------------- smlsld{x}<c> <RdLo>,<RdHi>,<Rn>,<Rm> ---------------- */
12549 UInt rN
= 99, rDlo
= 99, rDhi
= 99, rM
= 99;
12550 Bool m_swap
= False
;
12554 if ((INSNT0(15,4) == 0xFBD &&
12555 (INSNT1(7,4) & BITS4(1,1,1,0)) == BITS4(1,1,0,0))) {
12557 rDlo
= INSNT1(15,12);
12558 rDhi
= INSNT1(11,8);
12560 m_swap
= (INSNT1(4,4) & 1) == 1;
12561 if (!isBadRegT(rDlo
) && !isBadRegT(rDhi
) && !isBadRegT(rN
) &&
12562 !isBadRegT(rM
) && rDhi
!= rDlo
)
12566 if (INSNA(27,20) == BITS8(0,1,1,1,0,1,0,0) &&
12567 (INSNA(7,4) & BITS4(1,1,0,1)) == BITS4(0,1,0,1)) {
12569 rDlo
= INSNA(15,12);
12570 rDhi
= INSNA(19,16);
12572 m_swap
= (INSNA(5,5) & 1) == 1;
12573 if (rDlo
!= 15 && rDhi
!= 15 &&
12574 rN
!= 15 && rM
!= 15 && rDlo
!= rDhi
)
12579 IRTemp irt_rM
= newTemp(Ity_I32
);
12580 IRTemp irt_rN
= newTemp(Ity_I32
);
12581 IRTemp irt_rDhi
= newTemp(Ity_I32
);
12582 IRTemp irt_rDlo
= newTemp(Ity_I32
);
12583 IRTemp op_2
= newTemp(Ity_I32
);
12584 IRTemp pr_1
= newTemp(Ity_I64
);
12585 IRTemp pr_2
= newTemp(Ity_I64
);
12586 IRTemp result
= newTemp(Ity_I64
);
12587 IRTemp resHi
= newTemp(Ity_I32
);
12588 IRTemp resLo
= newTemp(Ity_I32
);
12589 assign( irt_rM
, isT
? getIRegT(rM
) : getIRegA(rM
) );
12590 assign( irt_rN
, isT
? getIRegT(rN
) : getIRegA(rN
) );
12591 assign( irt_rDhi
, isT
? getIRegT(rDhi
) : getIRegA(rDhi
) );
12592 assign( irt_rDlo
, isT
? getIRegT(rDlo
) : getIRegA(rDlo
) );
12593 assign( op_2
, genROR32(irt_rM
, m_swap
? 16 : 0) );
12594 assign( pr_1
, binop(Iop_MullS32
,
12596 unop(Iop_32to16
, mkexpr(irt_rN
))
12599 unop(Iop_32to16
, mkexpr(op_2
))
12603 assign( pr_2
, binop(Iop_MullS32
,
12604 binop(Iop_Sar32
, mkexpr(irt_rN
), mkU8(16)),
12605 binop(Iop_Sar32
, mkexpr(op_2
), mkU8(16))
12608 assign( result
, binop(Iop_Add64
,
12613 binop(Iop_32HLto64
,
12619 assign( resHi
, unop(Iop_64HIto32
, mkexpr(result
)) );
12620 assign( resLo
, unop(Iop_64to32
, mkexpr(result
)) );
12622 putIRegT( rDhi
, mkexpr(resHi
), condT
);
12623 putIRegT( rDlo
, mkexpr(resLo
), condT
);
12625 putIRegA( rDhi
, mkexpr(resHi
), condT
, Ijk_Boring
);
12626 putIRegA( rDlo
, mkexpr(resLo
), condT
, Ijk_Boring
);
12628 DIP("smlsld%c%s r%u, r%u, r%u, r%u\n",
12629 m_swap
? 'x' : ' ', nCC(conq
), rDlo
, rDhi
, rN
, rM
);
12635 /* ---------- Doesn't match anything. ---------- */
12644 /*------------------------------------------------------------*/
12645 /*--- V8 instructions ---*/
12646 /*------------------------------------------------------------*/
12648 /* Break a V128-bit value up into four 32-bit ints. */
12650 static void breakupV128to32s ( IRTemp t128
,
12652 IRTemp
* t3
, IRTemp
* t2
,
12653 IRTemp
* t1
, IRTemp
* t0
)
12655 IRTemp hi64
= newTemp(Ity_I64
);
12656 IRTemp lo64
= newTemp(Ity_I64
);
12657 assign( hi64
, unop(Iop_V128HIto64
, mkexpr(t128
)) );
12658 assign( lo64
, unop(Iop_V128to64
, mkexpr(t128
)) );
12660 vassert(t0
&& *t0
== IRTemp_INVALID
);
12661 vassert(t1
&& *t1
== IRTemp_INVALID
);
12662 vassert(t2
&& *t2
== IRTemp_INVALID
);
12663 vassert(t3
&& *t3
== IRTemp_INVALID
);
12665 *t0
= newTemp(Ity_I32
);
12666 *t1
= newTemp(Ity_I32
);
12667 *t2
= newTemp(Ity_I32
);
12668 *t3
= newTemp(Ity_I32
);
12669 assign( *t0
, unop(Iop_64to32
, mkexpr(lo64
)) );
12670 assign( *t1
, unop(Iop_64HIto32
, mkexpr(lo64
)) );
12671 assign( *t2
, unop(Iop_64to32
, mkexpr(hi64
)) );
12672 assign( *t3
, unop(Iop_64HIto32
, mkexpr(hi64
)) );
12676 /* Both ARM and Thumb */
12678 /* Translate a V8 instruction. If successful, returns True and *dres
12679 may or may not be updated. If unsuccessful, returns False and
12680 doesn't change *dres nor create any IR.
12682 The Thumb and ARM encodings are potentially different. In both
12683 ARM and Thumb mode, the caller must pass the entire 32 bits of
12684 the instruction. Callers may pass any instruction; this function
12685 ignores anything it doesn't recognise.
12687 Caller must supply an IRTemp 'condT' holding the gating condition,
12688 or IRTemp_INVALID indicating the insn is always executed.
12690 If we are decoding an ARM instruction which is in the NV space
12691 then it is expected that condT will be IRTemp_INVALID, and that is
12692 asserted for. That condition is ensured by the logic near the top
12693 of disInstr_ARM_WRK, that sets up condT.
12695 When decoding for Thumb, the caller must pass the ITState pre/post
12696 this instruction, so that we can generate a SIGILL in the cases where
12697 the instruction may not be in an IT block. When decoding for ARM,
12698 both of these must be IRTemp_INVALID.
12700 Finally, the caller must indicate whether this occurs in ARM or in
12703 static Bool
decode_V8_instruction (
12704 /*MOD*/DisResult
* dres
,
12708 IRTemp old_itstate
,
12712 # define INSN(_bMax,_bMin) SLICE_UInt(insnv8, (_bMax), (_bMin))
12715 vassert(old_itstate
!= IRTemp_INVALID
);
12716 vassert(new_itstate
!= IRTemp_INVALID
);
12718 vassert(old_itstate
== IRTemp_INVALID
);
12719 vassert(new_itstate
== IRTemp_INVALID
);
12722 /* ARMCondcode 'conq' is only used for debug printing and for no other
12723 purpose. For ARM, this is simply the top 4 bits of the instruction.
12724 For Thumb, the condition is not (really) known until run time, and so
12725 we set it to ARMCondAL in order that printing of these instructions
12726 does not show any condition. */
12731 conq
= (ARMCondcode
)INSN(31,28);
12732 if (conq
== ARMCondNV
|| conq
== ARMCondAL
) {
12733 vassert(condT
== IRTemp_INVALID
);
12735 vassert(condT
!= IRTemp_INVALID
);
12737 vassert(conq
>= ARMCondEQ
&& conq
<= ARMCondNV
);
12740 /* ----------- {AESD, AESE, AESMC, AESIMC}.8 q_q ----------- */
12741 /* 31 27 23 21 19 17 15 11 7 3
12742 T1: 1111 1111 1 D 11 sz 00 d 0011 00 M 0 m AESE Qd, Qm
12743 A1: 1111 0011 1 D 11 sz 00 d 0011 00 M 0 m AESE Qd, Qm
12745 T1: 1111 1111 1 D 11 sz 00 d 0011 01 M 0 m AESD Qd, Qm
12746 A1: 1111 0011 1 D 11 sz 00 d 0011 01 M 0 m AESD Qd, Qm
12748 T1: 1111 1111 1 D 11 sz 00 d 0011 10 M 0 m AESMC Qd, Qm
12749 A1: 1111 0011 1 D 11 sz 00 d 0011 10 M 0 m AESMC Qd, Qm
12751 T1: 1111 1111 1 D 11 sz 00 d 0011 11 M 0 m AESIMC Qd, Qm
12752 A1: 1111 0011 1 D 11 sz 00 d 0011 11 M 0 m AESIMC Qd, Qm
12755 ARM encoding is in NV space.
12756 In Thumb mode, we must not be in an IT block.
12759 UInt regD
= 99, regM
= 99, opc
= 4/*invalid*/;
12762 UInt high9
= isT
? BITS9(1,1,1,1,1,1,1,1,1) : BITS9(1,1,1,1,0,0,1,1,1);
12763 if (INSN(31,23) == high9
&& INSN(21,16) == BITS6(1,1,0,0,0,0)
12764 && INSN(11,8) == BITS4(0,0,1,1) && INSN(4,4) == 0) {
12765 UInt bitD
= INSN(22,22);
12766 UInt fldD
= INSN(15,12);
12767 UInt bitM
= INSN(5,5);
12768 UInt fldM
= INSN(3,0);
12770 regD
= (bitD
<< 4) | fldD
;
12771 regM
= (bitM
<< 4) | fldM
;
12773 if ((regD
& 1) == 1 || (regM
& 1) == 1)
12778 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
12780 /* In ARM mode, this is statically unconditional. In Thumb mode,
12781 this must be dynamically unconditional, and we've SIGILLd if not.
12782 In either case we can create unconditional IR. */
12783 IRTemp op1
= newTemp(Ity_V128
);
12784 IRTemp op2
= newTemp(Ity_V128
);
12785 IRTemp src
= newTemp(Ity_V128
);
12786 IRTemp res
= newTemp(Ity_V128
);
12787 assign(op1
, getQReg(regD
>> 1));
12788 assign(op2
, getQReg(regM
>> 1));
12789 assign(src
, opc
== BITS2(0,0) || opc
== BITS2(0,1)
12790 ? binop(Iop_XorV128
, mkexpr(op1
), mkexpr(op2
))
12794 = { &armg_dirtyhelper_AESE
, &armg_dirtyhelper_AESD
,
12795 &armg_dirtyhelper_AESMC
, &armg_dirtyhelper_AESIMC
};
12796 const HChar
* hNames
[4]
12797 = { "armg_dirtyhelper_AESE", "armg_dirtyhelper_AESD",
12798 "armg_dirtyhelper_AESMC", "armg_dirtyhelper_AESIMC" };
12799 const HChar
* iNames
[4]
12800 = { "aese", "aesd", "aesmc", "aesimc" };
12802 vassert(opc
>= 0 && opc
<= 3);
12803 void* helper
= helpers
[opc
];
12804 const HChar
* hname
= hNames
[opc
];
12806 IRTemp w32_3
, w32_2
, w32_1
, w32_0
;
12807 w32_3
= w32_2
= w32_1
= w32_0
= IRTemp_INVALID
;
12808 breakupV128to32s( src
, &w32_3
, &w32_2
, &w32_1
, &w32_0
);
12811 = unsafeIRDirty_1_N( res
, 0/*regparms*/, hname
, helper
,
12814 mkexpr(w32_3
), mkexpr(w32_2
),
12815 mkexpr(w32_1
), mkexpr(w32_0
)) );
12816 stmt(IRStmt_Dirty(di
));
12818 putQReg(regD
>> 1, mkexpr(res
), IRTemp_INVALID
);
12819 DIP("%s.8 q%d, q%d\n", iNames
[opc
], regD
>> 1, regM
>> 1);
12825 /* ----------- SHA 3-reg insns q_q_q ----------- */
12827 31 27 23 19 15 11 7 3
12828 T1: 1110 1111 0 D 00 n d 1100 N Q M 0 m SHA1C Qd, Qn, Qm ix=0
12829 A1: 1111 0010 ----------------------------
12831 T1: 1110 1111 0 D 01 n d 1100 N Q M 0 m SHA1P Qd, Qn, Qm ix=1
12832 A1: 1111 0010 ----------------------------
12834 T1: 1110 1111 0 D 10 n d 1100 N Q M 0 m SHA1M Qd, Qn, Qm ix=2
12835 A1: 1111 0010 ----------------------------
12837 T1: 1110 1111 0 D 11 n d 1100 N Q M 0 m SHA1SU0 Qd, Qn, Qm ix=3
12838 A1: 1111 0010 ----------------------------
12839 (that's a complete set of 4, based on insn[21,20])
12841 T1: 1111 1111 0 D 00 n d 1100 N Q M 0 m SHA256H Qd, Qn, Qm ix=4
12842 A1: 1111 0011 ----------------------------
12844 T1: 1111 1111 0 D 01 n d 1100 N Q M 0 m SHA256H2 Qd, Qn, Qm ix=5
12845 A1: 1111 0011 ----------------------------
12847 T1: 1111 1111 0 D 10 n d 1100 N Q M 0 m SHA256SU1 Qd, Qn, Qm ix=6
12848 A1: 1111 0011 ----------------------------
12849 (3/4 of a complete set of 4, based on insn[21,20])
12851 Q must be 1. Same comments about conditionalisation as for the AES
12855 UInt ix
= 8; /* invalid */
12858 UInt hi9_sha1
= isT
? BITS9(1,1,1,0,1,1,1,1,0)
12859 : BITS9(1,1,1,1,0,0,1,0,0);
12860 UInt hi9_sha256
= isT
? BITS9(1,1,1,1,1,1,1,1,0)
12861 : BITS9(1,1,1,1,0,0,1,1,0);
12862 if ((INSN(31,23) == hi9_sha1
|| INSN(31,23) == hi9_sha256
)
12863 && INSN(11,8) == BITS4(1,1,0,0)
12864 && INSN(6,6) == 1 && INSN(4,4) == 0) {
12866 if (INSN(31,23) == hi9_sha256
)
12872 UInt regN
= (INSN(7,7) << 4) | INSN(19,16);
12873 UInt regD
= (INSN(22,22) << 4) | INSN(15,12);
12874 UInt regM
= (INSN(5,5) << 4) | INSN(3,0);
12875 if ((regD
& 1) == 1 || (regM
& 1) == 1 || (regN
& 1) == 1)
12879 vassert(ix
>= 0 && ix
< 7);
12880 const HChar
* inames
[7]
12881 = { "sha1c", "sha1p", "sha1m", "sha1su0",
12882 "sha256h", "sha256h2", "sha256su1" };
12883 void(*helpers
[7])(V128
*,UInt
,UInt
,UInt
,UInt
,UInt
,UInt
,
12884 UInt
,UInt
,UInt
,UInt
,UInt
,UInt
)
12885 = { &armg_dirtyhelper_SHA1C
, &armg_dirtyhelper_SHA1P
,
12886 &armg_dirtyhelper_SHA1M
, &armg_dirtyhelper_SHA1SU0
,
12887 &armg_dirtyhelper_SHA256H
, &armg_dirtyhelper_SHA256H2
,
12888 &armg_dirtyhelper_SHA256SU1
};
12889 const HChar
* hnames
[7]
12890 = { "armg_dirtyhelper_SHA1C", "armg_dirtyhelper_SHA1P",
12891 "armg_dirtyhelper_SHA1M", "armg_dirtyhelper_SHA1SU0",
12892 "armg_dirtyhelper_SHA256H", "armg_dirtyhelper_SHA256H2",
12893 "armg_dirtyhelper_SHA256SU1" };
12895 /* This is a really lame way to implement this, even worse than
12896 the arm64 version. But at least it works. */
12899 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
12902 IRTemp vD
= newTemp(Ity_V128
);
12903 IRTemp vN
= newTemp(Ity_V128
);
12904 IRTemp vM
= newTemp(Ity_V128
);
12905 assign(vD
, getQReg(regD
>> 1));
12906 assign(vN
, getQReg(regN
>> 1));
12907 assign(vM
, getQReg(regM
>> 1));
12909 IRTemp d32_3
, d32_2
, d32_1
, d32_0
;
12910 d32_3
= d32_2
= d32_1
= d32_0
= IRTemp_INVALID
;
12911 breakupV128to32s( vD
, &d32_3
, &d32_2
, &d32_1
, &d32_0
);
12913 IRTemp n32_3_pre
, n32_2_pre
, n32_1_pre
, n32_0_pre
;
12914 n32_3_pre
= n32_2_pre
= n32_1_pre
= n32_0_pre
= IRTemp_INVALID
;
12915 breakupV128to32s( vN
, &n32_3_pre
, &n32_2_pre
, &n32_1_pre
, &n32_0_pre
);
12917 IRTemp m32_3
, m32_2
, m32_1
, m32_0
;
12918 m32_3
= m32_2
= m32_1
= m32_0
= IRTemp_INVALID
;
12919 breakupV128to32s( vM
, &m32_3
, &m32_2
, &m32_1
, &m32_0
);
12921 IRTemp n32_3
= newTemp(Ity_I32
);
12922 IRTemp n32_2
= newTemp(Ity_I32
);
12923 IRTemp n32_1
= newTemp(Ity_I32
);
12924 IRTemp n32_0
= newTemp(Ity_I32
);
12926 /* Mask off any bits of the N register operand that aren't actually
12927 needed, so that Memcheck doesn't complain unnecessarily. */
12929 case 0: case 1: case 2:
12930 assign(n32_3
, mkU32(0));
12931 assign(n32_2
, mkU32(0));
12932 assign(n32_1
, mkU32(0));
12933 assign(n32_0
, mkexpr(n32_0_pre
));
12935 case 3: case 4: case 5: case 6:
12936 assign(n32_3
, mkexpr(n32_3_pre
));
12937 assign(n32_2
, mkexpr(n32_2_pre
));
12938 assign(n32_1
, mkexpr(n32_1_pre
));
12939 assign(n32_0
, mkexpr(n32_0_pre
));
12948 mkexpr(d32_3
), mkexpr(d32_2
), mkexpr(d32_1
), mkexpr(d32_0
),
12949 mkexpr(n32_3
), mkexpr(n32_2
), mkexpr(n32_1
), mkexpr(n32_0
),
12950 mkexpr(m32_3
), mkexpr(m32_2
), mkexpr(m32_1
), mkexpr(m32_0
)
12953 IRTemp res
= newTemp(Ity_V128
);
12954 IRDirty
* di
= unsafeIRDirty_1_N( res
, 0/*regparms*/,
12955 hnames
[ix
], helpers
[ix
], argvec
);
12956 stmt(IRStmt_Dirty(di
));
12957 putQReg(regD
>> 1, mkexpr(res
), IRTemp_INVALID
);
12959 DIP("%s.8 q%u, q%u, q%u\n",
12960 inames
[ix
], regD
>> 1, regN
>> 1, regM
>> 1);
12966 /* ----------- SHA1SU1, SHA256SU0 ----------- */
12968 31 27 23 21 19 15 11 7 3
12969 T1: 1111 1111 1 D 11 1010 d 0011 10 M 0 m SHA1SU1 Qd, Qm
12970 A1: 1111 0011 ----------------------------
12972 T1: 1111 1111 1 D 11 1010 d 0011 11 M 0 m SHA256SU0 Qd, Qm
12973 A1: 1111 0011 ----------------------------
12975 Same comments about conditionalisation as for the AES group above apply.
12980 UInt hi9
= isT
? BITS9(1,1,1,1,1,1,1,1,1) : BITS9(1,1,1,1,0,0,1,1,1);
12981 if (INSN(31,23) == hi9
&& INSN(21,16) == BITS6(1,1,1,0,1,0)
12982 && INSN(11,7) == BITS5(0,0,1,1,1) && INSN(4,4) == 0) {
12986 UInt regD
= (INSN(22,22) << 4) | INSN(15,12);
12987 UInt regM
= (INSN(5,5) << 4) | INSN(3,0);
12988 if ((regD
& 1) == 1 || (regM
& 1) == 1)
12991 Bool is_1SU1
= INSN(6,6) == 0;
12995 = is_1SU1
? "sha1su1" : "sha256su0";
12996 void (*helper
)(V128
*,UInt
,UInt
,UInt
,UInt
,UInt
,UInt
,UInt
,UInt
)
12997 = is_1SU1
? &armg_dirtyhelper_SHA1SU1
12998 : *armg_dirtyhelper_SHA256SU0
;
13000 = is_1SU1
? "armg_dirtyhelper_SHA1SU1"
13001 : "armg_dirtyhelper_SHA256SU0";
13004 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13007 IRTemp vD
= newTemp(Ity_V128
);
13008 IRTemp vM
= newTemp(Ity_V128
);
13009 assign(vD
, getQReg(regD
>> 1));
13010 assign(vM
, getQReg(regM
>> 1));
13012 IRTemp d32_3
, d32_2
, d32_1
, d32_0
;
13013 d32_3
= d32_2
= d32_1
= d32_0
= IRTemp_INVALID
;
13014 breakupV128to32s( vD
, &d32_3
, &d32_2
, &d32_1
, &d32_0
);
13016 IRTemp m32_3
, m32_2
, m32_1
, m32_0
;
13017 m32_3
= m32_2
= m32_1
= m32_0
= IRTemp_INVALID
;
13018 breakupV128to32s( vM
, &m32_3
, &m32_2
, &m32_1
, &m32_0
);
13023 mkexpr(d32_3
), mkexpr(d32_2
), mkexpr(d32_1
), mkexpr(d32_0
),
13024 mkexpr(m32_3
), mkexpr(m32_2
), mkexpr(m32_1
), mkexpr(m32_0
)
13027 IRTemp res
= newTemp(Ity_V128
);
13028 IRDirty
* di
= unsafeIRDirty_1_N( res
, 0/*regparms*/,
13029 hname
, helper
, argvec
);
13030 stmt(IRStmt_Dirty(di
));
13031 putQReg(regD
>> 1, mkexpr(res
), IRTemp_INVALID
);
13033 DIP("%s.8 q%u, q%u\n", iname
, regD
>> 1, regM
>> 1);
13039 /* ----------- SHA1H ----------- */
13041 31 27 23 21 19 15 11 7 3
13042 T1: 1111 1111 1 D 11 1001 d 0010 11 M 0 m SHA1H Qd, Qm
13043 A1: 1111 0011 ----------------------------
13045 Same comments about conditionalisation as for the AES group above apply.
13050 UInt hi9
= isT
? BITS9(1,1,1,1,1,1,1,1,1) : BITS9(1,1,1,1,0,0,1,1,1);
13051 if (INSN(31,23) == hi9
&& INSN(21,16) == BITS6(1,1,1,0,0,1)
13052 && INSN(11,6) == BITS6(0,0,1,0,1,1) && INSN(4,4) == 0) {
13056 UInt regD
= (INSN(22,22) << 4) | INSN(15,12);
13057 UInt regM
= (INSN(5,5) << 4) | INSN(3,0);
13058 if ((regD
& 1) == 1 || (regM
& 1) == 1)
13062 const HChar
* iname
= "sha1h";
13063 void (*helper
)(V128
*,UInt
,UInt
,UInt
,UInt
) = &armg_dirtyhelper_SHA1H
;
13064 const HChar
* hname
= "armg_dirtyhelper_SHA1H";
13067 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13070 IRTemp vM
= newTemp(Ity_V128
);
13071 assign(vM
, getQReg(regM
>> 1));
13073 IRTemp m32_3
, m32_2
, m32_1
, m32_0
;
13074 m32_3
= m32_2
= m32_1
= m32_0
= IRTemp_INVALID
;
13075 breakupV128to32s( vM
, &m32_3
, &m32_2
, &m32_1
, &m32_0
);
13076 /* m32_3, m32_2, m32_1 are just abandoned. No harm; iropt will
13079 IRExpr
* zero
= mkU32(0);
13080 IRExpr
** argvec
= mkIRExprVec_5(IRExpr_VECRET(),
13081 zero
, zero
, zero
, mkexpr(m32_0
));
13083 IRTemp res
= newTemp(Ity_V128
);
13084 IRDirty
* di
= unsafeIRDirty_1_N( res
, 0/*regparms*/,
13085 hname
, helper
, argvec
);
13086 stmt(IRStmt_Dirty(di
));
13087 putQReg(regD
>> 1, mkexpr(res
), IRTemp_INVALID
);
13089 DIP("%s.8 q%u, q%u\n", iname
, regD
>> 1, regM
>> 1);
13095 /* ----------- VMULL.P64 ----------- */
13097 31 27 23 21 19 15 11 7 3
13098 T2: 1110 1111 1 D 10 n d 1110 N 0 M 0 m
13099 A2: 1111 0010 -------------------------
13101 The ARM documentation is pretty difficult to follow here.
13102 Same comments about conditionalisation as for the AES group above apply.
13107 UInt hi9
= isT
? BITS9(1,1,1,0,1,1,1,1,1) : BITS9(1,1,1,1,0,0,1,0,1);
13108 if (INSN(31,23) == hi9
&& INSN(21,20) == BITS2(1,0)
13109 && INSN(11,8) == BITS4(1,1,1,0)
13110 && INSN(6,6) == 0 && INSN(4,4) == 0) {
13114 UInt regN
= (INSN(7,7) << 4) | INSN(19,16);
13115 UInt regD
= (INSN(22,22) << 4) | INSN(15,12);
13116 UInt regM
= (INSN(5,5) << 4) | INSN(3,0);
13118 if ((regD
& 1) == 1)
13122 const HChar
* iname
= "vmull";
13123 void (*helper
)(V128
*,UInt
,UInt
,UInt
,UInt
) = &armg_dirtyhelper_VMULLP64
;
13124 const HChar
* hname
= "armg_dirtyhelper_VMULLP64";
13127 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13130 IRTemp srcN
= newTemp(Ity_I64
);
13131 IRTemp srcM
= newTemp(Ity_I64
);
13132 assign(srcN
, getDRegI64(regN
));
13133 assign(srcM
, getDRegI64(regM
));
13135 IRExpr
** argvec
= mkIRExprVec_5(IRExpr_VECRET(),
13136 unop(Iop_64HIto32
, mkexpr(srcN
)),
13137 unop(Iop_64to32
, mkexpr(srcN
)),
13138 unop(Iop_64HIto32
, mkexpr(srcM
)),
13139 unop(Iop_64to32
, mkexpr(srcM
)));
13141 IRTemp res
= newTemp(Ity_V128
);
13142 IRDirty
* di
= unsafeIRDirty_1_N( res
, 0/*regparms*/,
13143 hname
, helper
, argvec
);
13144 stmt(IRStmt_Dirty(di
));
13145 putQReg(regD
>> 1, mkexpr(res
), IRTemp_INVALID
);
13147 DIP("%s.p64 q%u, q%u, w%u\n", iname
, regD
>> 1, regN
, regM
);
13153 /* ----------- LDA{,B,H}, STL{,B,H} ----------- */
13154 /* 31 27 23 19 15 11 7 3
13155 A1: cond 0001 1001 n t 1100 1001 1111 LDA Rt, [Rn]
13156 A1: cond 0001 1111 n t 1100 1001 1111 LDAH Rt, [Rn]
13157 A1: cond 0001 1101 n t 1100 1001 1111 LDAB Rt, [Rn]
13159 A1: cond 0001 1000 n 1111 1100 1001 t STL Rt, [Rn]
13160 A1: cond 0001 1110 n 1111 1100 1001 t STLH Rt, [Rn]
13161 A1: cond 0001 1100 n 1111 1100 1001 t STLB Rt, [Rn]
13163 T1: 1110 1000 1101 n t 1111 1010 1111 LDA Rt, [Rn]
13164 T1: 1110 1000 1101 n t 1111 1001 1111 LDAH Rt, [Rn]
13165 T1: 1110 1000 1101 n t 1111 1000 1111 LDAB Rt, [Rn]
13167 T1: 1110 1000 1100 n t 1111 1010 1111 STL Rt, [Rn]
13168 T1: 1110 1000 1100 n t 1111 1001 1111 STLH Rt, [Rn]
13169 T1: 1110 1000 1100 n t 1111 1000 1111 STLB Rt, [Rn]
13172 UInt nn
= 16; // invalid
13173 UInt tt
= 16; // invalid
13174 UInt szBlg2
= 4; // invalid
13175 Bool isLoad
= False
;
13178 if (INSN(31,21) == BITS11(1,1,1,0,1,0,0,0,1,1,0)
13179 && INSN(11,6) == BITS6(1,1,1,1,1,0)
13180 && INSN(3,0) == BITS4(1,1,1,1)) {
13183 isLoad
= INSN(20,20) == 1;
13184 szBlg2
= INSN(5,4); // 00:B 01:H 10:W 11:invalid
13185 gate
= szBlg2
!= BITS2(1,1) && tt
!= 15 && nn
!= 15;
13188 if (INSN(27,23) == BITS5(0,0,0,1,1) && INSN(20,20) == 1
13189 && INSN(11,0) == BITS12(1,1,0,0,1,0,0,1,1,1,1,1)) {
13193 szBlg2
= INSN(22,21); // 10:B 11:H 00:W 01:invalid
13194 gate
= szBlg2
!= BITS2(0,1) && tt
!= 15 && nn
!= 15;
13197 if (INSN(27,23) == BITS5(0,0,0,1,1) && INSN(20,20) == 0
13198 && INSN(15,4) == BITS12(1,1,1,1,1,1,0,0,1,0,0,1)) {
13202 szBlg2
= INSN(22,21); // 10:B 11:H 00:W 01:invalid
13203 gate
= szBlg2
!= BITS2(0,1) && tt
!= 15 && nn
!= 15;
13206 // Rearrange szBlg2 bits to be the same as the Thumb case
13208 case 2: szBlg2
= 0; break;
13209 case 3: szBlg2
= 1; break;
13210 case 0: szBlg2
= 2; break;
13211 default: /*NOTREACHED*/vassert(0);
13215 // For both encodings, the instruction is guarded by condT, which
13216 // is passed in by the caller. Note that the the loads and stores
13217 // are conditional, so we don't have to truncate the IRSB at this
13218 // point, but the fence is unconditional. There's no way to
13219 // represent a conditional fence without a side exit, but it
13220 // doesn't matter from a correctness standpoint that it is
13221 // unconditional -- it just loses a bit of performance in the
13222 // case where the condition doesn't hold.
13224 vassert(szBlg2
<= 2 && nn
<= 14 && tt
<= 14);
13225 IRExpr
* ea
= llGetIReg(nn
);
13227 static IRLoadGOp cvt
[3]
13228 = { ILGop_8Uto32
, ILGop_16Uto32
, ILGop_Ident32
};
13229 IRTemp data
= newTemp(Ity_I32
);
13230 loadGuardedLE(data
, cvt
[szBlg2
], ea
, mkU32(0)/*alt*/, condT
);
13232 putIRegT(tt
, mkexpr(data
), condT
);
13234 putIRegA(tt
, mkexpr(data
), condT
, Ijk_INVALID
);
13236 stmt(IRStmt_MBE(Imbe_Fence
));
13238 stmt(IRStmt_MBE(Imbe_Fence
));
13239 IRExpr
* data
= llGetIReg(tt
);
13241 case 0: data
= unop(Iop_32to8
, data
); break;
13242 case 1: data
= unop(Iop_32to16
, data
); break;
13244 default: vassert(0);
13246 storeGuardedLE(ea
, data
, condT
);
13248 const HChar
* ldNames
[3] = { "ldab", "ldah", "lda" };
13249 const HChar
* stNames
[3] = { "stlb", "stlh", "stl" };
13250 DIP("%s r%u, [r%u]", (isLoad
? ldNames
: stNames
)[szBlg2
], tt
, nn
);
13253 /* else fall through */
13256 /* ----------- LDAEX{,B,H,D}, STLEX{,B,H,D} ----------- */
13257 /* 31 27 23 19 15 11 7 3
13258 A1: cond 0001 1101 n t 1110 1001 1111 LDAEXB Rt, [Rn]
13259 A1: cond 0001 1111 n t 1110 1001 1111 LDAEXH Rt, [Rn]
13260 A1: cond 0001 1001 n t 1110 1001 1111 LDAEX Rt, [Rn]
13261 A1: cond 0001 1011 n t 1110 1001 1111 LDAEXD Rt, Rt+1, [Rn]
13263 A1: cond 0001 1100 n d 1110 1001 t STLEXB Rd, Rt, [Rn]
13264 A1: cond 0001 1110 n d 1110 1001 t STLEXH Rd, Rt, [Rn]
13265 A1: cond 0001 1000 n d 1110 1001 t STLEX Rd, Rt, [Rn]
13266 A1: cond 0001 1010 n d 1110 1001 t STLEXD Rd, Rt, Rt+1, [Rn]
13268 31 28 24 19 15 11 7 3
13269 T1: 111 0100 01101 n t 1111 1100 1111 LDAEXB Rt, [Rn]
13270 T1: 111 0100 01101 n t 1111 1101 1111 LDAEXH Rt, [Rn]
13271 T1: 111 0100 01101 n t 1111 1110 1111 LDAEX Rt, [Rn]
13272 T1: 111 0100 01101 n t t2 1111 1111 LDAEXD Rt, Rt2, [Rn]
13274 T1: 111 0100 01100 n t 1111 1100 d STLEXB Rd, Rt, [Rn]
13275 T1: 111 0100 01100 n t 1111 1101 d STLEXH Rd, Rt, [Rn]
13276 T1: 111 0100 01100 n t 1111 1110 d STLEX Rd, Rt, [Rn]
13277 T1: 111 0100 01100 n t t2 1111 d STLEXD Rd, Rt, Rt2, [Rn]
13280 UInt nn
= 16; // invalid
13281 UInt tt
= 16; // invalid
13282 UInt tt2
= 16; // invalid
13283 UInt dd
= 16; // invalid
13284 UInt szBlg2
= 4; // invalid
13285 Bool isLoad
= False
;
13288 if (INSN(31,21) == BITS11(1,1,1,0,1,0,0,0,1,1,0)
13289 && INSN(7,6) == BITS2(1,1)) {
13290 isLoad
= INSN(20,20) == 1;
13294 szBlg2
= INSN(5,4);
13297 if (szBlg2
< BITS2(1,1) && tt2
!= BITS4(1,1,1,1)) gate
= False
;
13298 if (isLoad
&& dd
!= BITS4(1,1,1,1)) gate
= False
;
13299 // re-set not-used register values to invalid
13300 if (szBlg2
< BITS2(1,1)) tt2
= 16;
13301 if (isLoad
) dd
= 16;
13304 /* ARM encoding. Do the load and store cases separately as
13305 the register numbers are in different places and a combined decode
13306 is too confusing. */
13307 if (INSN(27,23) == BITS5(0,0,0,1,1) && INSN(20,20) == 1
13308 && INSN(11,0) == BITS12(1,1,1,0,1,0,0,1,1,1,1,1)) {
13309 szBlg2
= INSN(22,21);
13316 if (INSN(27,23) == BITS5(0,0,0,1,1) && INSN(20,20) == 0
13317 && INSN(11,4) == BITS8(1,1,1,0,1,0,0,1)) {
13318 szBlg2
= INSN(22,21);
13326 // Rearrange szBlg2 bits to be the same as the Thumb case
13328 case 2: szBlg2
= 0; break;
13329 case 3: szBlg2
= 1; break;
13330 case 0: szBlg2
= 2; break;
13331 case 1: szBlg2
= 3; break;
13332 default: /*NOTREACHED*/vassert(0);
13336 // Perform further checks on register numbers
13338 /**/ if (isT
&& isLoad
) {
13341 if (! (tt
!= 13 && tt
!= 15 && nn
!= 15)) gate
= False
;
13343 if (! (tt
!= 13 && tt
!= 15 && tt2
!= 13 && tt2
!= 15
13344 && tt
!= tt2
&& nn
!= 15)) gate
= False
;
13347 else if (isT
&& !isLoad
) {
13350 if (! (dd
!= 13 && dd
!= 15 && tt
!= 13 && tt
!= 15
13351 && nn
!= 15 && dd
!= nn
&& dd
!= tt
)) gate
= False
;
13353 if (! (dd
!= 13 && dd
!= 15 && tt
!= 13 && tt
!= 15
13354 && tt2
!= 13 && tt2
!= 15 && nn
!= 15 && dd
!= nn
13355 && dd
!= tt
&& dd
!= tt2
)) gate
= False
;
13358 else if (!isT
&& isLoad
) {
13361 if (! (tt
!= 15 && nn
!= 15)) gate
= False
;
13363 if (! ((tt
& 1) == 0 && tt
!= 14 && nn
!= 15)) gate
= False
;
13364 vassert(tt2
== 16/*invalid*/);
13368 else if (!isT
&& !isLoad
) {
13371 if (! (dd
!= 15 && tt
!= 15 && nn
!= 15
13372 && dd
!= nn
&& dd
!= tt
)) gate
= False
;
13374 if (! (dd
!= 15 && (tt
& 1) == 0 && tt
!= 14 && nn
!= 15
13375 && dd
!= nn
&& dd
!= tt
&& dd
!= tt
+1)) gate
= False
;
13376 vassert(tt2
== 16/*invalid*/);
13380 else /*NOTREACHED*/vassert(0);
13384 vassert(szBlg2
<= 3);
13385 if (szBlg2
< 3) { vassert(tt2
== 16/*invalid*/); }
13386 else { vassert(tt2
<= 14); }
13387 if (isLoad
) { vassert(dd
== 16/*invalid*/); }
13388 else { vassert(dd
<= 14); }
13390 // If we're still good even after all that, generate the IR.
13392 /* First, go unconditional. Staying in-line is too complex. */
13394 vassert(condT
!= IRTemp_INVALID
);
13395 mk_skip_over_T32_if_cond_is_false( condT
);
13397 if (condT
!= IRTemp_INVALID
) {
13398 mk_skip_over_A32_if_cond_is_false( condT
);
13399 condT
= IRTemp_INVALID
;
13402 /* Now the load or store. */
13403 IRType ty
= Ity_INVALID
; /* the type of the transferred data */
13404 const HChar
* nm
= NULL
;
13406 case 0: nm
= "b"; ty
= Ity_I8
; break;
13407 case 1: nm
= "h"; ty
= Ity_I16
; break;
13408 case 2: nm
= ""; ty
= Ity_I32
; break;
13409 case 3: nm
= "d"; ty
= Ity_I64
; break;
13410 default: vassert(0);
13412 IRExpr
* ea
= isT
? getIRegT(nn
) : getIRegA(nn
);
13414 // LOAD. Transaction, then fence.
13415 IROp widen
= Iop_INVALID
;
13417 case 0: widen
= Iop_8Uto32
; break;
13418 case 1: widen
= Iop_16Uto32
; break;
13419 case 2: case 3: break;
13420 default: vassert(0);
13422 IRTemp res
= newTemp(ty
);
13423 // FIXME: assumes little-endian guest
13424 stmt( IRStmt_LLSC(Iend_LE
, res
, ea
, NULL
/*this is a load*/) );
13426 # define PUT_IREG(_nnz, _eez) \
13427 do { vassert((_nnz) <= 14); /* no writes to the PC */ \
13428 if (isT) { putIRegT((_nnz), (_eez), IRTemp_INVALID); } \
13429 else { putIRegA((_nnz), (_eez), \
13430 IRTemp_INVALID, Ijk_Boring); } } while(0)
13431 if (ty
== Ity_I64
) {
13432 // FIXME: assumes little-endian guest
13433 PUT_IREG(tt
, unop(Iop_64to32
, mkexpr(res
)));
13434 PUT_IREG(tt2
, unop(Iop_64HIto32
, mkexpr(res
)));
13436 PUT_IREG(tt
, widen
== Iop_INVALID
13437 ? mkexpr(res
) : unop(widen
, mkexpr(res
)));
13439 stmt(IRStmt_MBE(Imbe_Fence
));
13440 if (ty
== Ity_I64
) {
13441 DIP("ldrex%s%s r%u, r%u, [r%u]\n",
13442 nm
, isT
? "" : nCC(conq
), tt
, tt2
, nn
);
13444 DIP("ldrex%s%s r%u, [r%u]\n", nm
, isT
? "" : nCC(conq
), tt
, nn
);
13448 // STORE. Fence, then transaction.
13449 IRTemp resSC1
, resSC32
, data
;
13450 IROp narrow
= Iop_INVALID
;
13452 case 0: narrow
= Iop_32to8
; break;
13453 case 1: narrow
= Iop_32to16
; break;
13454 case 2: case 3: break;
13455 default: vassert(0);
13457 stmt(IRStmt_MBE(Imbe_Fence
));
13458 data
= newTemp(ty
);
13459 # define GET_IREG(_nnz) (isT ? getIRegT(_nnz) : getIRegA(_nnz))
13462 // FIXME: assumes little-endian guest
13463 ? binop(Iop_32HLto64
, GET_IREG(tt2
), GET_IREG(tt
))
13464 : narrow
== Iop_INVALID
13466 : unop(narrow
, GET_IREG(tt
)));
13468 resSC1
= newTemp(Ity_I1
);
13469 // FIXME: assumes little-endian guest
13470 stmt( IRStmt_LLSC(Iend_LE
, resSC1
, ea
, mkexpr(data
)) );
13472 /* Set rDD to 1 on failure, 0 on success. Currently we have
13473 resSC1 == 0 on failure, 1 on success. */
13474 resSC32
= newTemp(Ity_I32
);
13476 unop(Iop_1Uto32
, unop(Iop_Not1
, mkexpr(resSC1
))));
13477 vassert(dd
<= 14); /* no writes to the PC */
13479 putIRegT(dd
, mkexpr(resSC32
), IRTemp_INVALID
);
13481 putIRegA(dd
, mkexpr(resSC32
), IRTemp_INVALID
, Ijk_Boring
);
13483 if (ty
== Ity_I64
) {
13484 DIP("strex%s%s r%u, r%u, r%u, [r%u]\n",
13485 nm
, isT
? "" : nCC(conq
), dd
, tt
, tt2
, nn
);
13487 DIP("strex%s%s r%u, r%u, [r%u]\n",
13488 nm
, isT
? "" : nCC(conq
), dd
, tt
, nn
);
13490 } /* if (isLoad) */
13493 /* else fall through */
13496 /* ----------- VSEL<c>.F64 d_d_d, VSEL<c>.F32 s_s_s ----------- */
13497 /* 31 27 22 21 19 15 11 8 7 6 5 4 3
13498 T1/A1: 1111 11100 D cc n d 101 1 N 0 M 0 m VSEL<c>.F64 Dd, Dn, Dm
13499 T1/A1: 1111 11100 D cc n d 101 0 N 0 M 0 m VSEL<c>.F32 Sd, Sn, Sm
13501 ARM encoding is in NV space.
13502 In Thumb mode, we must not be in an IT block.
13504 if (INSN(31,23) == BITS9(1,1,1,1,1,1,1,0,0) && INSN(11,9) == BITS3(1,0,1)
13505 && INSN(6,6) == 0 && INSN(4,4) == 0) {
13506 UInt bit_D
= INSN(22,22);
13507 UInt fld_cc
= INSN(21,20);
13508 UInt fld_n
= INSN(19,16);
13509 UInt fld_d
= INSN(15,12);
13510 Bool isF64
= INSN(8,8) == 1;
13511 UInt bit_N
= INSN(7,7);
13512 UInt bit_M
= INSN(5,5);
13513 UInt fld_m
= INSN(3,0);
13515 UInt dd
= isF64
? ((bit_D
<< 4) | fld_d
) : ((fld_d
<< 1) | bit_D
);
13516 UInt nn
= isF64
? ((bit_N
<< 4) | fld_n
) : ((fld_n
<< 1) | bit_N
);
13517 UInt mm
= isF64
? ((bit_M
<< 4) | fld_m
) : ((fld_m
<< 1) | bit_M
);
13519 UInt cc_1
= (fld_cc
>> 1) & 1;
13520 UInt cc_0
= (fld_cc
>> 0) & 1;
13521 UInt cond
= (fld_cc
<< 2) | ((cc_1
^ cc_0
) << 1) | 0;
13524 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13526 /* In ARM mode, this is statically unconditional. In Thumb mode,
13527 this must be dynamically unconditional, and we've SIGILLd if not.
13528 In either case we can create unconditional IR. */
13530 IRTemp guard
= newTemp(Ity_I32
);
13531 assign(guard
, mk_armg_calculate_condition(cond
));
13532 IRExpr
* srcN
= (isF64
? llGetDReg
: llGetFReg
)(nn
);
13533 IRExpr
* srcM
= (isF64
? llGetDReg
: llGetFReg
)(mm
);
13534 IRExpr
* res
= IRExpr_ITE(unop(Iop_32to1
, mkexpr(guard
)), srcN
, srcM
);
13535 (isF64
? llPutDReg
: llPutFReg
)(dd
, res
);
13537 UChar rch
= isF64
? 'd' : 'f';
13538 DIP("vsel%s.%s %c%u, %c%u, %c%u\n",
13539 nCC(cond
), isF64
? "f64" : "f32", rch
, dd
, rch
, nn
, rch
, mm
);
13543 /* -------- VRINT{A,N,P,M}.F64 d_d, VRINT{A,N,P,M}.F32 s_s -------- */
13544 /* 31 22 21 17 15 11 8 7 5 4 3
13545 T1/A1: 111111101 D 1110 rm Vd 101 1 01 M 0 Vm VRINT{A,N,P,M}.F64 Dd, Dm
13546 T1/A1: 111111101 D 1110 rm Vd 101 0 01 M 0 Vm VRINT{A,N,P,M}.F32 Sd, Sm
13548 ARM encoding is in NV space.
13549 In Thumb mode, we must not be in an IT block.
13551 if (INSN(31,23) == BITS9(1,1,1,1,1,1,1,0,1)
13552 && INSN(21,18) == BITS4(1,1,1,0) && INSN(11,9) == BITS3(1,0,1)
13553 && INSN(7,6) == BITS2(0,1) && INSN(4,4) == 0) {
13554 UInt bit_D
= INSN(22,22);
13555 UInt fld_rm
= INSN(17,16);
13556 UInt fld_d
= INSN(15,12);
13557 Bool isF64
= INSN(8,8) == 1;
13558 UInt bit_M
= INSN(5,5);
13559 UInt fld_m
= INSN(3,0);
13561 UInt dd
= isF64
? ((bit_D
<< 4) | fld_d
) : ((fld_d
<< 1) | bit_D
);
13562 UInt mm
= isF64
? ((bit_M
<< 4) | fld_m
) : ((fld_m
<< 1) | bit_M
);
13565 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13567 /* In ARM mode, this is statically unconditional. In Thumb mode,
13568 this must be dynamically unconditional, and we've SIGILLd if not.
13569 In either case we can create unconditional IR. */
13572 IRRoundingMode rm
= Irrm_NEAREST
;
13574 /* The use of NEAREST for both the 'a' and 'n' cases is a bit of a
13575 kludge since it doesn't take into account the nearest-even vs
13576 nearest-away semantics. */
13577 case BITS2(0,0): c
= 'a'; rm
= Irrm_NEAREST
; break;
13578 case BITS2(0,1): c
= 'n'; rm
= Irrm_NEAREST
; break;
13579 case BITS2(1,0): c
= 'p'; rm
= Irrm_PosINF
; break;
13580 case BITS2(1,1): c
= 'm'; rm
= Irrm_NegINF
; break;
13581 default: vassert(0);
13584 IRExpr
* srcM
= (isF64
? llGetDReg
: llGetFReg
)(mm
);
13585 IRExpr
* res
= binop(isF64
? Iop_RoundF64toInt
: Iop_RoundF32toInt
,
13586 mkU32((UInt
)rm
), srcM
);
13587 (isF64
? llPutDReg
: llPutFReg
)(dd
, res
);
13589 UChar rch
= isF64
? 'd' : 'f';
13590 DIP("vrint%c.%s.%s %c%u, %c%u\n",
13591 c
, isF64
? "f64" : "f32", isF64
? "f64" : "f32", rch
, dd
, rch
, mm
);
13595 /* -------- VRINT{Z,R}.F64.F64 d_d, VRINT{Z,R}.F32.F32 s_s -------- */
13596 /* 31 27 22 21 15 11 7 6 5 4 3
13597 T1: 1110 11101 D 110110 Vd 1011 op 1 M 0 Vm VRINT<r><c>.F64.F64 Dd, Dm
13598 A1: cond 11101 D 110110 Vd 1011 op 1 M 0 Vm
13600 T1: 1110 11101 D 110110 Vd 1010 op 1 M 0 Vm VRINT<r><c>.F32.F32 Sd, Sm
13601 A1: cond 11101 D 110110 Vd 1010 op 1 M 0 Vm
13603 In contrast to the VRINT variants just above, this can be conditional.
13605 if ((isT
? (INSN(31,28) == BITS4(1,1,1,0)) : True
)
13606 && INSN(27,23) == BITS5(1,1,1,0,1) && INSN(21,16) == BITS6(1,1,0,1,1,0)
13607 && INSN(11,9) == BITS3(1,0,1) && INSN(6,6) == 1 && INSN(4,4) == 0) {
13608 UInt bit_D
= INSN(22,22);
13609 UInt fld_Vd
= INSN(15,12);
13610 Bool isF64
= INSN(8,8) == 1;
13611 Bool rToZero
= INSN(7,7) == 1;
13612 UInt bit_M
= INSN(5,5);
13613 UInt fld_Vm
= INSN(3,0);
13614 UInt dd
= isF64
? ((bit_D
<< 4) | fld_Vd
) : ((fld_Vd
<< 1) | bit_D
);
13615 UInt mm
= isF64
? ((bit_M
<< 4) | fld_Vm
) : ((fld_Vm
<< 1) | bit_M
);
13617 if (isT
) vassert(condT
!= IRTemp_INVALID
);
13618 IRType ty
= isF64
? Ity_F64
: Ity_F32
;
13619 IRTemp src
= newTemp(ty
);
13620 IRTemp res
= newTemp(ty
);
13621 assign(src
, (isF64
? getDReg
: getFReg
)(mm
));
13623 IRTemp rm
= newTemp(Ity_I32
);
13624 assign(rm
, rToZero
? mkU32(Irrm_ZERO
)
13625 : mkexpr(mk_get_IR_rounding_mode()));
13626 assign(res
, binop(isF64
? Iop_RoundF64toInt
: Iop_RoundF32toInt
,
13627 mkexpr(rm
), mkexpr(src
)));
13628 (isF64
? putDReg
: putFReg
)(dd
, mkexpr(res
), condT
);
13630 UChar rch
= isF64
? 'd' : 'f';
13631 DIP("vrint%c.%s.%s %c%u, %c%u\n",
13632 rToZero
? 'z' : 'r',
13633 isF64
? "f64" : "f32", isF64
? "f64" : "f32", rch
, dd
, rch
, mm
);
13637 /* ----------- VCVT{A,N,P,M}{.S32,.U32}{.F64,.F32} ----------- */
13638 /* 31 27 22 21 17 15 11 8 7 6 5 4 3
13639 T1/A1: 1111 11101 D 1111 rm Vd 101 sz op 1 M 0 Vm
13640 VCVT{A,N,P,M}{.S32,.U32}.F64 Sd, Dm
13641 VCVT{A,N,P,M}{.S32,.U32}.F32 Sd, Sm
13643 ARM encoding is in NV space.
13644 In Thumb mode, we must not be in an IT block.
13646 if (INSN(31,23) == BITS9(1,1,1,1,1,1,1,0,1) && INSN(21,18) == BITS4(1,1,1,1)
13647 && INSN(11,9) == BITS3(1,0,1) && INSN(6,6) == 1 && INSN(4,4) == 0) {
13648 UInt bit_D
= INSN(22,22);
13649 UInt fld_rm
= INSN(17,16);
13650 UInt fld_Vd
= INSN(15,12);
13651 Bool isF64
= INSN(8,8) == 1;
13652 Bool isU
= INSN(7,7) == 0;
13653 UInt bit_M
= INSN(5,5);
13654 UInt fld_Vm
= INSN(3,0);
13656 UInt dd
= (fld_Vd
<< 1) | bit_D
;
13657 UInt mm
= isF64
? ((bit_M
<< 4) | fld_Vm
) : ((fld_Vm
<< 1) | bit_M
);
13660 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13662 /* In ARM mode, this is statically unconditional. In Thumb mode,
13663 this must be dynamically unconditional, and we've SIGILLd if not.
13664 In either case we can create unconditional IR. */
13667 IRRoundingMode rm
= Irrm_NEAREST
;
13669 /* The use of NEAREST for both the 'a' and 'n' cases is a bit of a
13670 kludge since it doesn't take into account the nearest-even vs
13671 nearest-away semantics. */
13672 case BITS2(0,0): c
= 'a'; rm
= Irrm_NEAREST
; break;
13673 case BITS2(0,1): c
= 'n'; rm
= Irrm_NEAREST
; break;
13674 case BITS2(1,0): c
= 'p'; rm
= Irrm_PosINF
; break;
13675 case BITS2(1,1): c
= 'm'; rm
= Irrm_NegINF
; break;
13676 default: vassert(0);
13679 IRExpr
* srcM
= (isF64
? llGetDReg
: llGetFReg
)(mm
);
13680 IRTemp res
= newTemp(Ity_I32
);
13682 /* The arm back end doesn't support use of Iop_F32toI32U or
13683 Iop_F32toI32S, so for those cases we widen the F32 to F64
13684 and then follow the F64 route. */
13686 srcM
= unop(Iop_F32toF64
, srcM
);
13688 assign(res
, binop(isU
? Iop_F64toI32U
: Iop_F64toI32S
,
13689 mkU32((UInt
)rm
), srcM
));
13691 llPutFReg(dd
, unop(Iop_ReinterpI32asF32
, mkexpr(res
)));
13693 UChar rch
= isF64
? 'd' : 'f';
13694 DIP("vcvt%c.%s.%s %c%u, %c%u\n",
13695 c
, isU
? "u32" : "s32", isF64
? "f64" : "f32", 's', dd
, rch
, mm
);
13699 /* ----------- V{MAX,MIN}NM{.F64 d_d_d, .F32 s_s_s} ----------- */
13700 /* 31 27 22 21 19 15 11 8 7 6 5 4 3
13701 1111 11101 D 00 Vn Vd 101 1 N op M 0 Vm V{MIN,MAX}NM.F64 Dd, Dn, Dm
13702 1111 11101 D 00 Vn Vd 101 0 N op M 0 Vm V{MIN,MAX}NM.F32 Sd, Sn, Sm
13704 ARM encoding is in NV space.
13705 In Thumb mode, we must not be in an IT block.
13707 if (INSN(31,23) == BITS9(1,1,1,1,1,1,1,0,1) && INSN(21,20) == BITS2(0,0)
13708 && INSN(11,9) == BITS3(1,0,1) && INSN(4,4) == 0) {
13709 UInt bit_D
= INSN(22,22);
13710 UInt fld_Vn
= INSN(19,16);
13711 UInt fld_Vd
= INSN(15,12);
13712 Bool isF64
= INSN(8,8) == 1;
13713 UInt bit_N
= INSN(7,7);
13714 Bool isMAX
= INSN(6,6) == 0;
13715 UInt bit_M
= INSN(5,5);
13716 UInt fld_Vm
= INSN(3,0);
13718 UInt dd
= isF64
? ((bit_D
<< 4) | fld_Vd
) : ((fld_Vd
<< 1) | bit_D
);
13719 UInt nn
= isF64
? ((bit_N
<< 4) | fld_Vn
) : ((fld_Vn
<< 1) | bit_N
);
13720 UInt mm
= isF64
? ((bit_M
<< 4) | fld_Vm
) : ((fld_Vm
<< 1) | bit_M
);
13723 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13725 /* In ARM mode, this is statically unconditional. In Thumb mode,
13726 this must be dynamically unconditional, and we've SIGILLd if not.
13727 In either case we can create unconditional IR. */
13729 IROp op
= isF64
? (isMAX
? Iop_MaxNumF64
: Iop_MinNumF64
)
13730 : (isMAX
? Iop_MaxNumF32
: Iop_MinNumF32
);
13731 IRExpr
* srcN
= (isF64
? llGetDReg
: llGetFReg
)(nn
);
13732 IRExpr
* srcM
= (isF64
? llGetDReg
: llGetFReg
)(mm
);
13733 IRExpr
* res
= binop(op
, srcN
, srcM
);
13734 (isF64
? llPutDReg
: llPutFReg
)(dd
, res
);
13736 UChar rch
= isF64
? 'd' : 'f';
13737 DIP("v%snm.%s %c%u, %c%u, %c%u\n",
13738 isMAX
? "max" : "min", isF64
? "f64" : "f32",
13739 rch
, dd
, rch
, nn
, rch
, mm
);
13743 /* ----------- VRINTX.F64.F64 d_d, VRINTX.F32.F32 s_s ----------- */
13744 /* 31 27 22 21 15 11 8 7 5 4 3
13745 T1: 1110 11101 D 110111 Vd 101 1 01 M 0 Vm VRINTX<c>.F64.F64 Dd, Dm
13746 A1: cond 11101 D 110111 Vd 101 1 01 M 0 Vm
13748 T1: 1110 11101 D 110111 Vd 101 0 01 M 0 Vm VRINTX<c>.F32.F32 Dd, Dm
13749 A1: cond 11101 D 110111 Vd 101 0 01 M 0 Vm
13751 Like VRINT{Z,R}{.F64.F64, .F32.F32} just above, this can be conditional.
13752 This produces the same code as the VRINTR case since we ignore the
13753 requirement to signal inexactness.
13755 if ((isT
? (INSN(31,28) == BITS4(1,1,1,0)) : True
)
13756 && INSN(27,23) == BITS5(1,1,1,0,1) && INSN(21,16) == BITS6(1,1,0,1,1,1)
13757 && INSN(11,9) == BITS3(1,0,1) && INSN(7,6) == BITS2(0,1)
13758 && INSN(4,4) == 0) {
13759 UInt bit_D
= INSN(22,22);
13760 UInt fld_Vd
= INSN(15,12);
13761 Bool isF64
= INSN(8,8) == 1;
13762 UInt bit_M
= INSN(5,5);
13763 UInt fld_Vm
= INSN(3,0);
13764 UInt dd
= isF64
? ((bit_D
<< 4) | fld_Vd
) : ((fld_Vd
<< 1) | bit_D
);
13765 UInt mm
= isF64
? ((bit_M
<< 4) | fld_Vm
) : ((fld_Vm
<< 1) | bit_M
);
13767 if (isT
) vassert(condT
!= IRTemp_INVALID
);
13768 IRType ty
= isF64
? Ity_F64
: Ity_F32
;
13769 IRTemp src
= newTemp(ty
);
13770 IRTemp res
= newTemp(ty
);
13771 assign(src
, (isF64
? getDReg
: getFReg
)(mm
));
13773 IRTemp rm
= newTemp(Ity_I32
);
13774 assign(rm
, mkexpr(mk_get_IR_rounding_mode()));
13775 assign(res
, binop(isF64
? Iop_RoundF64toInt
: Iop_RoundF32toInt
,
13776 mkexpr(rm
), mkexpr(src
)));
13777 (isF64
? putDReg
: putFReg
)(dd
, mkexpr(res
), condT
);
13779 UChar rch
= isF64
? 'd' : 'f';
13780 DIP("vrint%c.%s.%s %c%u, %c%u\n",
13782 isF64
? "f64" : "f32", isF64
? "f64" : "f32", rch
, dd
, rch
, mm
);
13786 /* ----------- V{MAX,MIN}NM{.F32 d_d_d, .F32 q_q_q} ----------- */
13787 /* 31 27 22 21 20 19 15 11 7 6 5 4 3
13788 T1: 1111 11110 D op 0 Vn Vd 1111 N 1 M 1 Vm V{MIN,MAX}NM.F32 Qd,Qn,Qm
13789 A1: 1111 00110 D op 0 Vn Vd 1111 N 1 M 1 Vm
13791 T1: 1111 11110 D op 0 Vn Vd 1111 N 0 M 1 Vm V{MIN,MAX}NM.F32 Dd,Dn,Dm
13792 A1: 1111 00110 D op 0 Vn Vd 1111 N 0 M 1 Vm
13794 ARM encoding is in NV space.
13795 In Thumb mode, we must not be in an IT block.
13797 if (INSN(31,23) == (isT
? BITS9(1,1,1,1,1,1,1,1,0)
13798 : BITS9(1,1,1,1,0,0,1,1,0))
13799 && INSN(20,20) == 0 && INSN(11,8) == BITS4(1,1,1,1) && INSN(4,4) == 1) {
13800 UInt bit_D
= INSN(22,22);
13801 Bool isMax
= INSN(21,21) == 0;
13802 UInt fld_Vn
= INSN(19,16);
13803 UInt fld_Vd
= INSN(15,12);
13804 UInt bit_N
= INSN(7,7);
13805 Bool isQ
= INSN(6,6) == 1;
13806 UInt bit_M
= INSN(5,5);
13807 UInt fld_Vm
= INSN(3,0);
13809 /* dd, nn, mm are D-register numbers. */
13810 UInt dd
= (bit_D
<< 4) | fld_Vd
;
13811 UInt nn
= (bit_N
<< 4) | fld_Vn
;
13812 UInt mm
= (bit_M
<< 4) | fld_Vm
;
13814 if (! (isQ
&& ((dd
& 1) == 1 || (nn
& 1) == 1 || (mm
& 1) == 1))) {
13815 /* Do this piecewise on f regs. This is a bit tricky
13816 though because we are dealing with the full 16 x Q == 32 x D
13817 register set, so the implied F reg numbers are 0 to 63. But
13818 ll{Get,Put}FReg only allow the 0 .. 31 as those are the only
13819 architected F regs. */
13820 UInt ddF
= dd
<< 1;
13821 UInt nnF
= nn
<< 1;
13822 UInt mmF
= mm
<< 1;
13825 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13827 /* In ARM mode, this is statically unconditional. In Thumb mode,
13828 this must be dynamically unconditional, and we've SIGILLd if not.
13829 In either case we can create unconditional IR. */
13831 IROp op
= isMax
? Iop_MaxNumF32
: Iop_MinNumF32
;
13833 IRTemp r0
= newTemp(Ity_F32
);
13834 IRTemp r1
= newTemp(Ity_F32
);
13835 IRTemp r2
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
13836 IRTemp r3
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
13838 assign(r0
, binop(op
, llGetFReg_up_to_64(nnF
+0),
13839 llGetFReg_up_to_64(mmF
+0)));
13840 assign(r1
, binop(op
, llGetFReg_up_to_64(nnF
+1),
13841 llGetFReg_up_to_64(mmF
+1)));
13843 assign(r2
, binop(op
, llGetFReg_up_to_64(nnF
+2),
13844 llGetFReg_up_to_64(mmF
+2)));
13845 assign(r3
, binop(op
, llGetFReg_up_to_64(nnF
+3),
13846 llGetFReg_up_to_64(mmF
+3)));
13848 llPutFReg_up_to_64(ddF
+0, mkexpr(r0
));
13849 llPutFReg_up_to_64(ddF
+1, mkexpr(r1
));
13851 llPutFReg_up_to_64(ddF
+2, mkexpr(r2
));
13852 llPutFReg_up_to_64(ddF
+3, mkexpr(r3
));
13855 HChar rch
= isQ
? 'q' : 'd';
13856 UInt sh
= isQ
? 1 : 0;
13857 DIP("v%snm.f32 %c%u, %c%u, %c%u\n",
13858 isMax
? "max" : "min", rch
,
13859 dd
>> sh
, rch
, nn
>> sh
, rch
, mm
>> sh
);
13862 /* else fall through */
13865 /* ----------- VCVT{A,N,P,M}{.F32 d_d, .F32 q_q} ----------- */
13866 /* 31 27 22 21 15 11 9 7 6 5 4 3
13867 T1: 1111 11111 D 111011 Vd 00 rm op Q M 0 Vm
13868 A1: 1111 00111 D 111011 Vd 00 rm op Q M 0 Vm
13870 ARM encoding is in NV space.
13871 In Thumb mode, we must not be in an IT block.
13873 if (INSN(31,23) == (isT
? BITS9(1,1,1,1,1,1,1,1,1)
13874 : BITS9(1,1,1,1,0,0,1,1,1))
13875 && INSN(21,16) == BITS6(1,1,1,0,1,1) && INSN(11,10) == BITS2(0,0)
13876 && INSN(4,4) == 0) {
13877 UInt bit_D
= INSN(22,22);
13878 UInt fld_Vd
= INSN(15,12);
13879 UInt fld_rm
= INSN(9,8);
13880 Bool isU
= INSN(7,7) == 1;
13881 Bool isQ
= INSN(6,6) == 1;
13882 UInt bit_M
= INSN(5,5);
13883 UInt fld_Vm
= INSN(3,0);
13885 /* dd, nn, mm are D-register numbers. */
13886 UInt dd
= (bit_D
<< 4) | fld_Vd
;
13887 UInt mm
= (bit_M
<< 4) | fld_Vm
;
13889 if (! (isQ
&& ((dd
& 1) == 1 || (mm
& 1) == 1))) {
13890 /* Do this piecewise on f regs. */
13891 UInt ddF
= dd
<< 1;
13892 UInt mmF
= mm
<< 1;
13895 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13897 /* In ARM mode, this is statically unconditional. In Thumb mode,
13898 this must be dynamically unconditional, and we've SIGILLd if not.
13899 In either case we can create unconditional IR. */
13902 IRRoundingMode rm
= Irrm_NEAREST
;
13904 /* The use of NEAREST for both the 'a' and 'n' cases is a bit of a
13905 kludge since it doesn't take into account the nearest-even vs
13906 nearest-away semantics. */
13907 case BITS2(0,0): cvtc
= 'a'; rm
= Irrm_NEAREST
; break;
13908 case BITS2(0,1): cvtc
= 'n'; rm
= Irrm_NEAREST
; break;
13909 case BITS2(1,0): cvtc
= 'p'; rm
= Irrm_PosINF
; break;
13910 case BITS2(1,1): cvtc
= 'm'; rm
= Irrm_NegINF
; break;
13911 default: vassert(0);
13914 IROp cvt
= isU
? Iop_F64toI32U
: Iop_F64toI32S
;
13916 IRTemp r0
= newTemp(Ity_F32
);
13917 IRTemp r1
= newTemp(Ity_F32
);
13918 IRTemp r2
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
13919 IRTemp r3
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
13921 IRExpr
* rmE
= mkU32((UInt
)rm
);
13923 assign(r0
, unop(Iop_ReinterpI32asF32
,
13924 binop(cvt
, rmE
, unop(Iop_F32toF64
,
13925 llGetFReg_up_to_64(mmF
+0)))));
13926 assign(r1
, unop(Iop_ReinterpI32asF32
,
13927 binop(cvt
, rmE
, unop(Iop_F32toF64
,
13928 llGetFReg_up_to_64(mmF
+1)))));
13930 assign(r2
, unop(Iop_ReinterpI32asF32
,
13931 binop(cvt
, rmE
, unop(Iop_F32toF64
,
13932 llGetFReg_up_to_64(mmF
+2)))));
13933 assign(r3
, unop(Iop_ReinterpI32asF32
,
13934 binop(cvt
, rmE
, unop(Iop_F32toF64
,
13935 llGetFReg_up_to_64(mmF
+3)))));
13938 llPutFReg_up_to_64(ddF
+0, mkexpr(r0
));
13939 llPutFReg_up_to_64(ddF
+1, mkexpr(r1
));
13941 llPutFReg_up_to_64(ddF
+2, mkexpr(r2
));
13942 llPutFReg_up_to_64(ddF
+3, mkexpr(r3
));
13945 HChar rch
= isQ
? 'q' : 'd';
13946 UInt sh
= isQ
? 1 : 0;
13947 DIP("vcvt%c.%c32.f32 %c%u, %c%u\n",
13948 cvtc
, isU
? 'u' : 's', rch
, dd
>> sh
, rch
, mm
>> sh
);
13951 /* else fall through */
13954 /* ----------- VRINT{A,N,P,M,X,Z}{.F32 d_d, .F32 q_q} ----------- */
13955 /* 31 27 22 21 15 11 9 6 5 4 3
13956 T1: 1111 11111 D 111010 Vd 01 op Q M 0 Vm
13957 A1: 1111 00111 D 111010 Vd 01 op Q M 0 Vm
13959 ARM encoding is in NV space.
13960 In Thumb mode, we must not be in an IT block.
13962 if (INSN(31,23) == (isT
? BITS9(1,1,1,1,1,1,1,1,1)
13963 : BITS9(1,1,1,1,0,0,1,1,1))
13964 && INSN(21,16) == BITS6(1,1,1,0,1,0) && INSN(11,10) == BITS2(0,1)
13965 && INSN(4,4) == 0) {
13966 UInt bit_D
= INSN(22,22);
13967 UInt fld_Vd
= INSN(15,12);
13968 UInt fld_op
= INSN(9,7);
13969 Bool isQ
= INSN(6,6) == 1;
13970 UInt bit_M
= INSN(5,5);
13971 UInt fld_Vm
= INSN(3,0);
13973 /* dd, nn, mm are D-register numbers. */
13974 UInt dd
= (bit_D
<< 4) | fld_Vd
;
13975 UInt mm
= (bit_M
<< 4) | fld_Vm
;
13977 if (! (fld_op
== BITS3(1,0,0) || fld_op
== BITS3(1,1,0))
13978 && ! (isQ
&& ((dd
& 1) == 1 || (mm
& 1) == 1))) {
13979 /* Do this piecewise on f regs. */
13980 UInt ddF
= dd
<< 1;
13981 UInt mmF
= mm
<< 1;
13984 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13986 /* In ARM mode, this is statically unconditional. In Thumb mode,
13987 this must be dynamically unconditional, and we've SIGILLd if not.
13988 In either case we can create unconditional IR. */
13991 IRRoundingMode rm
= Irrm_NEAREST
;
13993 /* Various kludges:
13994 - The use of NEAREST for both the 'a' and 'n' cases,
13995 since it doesn't take into account the nearest-even vs
13996 nearest-away semantics.
13997 - For the 'x' case, we don't signal inexactness.
13999 case BITS3(0,1,0): cvtc
= 'a'; rm
= Irrm_NEAREST
; break;
14000 case BITS3(0,0,0): cvtc
= 'n'; rm
= Irrm_NEAREST
; break;
14001 case BITS3(1,1,1): cvtc
= 'p'; rm
= Irrm_PosINF
; break;
14002 case BITS3(1,0,1): cvtc
= 'm'; rm
= Irrm_NegINF
; break;
14003 case BITS3(0,1,1): cvtc
= 'z'; rm
= Irrm_ZERO
; break;
14004 case BITS3(0,0,1): cvtc
= 'x'; rm
= Irrm_NEAREST
; break;
14007 default: vassert(0);
14010 IRTemp r0
= newTemp(Ity_F32
);
14011 IRTemp r1
= newTemp(Ity_F32
);
14012 IRTemp r2
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
14013 IRTemp r3
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
14015 IRExpr
* rmE
= mkU32((UInt
)rm
);
14016 IROp rnd
= Iop_RoundF32toInt
;
14018 assign(r0
, binop(rnd
, rmE
, llGetFReg_up_to_64(mmF
+0)));
14019 assign(r1
, binop(rnd
, rmE
, llGetFReg_up_to_64(mmF
+1)));
14021 assign(r2
, binop(rnd
, rmE
, llGetFReg_up_to_64(mmF
+2)));
14022 assign(r3
, binop(rnd
, rmE
, llGetFReg_up_to_64(mmF
+3)));
14025 llPutFReg_up_to_64(ddF
+0, mkexpr(r0
));
14026 llPutFReg_up_to_64(ddF
+1, mkexpr(r1
));
14028 llPutFReg_up_to_64(ddF
+2, mkexpr(r2
));
14029 llPutFReg_up_to_64(ddF
+3, mkexpr(r3
));
14032 HChar rch
= isQ
? 'q' : 'd';
14033 UInt sh
= isQ
? 1 : 0;
14034 DIP("vrint%c.f32.f32 %c%u, %c%u\n",
14035 cvtc
, rch
, dd
>> sh
, rch
, mm
>> sh
);
14038 /* else fall through */
14041 /* ---------- Doesn't match anything. ---------- */
14048 /*------------------------------------------------------------*/
14049 /*--- LDMxx/STMxx helper (both ARM and Thumb32) ---*/
14050 /*------------------------------------------------------------*/
14052 /* Generate IR for LDMxx and STMxx. This is complex. Assumes it's
14053 unconditional, so the caller must produce a jump-around before
14054 calling this, if the insn is to be conditional. Caller is
14055 responsible for all validation of parameters. For LDMxx, if PC is
14056 amongst the values loaded, caller is also responsible for
14057 generating the jump. */
14058 static void mk_ldm_stm ( Bool arm
, /* True: ARM, False: Thumb */
14059 UInt rN
, /* base reg */
14060 UInt bINC
, /* 1: inc, 0: dec */
14061 UInt bBEFORE
, /* 1: inc/dec before, 0: after */
14062 UInt bW
, /* 1: writeback to Rn */
14063 UInt bL
, /* 1: load, 0: store */
14066 Int i
, r
, m
, nRegs
;
14067 IRTemp jk
= Ijk_Boring
;
14069 /* Get hold of the old Rn value. We might need to write its value
14070 to memory during a store, and if it's also the writeback
14071 register then we need to get its value now. We can't treat it
14072 exactly like the other registers we're going to transfer,
14073 because for xxMDA and xxMDB writeback forms, the generated IR
14074 updates Rn in the guest state before any transfers take place.
14075 We have to do this as per comments below, in order that if Rn is
14076 the stack pointer then it always has a value is below or equal
14077 to any of the transfer addresses. Ick. */
14078 IRTemp oldRnT
= newTemp(Ity_I32
);
14079 assign(oldRnT
, arm
? getIRegA(rN
) : getIRegT(rN
));
14081 IRTemp anchorT
= newTemp(Ity_I32
);
14082 /* The old (Addison-Wesley) ARM ARM seems to say that LDMxx/STMxx
14083 ignore the bottom two bits of the address. However, Cortex-A8
14084 doesn't seem to care. Hence: */
14085 /* No .. don't force alignment .. */
14086 /* assign(anchorT, binop(Iop_And32, mkexpr(oldRnT), mkU32(~3U))); */
14087 /* Instead, use the potentially misaligned address directly. */
14088 assign(anchorT
, mkexpr(oldRnT
));
14090 IROp opADDorSUB
= bINC
? Iop_Add32
: Iop_Sub32
;
14091 // bINC == 1: xxMIA, xxMIB
14092 // bINC == 0: xxMDA, xxMDB
14094 // For xxMDA and xxMDB, update Rn first if necessary. We have
14095 // to do this first so that, for the common idiom of the transfers
14096 // faulting because we're pushing stuff onto a stack and the stack
14097 // is growing down onto allocate-on-fault pages (as Valgrind simulates),
14098 // we need to have the SP up-to-date "covering" (pointing below) the
14099 // transfer area. For the same reason, if we are doing xxMIA or xxMIB,
14100 // do the transfer first, and then update rN afterwards.
14102 for (i
= 0; i
< 16; i
++) {
14103 if ((regList
& (1 << i
)) != 0)
14106 if (bW
== 1 && !bINC
) {
14107 IRExpr
* e
= binop(opADDorSUB
, mkexpr(oldRnT
), mkU32(4*nRegs
));
14109 putIRegA( rN
, e
, IRTemp_INVALID
, Ijk_Boring
);
14111 putIRegT( rN
, e
, IRTemp_INVALID
);
14114 // Make up a list of the registers to transfer, and their offsets
14115 // in memory relative to the anchor. If the base reg (Rn) is part
14116 // of the transfer, then do it last for a load and first for a store.
14117 UInt xReg
[16], xOff
[16];
14120 for (i
= 0; i
< 16; i
++) {
14121 r
= bINC
? i
: (15-i
);
14122 if (0 == (regList
& (1<<r
)))
14126 /* paranoia: check we aren't transferring the writeback
14127 register during a load. Should be assured by decode-point
14129 if (bW
== 1 && bL
== 1)
14139 vassert(m
== nRegs
);
14140 vassert(nX
== nRegs
);
14143 if (bW
== 0 && (regList
& (1<<rN
)) != 0) {
14144 /* Non-writeback, and basereg is to be transferred. Do its
14145 transfer last for a load and first for a store. Requires
14146 reordering xOff/xReg. */
14148 vex_printf("\nREG_LIST_PRE: (rN=%u)\n", rN
);
14149 for (i
= 0; i
< nX
; i
++)
14150 vex_printf("reg %u off %u\n", xReg
[i
], xOff
[i
]);
14155 for (i
= 0; i
< nX
; i
++) {
14159 vassert(i
< nX
); /* else we didn't find it! */
14160 UInt tReg
= xReg
[i
];
14161 UInt tOff
= xOff
[i
];
14163 /* load; make this transfer happen last */
14165 for (m
= i
+1; m
< nX
; m
++) {
14166 xReg
[m
-1] = xReg
[m
];
14167 xOff
[m
-1] = xOff
[m
];
14174 /* store; make this transfer happen first */
14176 for (m
= i
-1; m
>= 0; m
--) {
14177 xReg
[m
+1] = xReg
[m
];
14178 xOff
[m
+1] = xOff
[m
];
14187 vex_printf("REG_LIST_POST:\n");
14188 for (i
= 0; i
< nX
; i
++)
14189 vex_printf("reg %u off %u\n", xReg
[i
], xOff
[i
]);
14194 /* According to the Cortex A8 TRM Sec. 5.2.1, LDM(1) with r13 as the base
14195 register and PC in the register list is a return for purposes of branch
14197 The ARM ARM Sec. C9.10.1 further specifies that writeback must be enabled
14198 to be counted in event 0x0E (Procedure return).*/
14199 if (rN
== 13 && bL
== 1 && bINC
&& !bBEFORE
&& bW
== 1) {
14203 /* Actually generate the transfers */
14204 for (i
= 0; i
< nX
; i
++) {
14207 IRExpr
* e
= loadLE(Ity_I32
,
14208 binop(opADDorSUB
, mkexpr(anchorT
),
14211 putIRegA( r
, e
, IRTemp_INVALID
, jk
);
14213 // no: putIRegT( r, e, IRTemp_INVALID );
14214 // putIRegT refuses to write to R15. But that might happen.
14215 // Since this is uncond, and we need to be able to
14216 // write the PC, just use the low level put:
14220 /* if we're storing Rn, make sure we use the correct
14221 value, as per extensive comments above */
14222 storeLE( binop(opADDorSUB
, mkexpr(anchorT
), mkU32(xOff
[i
])),
14223 r
== rN
? mkexpr(oldRnT
)
14224 : (arm
? getIRegA(r
) : getIRegT(r
) ) );
14228 // If we are doing xxMIA or xxMIB,
14229 // do the transfer first, and then update rN afterwards.
14230 if (bW
== 1 && bINC
) {
14231 IRExpr
* e
= binop(opADDorSUB
, mkexpr(oldRnT
), mkU32(4*nRegs
));
14233 putIRegA( rN
, e
, IRTemp_INVALID
, Ijk_Boring
);
14235 putIRegT( rN
, e
, IRTemp_INVALID
);
14240 /*------------------------------------------------------------*/
14241 /*--- VFP (CP 10 and 11) instructions ---*/
14242 /*------------------------------------------------------------*/
14244 /* Both ARM and Thumb */
14246 /* Translate a CP10 or CP11 instruction. If successful, returns
14247 True and *dres may or may not be updated. If failure, returns
14248 False and doesn't change *dres nor create any IR.
14250 The ARM and Thumb encodings are identical for the low 28 bits of
14251 the insn (yay!) and that's what the caller must supply, iow, imm28
14252 has the top 4 bits masked out. Caller is responsible for
14253 determining whether the masked-out bits are valid for a CP10/11
14254 insn. The rules for the top 4 bits are:
14256 ARM: 0000 to 1110 allowed, and this is the gating condition.
14257 1111 (NV) is not allowed.
14259 Thumb: must be 1110. The gating condition is taken from
14260 ITSTATE in the normal way.
14262 Conditionalisation:
14264 Caller must supply an IRTemp 'condT' holding the gating condition,
14265 or IRTemp_INVALID indicating the insn is always executed.
14267 Caller must also supply an ARMCondcode 'cond'. This is only used
14268 for debug printing, no other purpose. For ARM, this is simply the
14269 top 4 bits of the original instruction. For Thumb, the condition
14270 is not (really) known until run time, and so ARMCondAL should be
14271 passed, only so that printing of these instructions does not show
14274 Finally, the caller must indicate whether this occurs in ARM or
14277 static Bool
decode_CP10_CP11_instruction (
14278 /*MOD*/DisResult
* dres
,
14285 # define INSN(_bMax,_bMin) SLICE_UInt(insn28, (_bMax), (_bMin))
14287 vassert(INSN(31,28) == BITS4(0,0,0,0)); // caller's obligation
14290 vassert(conq
== ARMCondAL
);
14292 vassert(conq
>= ARMCondEQ
&& conq
<= ARMCondAL
);
14295 /* ----------------------------------------------------------- */
14296 /* -- VFP instructions -- double precision (mostly) -- */
14297 /* ----------------------------------------------------------- */
14299 /* --------------------- fldmx, fstmx --------------------- */
14301 31 27 23 19 15 11 7 0
14303 C4-100, C5-26 1 FSTMX cond 1100 1000 Rn Dd 1011 offset
14304 C4-100, C5-28 2 FSTMIAX cond 1100 1010 Rn Dd 1011 offset
14305 C4-100, C5-30 3 FSTMDBX cond 1101 0010 Rn Dd 1011 offset
14307 C4-42, C5-26 1 FLDMX cond 1100 1001 Rn Dd 1011 offset
14308 C4-42, C5-28 2 FLDMIAX cond 1100 1011 Rn Dd 1011 offset
14309 C4-42, C5-30 3 FLDMDBX cond 1101 0011 Rn Dd 1011 offset
14311 Regs transferred: Dd .. D(d + (offset-3)/2)
14312 offset must be odd, must not imply a reg > 15
14313 IA/DB: Rn is changed by (4 + 8 x # regs transferred)
14316 1 at-Rn (access at Rn)
14317 2 ia-Rn (access at Rn, then Rn += 4+8n)
14318 3 db-Rn (Rn -= 4+8n, then access at Rn)
14320 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
14321 && INSN(11,8) == BITS4(1,0,1,1)) {
14322 UInt bP
= (insn28
>> 24) & 1;
14323 UInt bU
= (insn28
>> 23) & 1;
14324 UInt bW
= (insn28
>> 21) & 1;
14325 UInt bL
= (insn28
>> 20) & 1;
14326 UInt offset
= (insn28
>> 0) & 0xFF;
14327 UInt rN
= INSN(19,16);
14328 UInt dD
= (INSN(22,22) << 4) | INSN(15,12);
14329 UInt nRegs
= (offset
- 1) / 2;
14333 /**/ if (bP
== 0 && bU
== 1 && bW
== 0) {
14336 else if (bP
== 0 && bU
== 1 && bW
== 1) {
14339 else if (bP
== 1 && bU
== 0 && bW
== 1) {
14342 else goto after_vfp_fldmx_fstmx
;
14344 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */
14345 if (rN
== 15 && (summary
== 2 || summary
== 3 || isT
))
14346 goto after_vfp_fldmx_fstmx
;
14348 /* offset must be odd, and specify at least one register */
14349 if (0 == (offset
& 1) || offset
< 3)
14350 goto after_vfp_fldmx_fstmx
;
14352 /* can't transfer regs after D15 */
14353 if (dD
+ nRegs
- 1 >= 32)
14354 goto after_vfp_fldmx_fstmx
;
14356 /* Now, we can't do a conditional load or store, since that very
14357 likely will generate an exception. So we have to take a side
14358 exit at this point if the condition is false. */
14359 if (condT
!= IRTemp_INVALID
) {
14361 mk_skip_over_T32_if_cond_is_false( condT
);
14363 mk_skip_over_A32_if_cond_is_false( condT
);
14364 condT
= IRTemp_INVALID
;
14366 /* Ok, now we're unconditional. Do the load or store. */
14368 /* get the old Rn value */
14369 IRTemp rnT
= newTemp(Ity_I32
);
14370 assign(rnT
, align4if(isT
? getIRegT(rN
) : getIRegA(rN
),
14373 /* make a new value for Rn, post-insn */
14374 IRTemp rnTnew
= IRTemp_INVALID
;
14375 if (summary
== 2 || summary
== 3) {
14376 rnTnew
= newTemp(Ity_I32
);
14377 assign(rnTnew
, binop(summary
== 2 ? Iop_Add32
: Iop_Sub32
,
14379 mkU32(4 + 8 * nRegs
)));
14382 /* decide on the base transfer address */
14383 IRTemp taT
= newTemp(Ity_I32
);
14384 assign(taT
, summary
== 3 ? mkexpr(rnTnew
) : mkexpr(rnT
));
14386 /* update Rn if necessary -- in case 3, we're moving it down, so
14387 update before any memory reference, in order to keep Memcheck
14388 and V's stack-extending logic (on linux) happy */
14389 if (summary
== 3) {
14391 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
14393 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
14396 /* generate the transfers */
14397 for (i
= 0; i
< nRegs
; i
++) {
14398 IRExpr
* addr
= binop(Iop_Add32
, mkexpr(taT
), mkU32(8*i
));
14400 putDReg(dD
+ i
, loadLE(Ity_F64
, addr
), IRTemp_INVALID
);
14402 storeLE(addr
, getDReg(dD
+ i
));
14406 /* update Rn if necessary -- in case 2, we're moving it up, so
14407 update after any memory reference, in order to keep Memcheck
14408 and V's stack-extending logic (on linux) happy */
14409 if (summary
== 2) {
14411 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
14413 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
14416 const HChar
* nm
= bL
==1 ? "ld" : "st";
14418 case 1: DIP("f%smx%s r%u, {d%u-d%u}\n",
14419 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14421 case 2: DIP("f%smiax%s r%u!, {d%u-d%u}\n",
14422 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14424 case 3: DIP("f%smdbx%s r%u!, {d%u-d%u}\n",
14425 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14427 default: vassert(0);
14430 goto decode_success_vfp
;
14431 /* FIXME alignment constraints? */
14434 after_vfp_fldmx_fstmx
:
14436 /* --------------------- fldmd, fstmd --------------------- */
14438 31 27 23 19 15 11 7 0
14440 C4-96, C5-26 1 FSTMD cond 1100 1000 Rn Dd 1011 offset
14441 C4-96, C5-28 2 FSTMDIA cond 1100 1010 Rn Dd 1011 offset
14442 C4-96, C5-30 3 FSTMDDB cond 1101 0010 Rn Dd 1011 offset
14444 C4-38, C5-26 1 FLDMD cond 1100 1001 Rn Dd 1011 offset
14445 C4-38, C5-28 2 FLDMIAD cond 1100 1011 Rn Dd 1011 offset
14446 C4-38, C5-30 3 FLDMDBD cond 1101 0011 Rn Dd 1011 offset
14448 Regs transferred: Dd .. D(d + (offset-2)/2)
14449 offset must be even, must not imply a reg > 15
14450 IA/DB: Rn is changed by (8 x # regs transferred)
14453 1 at-Rn (access at Rn)
14454 2 ia-Rn (access at Rn, then Rn += 8n)
14455 3 db-Rn (Rn -= 8n, then access at Rn)
14457 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
14458 && INSN(11,8) == BITS4(1,0,1,1)) {
14459 UInt bP
= (insn28
>> 24) & 1;
14460 UInt bU
= (insn28
>> 23) & 1;
14461 UInt bW
= (insn28
>> 21) & 1;
14462 UInt bL
= (insn28
>> 20) & 1;
14463 UInt offset
= (insn28
>> 0) & 0xFF;
14464 UInt rN
= INSN(19,16);
14465 UInt dD
= (INSN(22,22) << 4) | INSN(15,12);
14466 UInt nRegs
= offset
/ 2;
14470 /**/ if (bP
== 0 && bU
== 1 && bW
== 0) {
14473 else if (bP
== 0 && bU
== 1 && bW
== 1) {
14476 else if (bP
== 1 && bU
== 0 && bW
== 1) {
14479 else goto after_vfp_fldmd_fstmd
;
14481 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */
14482 if (rN
== 15 && (summary
== 2 || summary
== 3 || isT
))
14483 goto after_vfp_fldmd_fstmd
;
14485 /* offset must be even, and specify at least one register */
14486 if (1 == (offset
& 1) || offset
< 2)
14487 goto after_vfp_fldmd_fstmd
;
14489 /* can't transfer regs after D15 */
14490 if (dD
+ nRegs
- 1 >= 32)
14491 goto after_vfp_fldmd_fstmd
;
14493 /* Now, we can't do a conditional load or store, since that very
14494 likely will generate an exception. So we have to take a side
14495 exit at this point if the condition is false. */
14496 if (condT
!= IRTemp_INVALID
) {
14498 mk_skip_over_T32_if_cond_is_false( condT
);
14500 mk_skip_over_A32_if_cond_is_false( condT
);
14501 condT
= IRTemp_INVALID
;
14503 /* Ok, now we're unconditional. Do the load or store. */
14505 /* get the old Rn value */
14506 IRTemp rnT
= newTemp(Ity_I32
);
14507 assign(rnT
, align4if(isT
? getIRegT(rN
) : getIRegA(rN
),
14510 /* make a new value for Rn, post-insn */
14511 IRTemp rnTnew
= IRTemp_INVALID
;
14512 if (summary
== 2 || summary
== 3) {
14513 rnTnew
= newTemp(Ity_I32
);
14514 assign(rnTnew
, binop(summary
== 2 ? Iop_Add32
: Iop_Sub32
,
14516 mkU32(8 * nRegs
)));
14519 /* decide on the base transfer address */
14520 IRTemp taT
= newTemp(Ity_I32
);
14521 assign(taT
, summary
== 3 ? mkexpr(rnTnew
) : mkexpr(rnT
));
14523 /* update Rn if necessary -- in case 3, we're moving it down, so
14524 update before any memory reference, in order to keep Memcheck
14525 and V's stack-extending logic (on linux) happy */
14526 if (summary
== 3) {
14528 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
14530 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
14533 /* generate the transfers */
14534 for (i
= 0; i
< nRegs
; i
++) {
14535 IRExpr
* addr
= binop(Iop_Add32
, mkexpr(taT
), mkU32(8*i
));
14537 putDReg(dD
+ i
, loadLE(Ity_F64
, addr
), IRTemp_INVALID
);
14539 storeLE(addr
, getDReg(dD
+ i
));
14543 /* update Rn if necessary -- in case 2, we're moving it up, so
14544 update after any memory reference, in order to keep Memcheck
14545 and V's stack-extending logic (on linux) happy */
14546 if (summary
== 2) {
14548 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
14550 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
14553 const HChar
* nm
= bL
==1 ? "ld" : "st";
14555 case 1: DIP("f%smd%s r%u, {d%u-d%u}\n",
14556 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14558 case 2: DIP("f%smiad%s r%u!, {d%u-d%u}\n",
14559 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14561 case 3: DIP("f%smdbd%s r%u!, {d%u-d%u}\n",
14562 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14564 default: vassert(0);
14567 goto decode_success_vfp
;
14568 /* FIXME alignment constraints? */
14571 after_vfp_fldmd_fstmd
:
14573 /* ------------------- fmrx, fmxr ------------------- */
14574 if (BITS8(1,1,1,0,1,1,1,1) == INSN(27,20)
14575 && BITS4(1,0,1,0) == INSN(11,8)
14576 && BITS8(0,0,0,1,0,0,0,0) == (insn28
& 0xFF)) {
14577 UInt rD
= INSN(15,12);
14578 UInt reg
= INSN(19,16);
14579 if (reg
== BITS4(0,0,0,1)) {
14581 IRTemp nzcvT
= newTemp(Ity_I32
);
14582 /* When rD is 15, we are copying the top 4 bits of FPSCR
14583 into CPSR. That is, set the flags thunk to COPY and
14584 install FPSCR[31:28] as the value to copy. */
14585 assign(nzcvT
, binop(Iop_And32
,
14586 IRExpr_Get(OFFB_FPSCR
, Ity_I32
),
14587 mkU32(0xF0000000)));
14588 setFlags_D1(ARMG_CC_OP_COPY
, nzcvT
, condT
);
14589 DIP("fmstat%s\n", nCC(conq
));
14591 /* Otherwise, merely transfer FPSCR to r0 .. r14. */
14592 IRExpr
* e
= IRExpr_Get(OFFB_FPSCR
, Ity_I32
);
14594 putIRegT(rD
, e
, condT
);
14596 putIRegA(rD
, e
, condT
, Ijk_Boring
);
14597 DIP("fmrx%s r%u, fpscr\n", nCC(conq
), rD
);
14599 goto decode_success_vfp
;
14604 if (BITS8(1,1,1,0,1,1,1,0) == INSN(27,20)
14605 && BITS4(1,0,1,0) == INSN(11,8)
14606 && BITS8(0,0,0,1,0,0,0,0) == (insn28
& 0xFF)) {
14607 UInt rD
= INSN(15,12);
14608 UInt reg
= INSN(19,16);
14609 if (reg
== BITS4(0,0,0,1)) {
14610 putMiscReg32(OFFB_FPSCR
,
14611 isT
? getIRegT(rD
) : getIRegA(rD
), condT
);
14612 DIP("fmxr%s fpscr, r%u\n", nCC(conq
), rD
);
14613 goto decode_success_vfp
;
14618 /* --------------------- vmov --------------------- */
14620 if (0x0C400B10 == (insn28
& 0x0FF00FD0)) {
14621 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
14622 UInt rD
= INSN(15,12); /* lo32 */
14623 UInt rN
= INSN(19,16); /* hi32 */
14624 if (rD
== 15 || rN
== 15 || (isT
&& (rD
== 13 || rN
== 13))) {
14628 unop(Iop_ReinterpI64asF64
,
14629 binop(Iop_32HLto64
,
14630 isT
? getIRegT(rN
) : getIRegA(rN
),
14631 isT
? getIRegT(rD
) : getIRegA(rD
))),
14633 DIP("vmov%s d%u, r%u, r%u\n", nCC(conq
), dM
, rD
, rN
);
14634 goto decode_success_vfp
;
14640 if (0x0C500B10 == (insn28
& 0x0FF00FD0)) {
14641 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
14642 UInt rD
= INSN(15,12); /* lo32 */
14643 UInt rN
= INSN(19,16); /* hi32 */
14644 if (rD
== 15 || rN
== 15 || (isT
&& (rD
== 13 || rN
== 13))
14648 IRTemp i64
= newTemp(Ity_I64
);
14649 assign(i64
, unop(Iop_ReinterpF64asI64
, getDReg(dM
)));
14650 IRExpr
* hi32
= unop(Iop_64HIto32
, mkexpr(i64
));
14651 IRExpr
* lo32
= unop(Iop_64to32
, mkexpr(i64
));
14653 putIRegT(rN
, hi32
, condT
);
14654 putIRegT(rD
, lo32
, condT
);
14656 putIRegA(rN
, hi32
, condT
, Ijk_Boring
);
14657 putIRegA(rD
, lo32
, condT
, Ijk_Boring
);
14659 DIP("vmov%s r%u, r%u, d%u\n", nCC(conq
), rD
, rN
, dM
);
14660 goto decode_success_vfp
;
14665 // VMOV sD, sD+1, rN, rM
14666 if (0x0C400A10 == (insn28
& 0x0FF00FD0)) {
14667 UInt sD
= (INSN(3,0) << 1) | INSN(5,5);
14668 UInt rN
= INSN(15,12);
14669 UInt rM
= INSN(19,16);
14670 if (rM
== 15 || rN
== 15 || (isT
&& (rM
== 13 || rN
== 13))
14675 unop(Iop_ReinterpI32asF32
, isT
? getIRegT(rN
) : getIRegA(rN
)),
14678 unop(Iop_ReinterpI32asF32
, isT
? getIRegT(rM
) : getIRegA(rM
)),
14680 DIP("vmov%s, s%u, s%u, r%u, r%u\n",
14681 nCC(conq
), sD
, sD
+ 1, rN
, rM
);
14682 goto decode_success_vfp
;
14686 // VMOV rN, rM, sD, sD+1
14687 if (0x0C500A10 == (insn28
& 0x0FF00FD0)) {
14688 UInt sD
= (INSN(3,0) << 1) | INSN(5,5);
14689 UInt rN
= INSN(15,12);
14690 UInt rM
= INSN(19,16);
14691 if (rM
== 15 || rN
== 15 || (isT
&& (rM
== 13 || rN
== 13))
14692 || sD
== 31 || rN
== rM
) {
14695 IRExpr
* res0
= unop(Iop_ReinterpF32asI32
, getFReg(sD
));
14696 IRExpr
* res1
= unop(Iop_ReinterpF32asI32
, getFReg(sD
+1));
14698 putIRegT(rN
, res0
, condT
);
14699 putIRegT(rM
, res1
, condT
);
14701 putIRegA(rN
, res0
, condT
, Ijk_Boring
);
14702 putIRegA(rM
, res1
, condT
, Ijk_Boring
);
14704 DIP("vmov%s, r%u, r%u, s%u, s%u\n",
14705 nCC(conq
), rN
, rM
, sD
, sD
+ 1);
14706 goto decode_success_vfp
;
14710 // VMOV rD[x], rT (ARM core register to scalar)
14711 if (0x0E000B10 == (insn28
& 0x0F900F1F)) {
14712 UInt rD
= (INSN(7,7) << 4) | INSN(19,16);
14713 UInt rT
= INSN(15,12);
14714 UInt opc
= (INSN(22,21) << 2) | INSN(6,5);
14716 if (rT
== 15 || (isT
&& rT
== 13)) {
14719 if ((opc
& BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
14721 putDRegI64(rD
, triop(Iop_SetElem8x8
,
14725 isT
? getIRegT(rT
) : getIRegA(rT
))),
14727 DIP("vmov%s.8 d%u[%u], r%u\n", nCC(conq
), rD
, index
, rT
);
14728 goto decode_success_vfp
;
14730 else if ((opc
& BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
14731 index
= (opc
>> 1) & 3;
14732 putDRegI64(rD
, triop(Iop_SetElem16x4
,
14736 isT
? getIRegT(rT
) : getIRegA(rT
))),
14738 DIP("vmov%s.16 d%u[%u], r%u\n", nCC(conq
), rD
, index
, rT
);
14739 goto decode_success_vfp
;
14741 else if ((opc
& BITS4(1,0,1,1)) == BITS4(0,0,0,0)) {
14742 index
= (opc
>> 2) & 1;
14743 putDRegI64(rD
, triop(Iop_SetElem32x2
,
14746 isT
? getIRegT(rT
) : getIRegA(rT
)),
14748 DIP("vmov%s.32 d%u[%u], r%u\n", nCC(conq
), rD
, index
, rT
);
14749 goto decode_success_vfp
;
14756 // VMOV (scalar to ARM core register)
14758 if (0x0E100B10 == (insn28
& 0x0F100F1F)) {
14759 UInt rN
= (INSN(7,7) << 4) | INSN(19,16);
14760 UInt rT
= INSN(15,12);
14761 UInt U
= INSN(23,23);
14762 UInt opc
= (INSN(22,21) << 2) | INSN(6,5);
14764 if (rT
== 15 || (isT
&& rT
== 13)) {
14767 if ((opc
& BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
14769 IRExpr
* e
= unop(U
? Iop_8Uto32
: Iop_8Sto32
,
14770 binop(Iop_GetElem8x8
,
14774 putIRegT(rT
, e
, condT
);
14776 putIRegA(rT
, e
, condT
, Ijk_Boring
);
14777 DIP("vmov%s.%c8 r%u, d%u[%u]\n", nCC(conq
), U
? 'u' : 's',
14779 goto decode_success_vfp
;
14781 else if ((opc
& BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
14782 index
= (opc
>> 1) & 3;
14783 IRExpr
* e
= unop(U
? Iop_16Uto32
: Iop_16Sto32
,
14784 binop(Iop_GetElem16x4
,
14788 putIRegT(rT
, e
, condT
);
14790 putIRegA(rT
, e
, condT
, Ijk_Boring
);
14791 DIP("vmov%s.%c16 r%u, d%u[%u]\n", nCC(conq
), U
? 'u' : 's',
14793 goto decode_success_vfp
;
14795 else if ((opc
& BITS4(1,0,1,1)) == BITS4(0,0,0,0) && U
== 0) {
14796 index
= (opc
>> 2) & 1;
14797 IRExpr
* e
= binop(Iop_GetElem32x2
, getDRegI64(rN
), mkU8(index
));
14799 putIRegT(rT
, e
, condT
);
14801 putIRegA(rT
, e
, condT
, Ijk_Boring
);
14802 DIP("vmov%s.32 r%u, d%u[%u]\n", nCC(conq
), rT
, rN
, index
);
14803 goto decode_success_vfp
;
14810 // VMOV.F32 sD, #imm
14811 // FCONSTS sD, #imm
14812 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
14813 && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,0)) {
14814 UInt rD
= (INSN(15,12) << 1) | INSN(22,22);
14815 UInt imm8
= (INSN(19,16) << 4) | INSN(3,0);
14816 UInt b
= (imm8
>> 6) & 1;
14818 imm
= (BITS8((imm8
>> 7) & 1,(~b
) & 1,b
,b
,b
,b
,b
,(imm8
>> 5) & 1) << 8)
14819 | ((imm8
& 0x1f) << 3);
14821 putFReg(rD
, unop(Iop_ReinterpI32asF32
, mkU32(imm
)), condT
);
14822 DIP("fconsts%s s%u #%u", nCC(conq
), rD
, imm8
);
14823 goto decode_success_vfp
;
14826 // VMOV.F64 dD, #imm
14827 // FCONSTD dD, #imm
14828 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
14829 && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,1)) {
14830 UInt rD
= INSN(15,12) | (INSN(22,22) << 4);
14831 UInt imm8
= (INSN(19,16) << 4) | INSN(3,0);
14832 UInt b
= (imm8
>> 6) & 1;
14834 imm
= (BITS8((imm8
>> 7) & 1,(~b
) & 1,b
,b
,b
,b
,b
,b
) << 8)
14835 | BITS8(b
,b
,0,0,0,0,0,0) | (imm8
& 0x3f);
14837 putDReg(rD
, unop(Iop_ReinterpI64asF64
, mkU64(imm
)), condT
);
14838 DIP("fconstd%s d%u #%u", nCC(conq
), rD
, imm8
);
14839 goto decode_success_vfp
;
14842 /* ---------------------- vdup ------------------------- */
14845 if (BITS8(1,1,1,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,1))
14846 && BITS4(1,0,1,1) == INSN(11,8) && INSN(6,6) == 0 && INSN(4,4) == 1) {
14847 UInt rD
= (INSN(7,7) << 4) | INSN(19,16);
14848 UInt rT
= INSN(15,12);
14849 UInt Q
= INSN(21,21);
14850 UInt size
= (INSN(22,22) << 1) | INSN(5,5);
14851 if (rT
== 15 || (isT
&& rT
== 13) || size
== 3 || (Q
&& (rD
& 1))) {
14854 IRExpr
* e
= isT
? getIRegT(rT
) : getIRegA(rT
);
14859 putQReg(rD
, unop(Iop_Dup32x4
, e
), condT
);
14862 putQReg(rD
, unop(Iop_Dup16x8
, unop(Iop_32to16
, e
)),
14866 putQReg(rD
, unop(Iop_Dup8x16
, unop(Iop_32to8
, e
)),
14872 DIP("vdup.%d q%u, r%u\n", 32 / (1<<size
), rD
, rT
);
14876 putDRegI64(rD
, unop(Iop_Dup32x2
, e
), condT
);
14879 putDRegI64(rD
, unop(Iop_Dup16x4
, unop(Iop_32to16
, e
)),
14883 putDRegI64(rD
, unop(Iop_Dup8x8
, unop(Iop_32to8
, e
)),
14889 DIP("vdup.%d d%u, r%u\n", 32 / (1<<size
), rD
, rT
);
14891 goto decode_success_vfp
;
14895 /* --------------------- f{ld,st}d --------------------- */
14897 if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
14898 && BITS4(1,0,1,1) == INSN(11,8)) {
14899 UInt dD
= INSN(15,12) | (INSN(22,22) << 4);
14900 UInt rN
= INSN(19,16);
14901 UInt offset
= (insn28
& 0xFF) << 2;
14902 UInt bU
= (insn28
>> 23) & 1; /* 1: +offset 0: -offset */
14903 UInt bL
= (insn28
>> 20) & 1; /* 1: load 0: store */
14904 /* make unconditional */
14905 if (condT
!= IRTemp_INVALID
) {
14907 mk_skip_over_T32_if_cond_is_false( condT
);
14909 mk_skip_over_A32_if_cond_is_false( condT
);
14910 condT
= IRTemp_INVALID
;
14912 IRTemp ea
= newTemp(Ity_I32
);
14913 assign(ea
, binop(bU
? Iop_Add32
: Iop_Sub32
,
14914 align4if(isT
? getIRegT(rN
) : getIRegA(rN
),
14918 putDReg(dD
, loadLE(Ity_F64
,mkexpr(ea
)), IRTemp_INVALID
);
14920 storeLE(mkexpr(ea
), getDReg(dD
));
14922 DIP("f%sd%s d%u, [r%u, %c#%u]\n",
14923 bL
? "ld" : "st", nCC(conq
), dD
, rN
,
14924 bU
? '+' : '-', offset
);
14925 goto decode_success_vfp
;
14928 /* --------------------- dp insns (D) --------------------- */
14929 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
14930 && BITS4(1,0,1,1) == INSN(11,8)
14931 && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
14932 UInt dM
= INSN(3,0) | (INSN(5,5) << 4); /* argR */
14933 UInt dD
= INSN(15,12) | (INSN(22,22) << 4); /* dst/acc */
14934 UInt dN
= INSN(19,16) | (INSN(7,7) << 4); /* argL */
14935 UInt bP
= (insn28
>> 23) & 1;
14936 UInt bQ
= (insn28
>> 21) & 1;
14937 UInt bR
= (insn28
>> 20) & 1;
14938 UInt bS
= (insn28
>> 6) & 1;
14939 UInt opc
= (bP
<< 3) | (bQ
<< 2) | (bR
<< 1) | bS
;
14940 IRExpr
* rm
= get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
14942 case BITS4(0,0,0,0): /* MAC: d + n * m */
14943 putDReg(dD
, triop(Iop_AddF64
, rm
,
14945 triop(Iop_MulF64
, rm
, getDReg(dN
),
14948 DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14949 goto decode_success_vfp
;
14950 case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
14951 putDReg(dD
, triop(Iop_AddF64
, rm
,
14954 triop(Iop_MulF64
, rm
, getDReg(dN
),
14957 DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14958 goto decode_success_vfp
;
14959 case BITS4(0,0,1,0): /* MSC: - d + n * m */
14960 putDReg(dD
, triop(Iop_AddF64
, rm
,
14961 unop(Iop_NegF64
, getDReg(dD
)),
14962 triop(Iop_MulF64
, rm
, getDReg(dN
),
14965 DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14966 goto decode_success_vfp
;
14967 case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
14968 putDReg(dD
, triop(Iop_AddF64
, rm
,
14969 unop(Iop_NegF64
, getDReg(dD
)),
14971 triop(Iop_MulF64
, rm
, getDReg(dN
),
14974 DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14975 goto decode_success_vfp
;
14976 case BITS4(0,1,0,0): /* MUL: n * m */
14977 putDReg(dD
, triop(Iop_MulF64
, rm
, getDReg(dN
), getDReg(dM
)),
14979 DIP("fmuld%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14980 goto decode_success_vfp
;
14981 case BITS4(0,1,0,1): /* NMUL: - n * m */
14982 putDReg(dD
, unop(Iop_NegF64
,
14983 triop(Iop_MulF64
, rm
, getDReg(dN
),
14986 DIP("fnmuld%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14987 goto decode_success_vfp
;
14988 case BITS4(0,1,1,0): /* ADD: n + m */
14989 putDReg(dD
, triop(Iop_AddF64
, rm
, getDReg(dN
), getDReg(dM
)),
14991 DIP("faddd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14992 goto decode_success_vfp
;
14993 case BITS4(0,1,1,1): /* SUB: n - m */
14994 putDReg(dD
, triop(Iop_SubF64
, rm
, getDReg(dN
), getDReg(dM
)),
14996 DIP("fsubd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14997 goto decode_success_vfp
;
14998 case BITS4(1,0,0,0): /* DIV: n / m */
14999 putDReg(dD
, triop(Iop_DivF64
, rm
, getDReg(dN
), getDReg(dM
)),
15001 DIP("fdivd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
15002 goto decode_success_vfp
;
15003 case BITS4(1,0,1,0): /* VNFMS: -(d - n * m) (fused) */
15004 /* XXXROUNDINGFIXME look up ARM reference for fused
15005 multiply-add rounding */
15006 putDReg(dD
, triop(Iop_AddF64
, rm
,
15007 unop(Iop_NegF64
, getDReg(dD
)),
15008 triop(Iop_MulF64
, rm
,
15012 DIP("vfnmsd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
15013 goto decode_success_vfp
;
15014 case BITS4(1,0,1,1): /* VNFMA: -(d + n * m) (fused) */
15015 /* XXXROUNDINGFIXME look up ARM reference for fused
15016 multiply-add rounding */
15017 putDReg(dD
, triop(Iop_AddF64
, rm
,
15018 unop(Iop_NegF64
, getDReg(dD
)),
15019 triop(Iop_MulF64
, rm
,
15020 unop(Iop_NegF64
, getDReg(dN
)),
15023 DIP("vfnmad%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
15024 goto decode_success_vfp
;
15025 case BITS4(1,1,0,0): /* VFMA: d + n * m (fused) */
15026 /* XXXROUNDINGFIXME look up ARM reference for fused
15027 multiply-add rounding */
15028 putDReg(dD
, triop(Iop_AddF64
, rm
,
15030 triop(Iop_MulF64
, rm
, getDReg(dN
),
15033 DIP("vfmad%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
15034 goto decode_success_vfp
;
15035 case BITS4(1,1,0,1): /* VFMS: d + (-n * m) (fused) */
15036 /* XXXROUNDINGFIXME look up ARM reference for fused
15037 multiply-add rounding */
15038 putDReg(dD
, triop(Iop_AddF64
, rm
,
15040 triop(Iop_MulF64
, rm
,
15041 unop(Iop_NegF64
, getDReg(dN
)),
15044 DIP("vfmsd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
15045 goto decode_success_vfp
;
15051 /* --------------------- compares (D) --------------------- */
15052 /* 31 27 23 19 15 11 7 3
15053 28 24 20 16 12 8 4 0
15054 FCMPD cond 1110 1D11 0100 Dd 1011 0100 Dm
15055 FCMPED cond 1110 1D11 0100 Dd 1011 1100 Dm
15056 FCMPZD cond 1110 1D11 0101 Dd 1011 0100 0000
15057 FCMPZED cond 1110 1D11 0101 Dd 1011 1100 0000
15060 Z=0 Compare Dd vs Dm and set FPSCR 31:28 accordingly
15061 Z=1 Compare Dd vs zero
15063 N=1 generates Invalid Operation exn if either arg is any kind of NaN
15064 N=0 generates Invalid Operation exn if either arg is a signalling NaN
15065 (Not that we pay any attention to N here)
15067 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15068 && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15069 && BITS4(1,0,1,1) == INSN(11,8)
15070 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15071 UInt bZ
= (insn28
>> 16) & 1;
15072 UInt bN
= (insn28
>> 7) & 1;
15073 UInt dD
= INSN(15,12) | (INSN(22,22) << 4);
15074 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
15075 if (bZ
&& INSN(3,0) != 0) {
15076 /* does not decode; fall through */
15078 IRTemp argL
= newTemp(Ity_F64
);
15079 IRTemp argR
= newTemp(Ity_F64
);
15080 IRTemp irRes
= newTemp(Ity_I32
);
15081 assign(argL
, getDReg(dD
));
15082 assign(argR
, bZ
? IRExpr_Const(IRConst_F64i(0)) : getDReg(dM
));
15083 assign(irRes
, binop(Iop_CmpF64
, mkexpr(argL
), mkexpr(argR
)));
15085 IRTemp nzcv
= IRTemp_INVALID
;
15086 IRTemp oldFPSCR
= newTemp(Ity_I32
);
15087 IRTemp newFPSCR
= newTemp(Ity_I32
);
15089 /* This is where the fun starts. We have to convert 'irRes'
15090 from an IR-convention return result (IRCmpF64Result) to an
15091 ARM-encoded (N,Z,C,V) group. The final result is in the
15092 bottom 4 bits of 'nzcv'. */
15093 /* Map compare result from IR to ARM(nzcv) */
15095 FP cmp result | IR | ARM(nzcv)
15096 --------------------------------
15102 nzcv
= mk_convert_IRCmpF64Result_to_NZCV(irRes
);
15104 /* And update FPSCR accordingly */
15105 assign(oldFPSCR
, IRExpr_Get(OFFB_FPSCR
, Ity_I32
));
15108 binop(Iop_And32
, mkexpr(oldFPSCR
), mkU32(0x0FFFFFFF)),
15109 binop(Iop_Shl32
, mkexpr(nzcv
), mkU8(28))));
15111 putMiscReg32(OFFB_FPSCR
, mkexpr(newFPSCR
), condT
);
15114 DIP("fcmpz%sd%s d%u\n", bN
? "e" : "", nCC(conq
), dD
);
15116 DIP("fcmp%sd%s d%u, d%u\n", bN
? "e" : "", nCC(conq
), dD
, dM
);
15118 goto decode_success_vfp
;
15123 /* --------------------- unary (D) --------------------- */
15124 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15125 && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15126 && BITS4(1,0,1,1) == INSN(11,8)
15127 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15128 UInt dD
= INSN(15,12) | (INSN(22,22) << 4);
15129 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
15130 UInt b16
= (insn28
>> 16) & 1;
15131 UInt b7
= (insn28
>> 7) & 1;
15132 /**/ if (b16
== 0 && b7
== 0) {
15134 putDReg(dD
, getDReg(dM
), condT
);
15135 DIP("fcpyd%s d%u, d%u\n", nCC(conq
), dD
, dM
);
15136 goto decode_success_vfp
;
15138 else if (b16
== 0 && b7
== 1) {
15140 putDReg(dD
, unop(Iop_AbsF64
, getDReg(dM
)), condT
);
15141 DIP("fabsd%s d%u, d%u\n", nCC(conq
), dD
, dM
);
15142 goto decode_success_vfp
;
15144 else if (b16
== 1 && b7
== 0) {
15146 putDReg(dD
, unop(Iop_NegF64
, getDReg(dM
)), condT
);
15147 DIP("fnegd%s d%u, d%u\n", nCC(conq
), dD
, dM
);
15148 goto decode_success_vfp
;
15150 else if (b16
== 1 && b7
== 1) {
15152 IRExpr
* rm
= get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
15153 putDReg(dD
, binop(Iop_SqrtF64
, rm
, getDReg(dM
)), condT
);
15154 DIP("fsqrtd%s d%u, d%u\n", nCC(conq
), dD
, dM
);
15155 goto decode_success_vfp
;
15163 /* ----------------- I <-> D conversions ----------------- */
15165 // F{S,U}ITOD dD, fM
15166 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15167 && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1))
15168 && BITS4(1,0,1,1) == INSN(11,8)
15169 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15170 UInt bM
= (insn28
>> 5) & 1;
15171 UInt fM
= (INSN(3,0) << 1) | bM
;
15172 UInt dD
= INSN(15,12) | (INSN(22,22) << 4);
15173 UInt syned
= (insn28
>> 7) & 1;
15176 putDReg(dD
, unop(Iop_I32StoF64
,
15177 unop(Iop_ReinterpF32asI32
, getFReg(fM
))),
15179 DIP("fsitod%s d%u, s%u\n", nCC(conq
), dD
, fM
);
15182 putDReg(dD
, unop(Iop_I32UtoF64
,
15183 unop(Iop_ReinterpF32asI32
, getFReg(fM
))),
15185 DIP("fuitod%s d%u, s%u\n", nCC(conq
), dD
, fM
);
15187 goto decode_success_vfp
;
15190 // FTO{S,U}ID fD, dM
15191 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15192 && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15193 && BITS4(1,0,1,1) == INSN(11,8)
15194 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15195 UInt bD
= (insn28
>> 22) & 1;
15196 UInt fD
= (INSN(15,12) << 1) | bD
;
15197 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
15198 UInt bZ
= (insn28
>> 7) & 1;
15199 UInt syned
= (insn28
>> 16) & 1;
15200 IRTemp rmode
= newTemp(Ity_I32
);
15201 assign(rmode
, bZ
? mkU32(Irrm_ZERO
)
15202 : mkexpr(mk_get_IR_rounding_mode()));
15205 putFReg(fD
, unop(Iop_ReinterpI32asF32
,
15206 binop(Iop_F64toI32S
, mkexpr(rmode
),
15209 DIP("ftosi%sd%s s%u, d%u\n", bZ
? "z" : "",
15210 nCC(conq
), fD
, dM
);
15213 putFReg(fD
, unop(Iop_ReinterpI32asF32
,
15214 binop(Iop_F64toI32U
, mkexpr(rmode
),
15217 DIP("ftoui%sd%s s%u, d%u\n", bZ
? "z" : "",
15218 nCC(conq
), fD
, dM
);
15220 goto decode_success_vfp
;
15223 /* ----------------------------------------------------------- */
15224 /* -- VFP instructions -- single precision -- */
15225 /* ----------------------------------------------------------- */
15227 /* --------------------- fldms, fstms --------------------- */
15229 31 27 23 19 15 11 7 0
15231 C4-98, C5-26 1 FSTMD cond 1100 1x00 Rn Fd 1010 offset
15232 C4-98, C5-28 2 FSTMDIA cond 1100 1x10 Rn Fd 1010 offset
15233 C4-98, C5-30 3 FSTMDDB cond 1101 0x10 Rn Fd 1010 offset
15235 C4-40, C5-26 1 FLDMD cond 1100 1x01 Rn Fd 1010 offset
15236 C4-40, C5-26 2 FLDMIAD cond 1100 1x11 Rn Fd 1010 offset
15237 C4-40, C5-26 3 FLDMDBD cond 1101 0x11 Rn Fd 1010 offset
15239 Regs transferred: F(Fd:D) .. F(Fd:d + offset)
15240 offset must not imply a reg > 15
15241 IA/DB: Rn is changed by (4 x # regs transferred)
15244 1 at-Rn (access at Rn)
15245 2 ia-Rn (access at Rn, then Rn += 4n)
15246 3 db-Rn (Rn -= 4n, then access at Rn)
15248 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
15249 && INSN(11,8) == BITS4(1,0,1,0)) {
15250 UInt bP
= (insn28
>> 24) & 1;
15251 UInt bU
= (insn28
>> 23) & 1;
15252 UInt bW
= (insn28
>> 21) & 1;
15253 UInt bL
= (insn28
>> 20) & 1;
15254 UInt bD
= (insn28
>> 22) & 1;
15255 UInt offset
= (insn28
>> 0) & 0xFF;
15256 UInt rN
= INSN(19,16);
15257 UInt fD
= (INSN(15,12) << 1) | bD
;
15258 UInt nRegs
= offset
;
15262 /**/ if (bP
== 0 && bU
== 1 && bW
== 0) {
15265 else if (bP
== 0 && bU
== 1 && bW
== 1) {
15268 else if (bP
== 1 && bU
== 0 && bW
== 1) {
15271 else goto after_vfp_fldms_fstms
;
15273 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */
15274 if (rN
== 15 && (summary
== 2 || summary
== 3 || isT
))
15275 goto after_vfp_fldms_fstms
;
15277 /* offset must specify at least one register */
15279 goto after_vfp_fldms_fstms
;
15281 /* can't transfer regs after S31 */
15282 if (fD
+ nRegs
- 1 >= 32)
15283 goto after_vfp_fldms_fstms
;
15285 /* Now, we can't do a conditional load or store, since that very
15286 likely will generate an exception. So we have to take a side
15287 exit at this point if the condition is false. */
15288 if (condT
!= IRTemp_INVALID
) {
15290 mk_skip_over_T32_if_cond_is_false( condT
);
15292 mk_skip_over_A32_if_cond_is_false( condT
);
15293 condT
= IRTemp_INVALID
;
15295 /* Ok, now we're unconditional. Do the load or store. */
15297 /* get the old Rn value */
15298 IRTemp rnT
= newTemp(Ity_I32
);
15299 assign(rnT
, align4if(isT
? getIRegT(rN
) : getIRegA(rN
),
15302 /* make a new value for Rn, post-insn */
15303 IRTemp rnTnew
= IRTemp_INVALID
;
15304 if (summary
== 2 || summary
== 3) {
15305 rnTnew
= newTemp(Ity_I32
);
15306 assign(rnTnew
, binop(summary
== 2 ? Iop_Add32
: Iop_Sub32
,
15308 mkU32(4 * nRegs
)));
15311 /* decide on the base transfer address */
15312 IRTemp taT
= newTemp(Ity_I32
);
15313 assign(taT
, summary
== 3 ? mkexpr(rnTnew
) : mkexpr(rnT
));
15315 /* update Rn if necessary -- in case 3, we're moving it down, so
15316 update before any memory reference, in order to keep Memcheck
15317 and V's stack-extending logic (on linux) happy */
15318 if (summary
== 3) {
15320 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
15322 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
15325 /* generate the transfers */
15326 for (i
= 0; i
< nRegs
; i
++) {
15327 IRExpr
* addr
= binop(Iop_Add32
, mkexpr(taT
), mkU32(4*i
));
15329 putFReg(fD
+ i
, loadLE(Ity_F32
, addr
), IRTemp_INVALID
);
15331 storeLE(addr
, getFReg(fD
+ i
));
15335 /* update Rn if necessary -- in case 2, we're moving it up, so
15336 update after any memory reference, in order to keep Memcheck
15337 and V's stack-extending logic (on linux) happy */
15338 if (summary
== 2) {
15340 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
15342 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
15345 const HChar
* nm
= bL
==1 ? "ld" : "st";
15347 case 1: DIP("f%sms%s r%u, {s%u-s%u}\n",
15348 nm
, nCC(conq
), rN
, fD
, fD
+ nRegs
- 1);
15350 case 2: DIP("f%smias%s r%u!, {s%u-s%u}\n",
15351 nm
, nCC(conq
), rN
, fD
, fD
+ nRegs
- 1);
15353 case 3: DIP("f%smdbs%s r%u!, {s%u-s%u}\n",
15354 nm
, nCC(conq
), rN
, fD
, fD
+ nRegs
- 1);
15356 default: vassert(0);
15359 goto decode_success_vfp
;
15360 /* FIXME alignment constraints? */
15363 after_vfp_fldms_fstms
:
15365 /* --------------------- fmsr, fmrs --------------------- */
15366 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
15367 && BITS4(1,0,1,0) == INSN(11,8)
15368 && BITS4(0,0,0,0) == INSN(3,0)
15369 && BITS4(0,0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
15370 UInt rD
= INSN(15,12);
15371 UInt b7
= (insn28
>> 7) & 1;
15372 UInt fN
= (INSN(19,16) << 1) | b7
;
15373 UInt b20
= (insn28
>> 20) & 1;
15376 /* Let's assume that no sane person would want to do
15377 floating-point transfers to or from the program counter,
15378 and simply decline to decode the instruction. The ARM ARM
15379 doesn't seem to explicitly disallow this case, though. */
15382 IRExpr
* res
= unop(Iop_ReinterpF32asI32
, getFReg(fN
));
15384 putIRegT(rD
, res
, condT
);
15386 putIRegA(rD
, res
, condT
, Ijk_Boring
);
15387 DIP("fmrs%s r%u, s%u\n", nCC(conq
), rD
, fN
);
15389 putFReg(fN
, unop(Iop_ReinterpI32asF32
,
15390 isT
? getIRegT(rD
) : getIRegA(rD
)),
15392 DIP("fmsr%s s%u, r%u\n", nCC(conq
), fN
, rD
);
15394 goto decode_success_vfp
;
15399 /* --------------------- f{ld,st}s --------------------- */
15401 if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
15402 && BITS4(1,0,1,0) == INSN(11,8)) {
15403 UInt bD
= (insn28
>> 22) & 1;
15404 UInt fD
= (INSN(15,12) << 1) | bD
;
15405 UInt rN
= INSN(19,16);
15406 UInt offset
= (insn28
& 0xFF) << 2;
15407 UInt bU
= (insn28
>> 23) & 1; /* 1: +offset 0: -offset */
15408 UInt bL
= (insn28
>> 20) & 1; /* 1: load 0: store */
15409 /* make unconditional */
15410 if (condT
!= IRTemp_INVALID
) {
15412 mk_skip_over_T32_if_cond_is_false( condT
);
15414 mk_skip_over_A32_if_cond_is_false( condT
);
15415 condT
= IRTemp_INVALID
;
15417 IRTemp ea
= newTemp(Ity_I32
);
15418 assign(ea
, binop(bU
? Iop_Add32
: Iop_Sub32
,
15419 align4if(isT
? getIRegT(rN
) : getIRegA(rN
),
15423 putFReg(fD
, loadLE(Ity_F32
,mkexpr(ea
)), IRTemp_INVALID
);
15425 storeLE(mkexpr(ea
), getFReg(fD
));
15427 DIP("f%ss%s s%u, [r%u, %c#%u]\n",
15428 bL
? "ld" : "st", nCC(conq
), fD
, rN
,
15429 bU
? '+' : '-', offset
);
15430 goto decode_success_vfp
;
15433 /* --------------------- dp insns (F) --------------------- */
15434 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
15435 && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
15436 && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
15437 UInt bM
= (insn28
>> 5) & 1;
15438 UInt bD
= (insn28
>> 22) & 1;
15439 UInt bN
= (insn28
>> 7) & 1;
15440 UInt fM
= (INSN(3,0) << 1) | bM
; /* argR */
15441 UInt fD
= (INSN(15,12) << 1) | bD
; /* dst/acc */
15442 UInt fN
= (INSN(19,16) << 1) | bN
; /* argL */
15443 UInt bP
= (insn28
>> 23) & 1;
15444 UInt bQ
= (insn28
>> 21) & 1;
15445 UInt bR
= (insn28
>> 20) & 1;
15446 UInt bS
= (insn28
>> 6) & 1;
15447 UInt opc
= (bP
<< 3) | (bQ
<< 2) | (bR
<< 1) | bS
;
15448 IRExpr
* rm
= get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
15450 case BITS4(0,0,0,0): /* MAC: d + n * m */
15451 putFReg(fD
, triop(Iop_AddF32
, rm
,
15453 triop(Iop_MulF32
, rm
, getFReg(fN
), getFReg(fM
))),
15455 DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15456 goto decode_success_vfp
;
15457 case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
15458 putFReg(fD
, triop(Iop_AddF32
, rm
,
15461 triop(Iop_MulF32
, rm
, getFReg(fN
),
15464 DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15465 goto decode_success_vfp
;
15466 case BITS4(0,0,1,0): /* MSC: - d + n * m */
15467 putFReg(fD
, triop(Iop_AddF32
, rm
,
15468 unop(Iop_NegF32
, getFReg(fD
)),
15469 triop(Iop_MulF32
, rm
, getFReg(fN
), getFReg(fM
))),
15471 DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15472 goto decode_success_vfp
;
15473 case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
15474 putFReg(fD
, triop(Iop_AddF32
, rm
,
15475 unop(Iop_NegF32
, getFReg(fD
)),
15477 triop(Iop_MulF32
, rm
,
15481 DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15482 goto decode_success_vfp
;
15483 case BITS4(0,1,0,0): /* MUL: n * m */
15484 putFReg(fD
, triop(Iop_MulF32
, rm
, getFReg(fN
), getFReg(fM
)),
15486 DIP("fmuls%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15487 goto decode_success_vfp
;
15488 case BITS4(0,1,0,1): /* NMUL: - n * m */
15489 putFReg(fD
, unop(Iop_NegF32
,
15490 triop(Iop_MulF32
, rm
, getFReg(fN
),
15493 DIP("fnmuls%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15494 goto decode_success_vfp
;
15495 case BITS4(0,1,1,0): /* ADD: n + m */
15496 putFReg(fD
, triop(Iop_AddF32
, rm
, getFReg(fN
), getFReg(fM
)),
15498 DIP("fadds%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15499 goto decode_success_vfp
;
15500 case BITS4(0,1,1,1): /* SUB: n - m */
15501 putFReg(fD
, triop(Iop_SubF32
, rm
, getFReg(fN
), getFReg(fM
)),
15503 DIP("fsubs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15504 goto decode_success_vfp
;
15505 case BITS4(1,0,0,0): /* DIV: n / m */
15506 putFReg(fD
, triop(Iop_DivF32
, rm
, getFReg(fN
), getFReg(fM
)),
15508 DIP("fdivs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15509 goto decode_success_vfp
;
15510 case BITS4(1,0,1,0): /* VNFMS: -(d - n * m) (fused) */
15511 /* XXXROUNDINGFIXME look up ARM reference for fused
15512 multiply-add rounding */
15513 putFReg(fD
, triop(Iop_AddF32
, rm
,
15514 unop(Iop_NegF32
, getFReg(fD
)),
15515 triop(Iop_MulF32
, rm
,
15519 DIP("vfnmss%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15520 goto decode_success_vfp
;
15521 case BITS4(1,0,1,1): /* VNFMA: -(d + n * m) (fused) */
15522 /* XXXROUNDINGFIXME look up ARM reference for fused
15523 multiply-add rounding */
15524 putFReg(fD
, triop(Iop_AddF32
, rm
,
15525 unop(Iop_NegF32
, getFReg(fD
)),
15526 triop(Iop_MulF32
, rm
,
15527 unop(Iop_NegF32
, getFReg(fN
)),
15530 DIP("vfnmas%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15531 goto decode_success_vfp
;
15532 case BITS4(1,1,0,0): /* VFMA: d + n * m (fused) */
15533 /* XXXROUNDINGFIXME look up ARM reference for fused
15534 multiply-add rounding */
15535 putFReg(fD
, triop(Iop_AddF32
, rm
,
15537 triop(Iop_MulF32
, rm
, getFReg(fN
),
15540 DIP("vfmas%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15541 goto decode_success_vfp
;
15542 case BITS4(1,1,0,1): /* VFMS: d + (-n * m) (fused) */
15543 /* XXXROUNDINGFIXME look up ARM reference for fused
15544 multiply-add rounding */
15545 putFReg(fD
, triop(Iop_AddF32
, rm
,
15547 triop(Iop_MulF32
, rm
,
15548 unop(Iop_NegF32
, getFReg(fN
)),
15551 DIP("vfmss%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15552 goto decode_success_vfp
;
15558 /* --------------------- compares (S) --------------------- */
15559 /* 31 27 23 19 15 11 7 3
15560 28 24 20 16 12 8 4 0
15561 FCMPS cond 1110 1D11 0100 Fd 1010 01M0 Fm
15562 FCMPES cond 1110 1D11 0100 Fd 1010 11M0 Fm
15563 FCMPZS cond 1110 1D11 0101 Fd 1010 0100 0000
15564 FCMPZED cond 1110 1D11 0101 Fd 1010 1100 0000
15567 Z=0 Compare Fd:D vs Fm:M and set FPSCR 31:28 accordingly
15568 Z=1 Compare Fd:D vs zero
15570 N=1 generates Invalid Operation exn if either arg is any kind of NaN
15571 N=0 generates Invalid Operation exn if either arg is a signalling NaN
15572 (Not that we pay any attention to N here)
15574 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15575 && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15576 && BITS4(1,0,1,0) == INSN(11,8)
15577 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15578 UInt bZ
= (insn28
>> 16) & 1;
15579 UInt bN
= (insn28
>> 7) & 1;
15580 UInt bD
= (insn28
>> 22) & 1;
15581 UInt bM
= (insn28
>> 5) & 1;
15582 UInt fD
= (INSN(15,12) << 1) | bD
;
15583 UInt fM
= (INSN(3,0) << 1) | bM
;
15584 if (bZ
&& (INSN(3,0) != 0 || (INSN(7,4) & 3) != 0)) {
15585 /* does not decode; fall through */
15587 IRTemp argL
= newTemp(Ity_F64
);
15588 IRTemp argR
= newTemp(Ity_F64
);
15589 IRTemp irRes
= newTemp(Ity_I32
);
15591 assign(argL
, unop(Iop_F32toF64
, getFReg(fD
)));
15592 assign(argR
, bZ
? IRExpr_Const(IRConst_F64i(0))
15593 : unop(Iop_F32toF64
, getFReg(fM
)));
15594 assign(irRes
, binop(Iop_CmpF64
, mkexpr(argL
), mkexpr(argR
)));
15596 IRTemp nzcv
= IRTemp_INVALID
;
15597 IRTemp oldFPSCR
= newTemp(Ity_I32
);
15598 IRTemp newFPSCR
= newTemp(Ity_I32
);
15600 /* This is where the fun starts. We have to convert 'irRes'
15601 from an IR-convention return result (IRCmpF64Result) to an
15602 ARM-encoded (N,Z,C,V) group. The final result is in the
15603 bottom 4 bits of 'nzcv'. */
15604 /* Map compare result from IR to ARM(nzcv) */
15606 FP cmp result | IR | ARM(nzcv)
15607 --------------------------------
15613 nzcv
= mk_convert_IRCmpF64Result_to_NZCV(irRes
);
15615 /* And update FPSCR accordingly */
15616 assign(oldFPSCR
, IRExpr_Get(OFFB_FPSCR
, Ity_I32
));
15619 binop(Iop_And32
, mkexpr(oldFPSCR
), mkU32(0x0FFFFFFF)),
15620 binop(Iop_Shl32
, mkexpr(nzcv
), mkU8(28))));
15622 putMiscReg32(OFFB_FPSCR
, mkexpr(newFPSCR
), condT
);
15625 DIP("fcmpz%ss%s s%u\n", bN
? "e" : "", nCC(conq
), fD
);
15627 DIP("fcmp%ss%s s%u, s%u\n", bN
? "e" : "",
15628 nCC(conq
), fD
, fM
);
15630 goto decode_success_vfp
;
15635 /* --------------------- unary (S) --------------------- */
15636 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15637 && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15638 && BITS4(1,0,1,0) == INSN(11,8)
15639 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15640 UInt bD
= (insn28
>> 22) & 1;
15641 UInt bM
= (insn28
>> 5) & 1;
15642 UInt fD
= (INSN(15,12) << 1) | bD
;
15643 UInt fM
= (INSN(3,0) << 1) | bM
;
15644 UInt b16
= (insn28
>> 16) & 1;
15645 UInt b7
= (insn28
>> 7) & 1;
15646 /**/ if (b16
== 0 && b7
== 0) {
15648 putFReg(fD
, getFReg(fM
), condT
);
15649 DIP("fcpys%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15650 goto decode_success_vfp
;
15652 else if (b16
== 0 && b7
== 1) {
15654 putFReg(fD
, unop(Iop_AbsF32
, getFReg(fM
)), condT
);
15655 DIP("fabss%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15656 goto decode_success_vfp
;
15658 else if (b16
== 1 && b7
== 0) {
15660 putFReg(fD
, unop(Iop_NegF32
, getFReg(fM
)), condT
);
15661 DIP("fnegs%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15662 goto decode_success_vfp
;
15664 else if (b16
== 1 && b7
== 1) {
15666 IRExpr
* rm
= get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
15667 putFReg(fD
, binop(Iop_SqrtF32
, rm
, getFReg(fM
)), condT
);
15668 DIP("fsqrts%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15669 goto decode_success_vfp
;
15677 /* ----------------- I <-> S conversions ----------------- */
15679 // F{S,U}ITOS fD, fM
15680 /* These are more complex than FSITOD/FUITOD. In the D cases, a 32
15681 bit int will always fit within the 53 bit mantissa, so there's
15682 no possibility of a loss of precision, but that's obviously not
15683 the case here. Hence this case possibly requires rounding, and
15684 so it drags in the current rounding mode. */
15685 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15686 && BITS4(1,0,0,0) == INSN(19,16)
15687 && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
15688 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15689 UInt bM
= (insn28
>> 5) & 1;
15690 UInt bD
= (insn28
>> 22) & 1;
15691 UInt fM
= (INSN(3,0) << 1) | bM
;
15692 UInt fD
= (INSN(15,12) << 1) | bD
;
15693 UInt syned
= (insn28
>> 7) & 1;
15694 IRTemp rmode
= newTemp(Ity_I32
);
15695 assign(rmode
, mkexpr(mk_get_IR_rounding_mode()));
15698 putFReg(fD
, binop(Iop_F64toF32
,
15700 unop(Iop_I32StoF64
,
15701 unop(Iop_ReinterpF32asI32
, getFReg(fM
)))),
15703 DIP("fsitos%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15706 putFReg(fD
, binop(Iop_F64toF32
,
15708 unop(Iop_I32UtoF64
,
15709 unop(Iop_ReinterpF32asI32
, getFReg(fM
)))),
15711 DIP("fuitos%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15713 goto decode_success_vfp
;
15716 // FTO{S,U}IS fD, fM
15717 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15718 && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15719 && BITS4(1,0,1,0) == INSN(11,8)
15720 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15721 UInt bM
= (insn28
>> 5) & 1;
15722 UInt bD
= (insn28
>> 22) & 1;
15723 UInt fD
= (INSN(15,12) << 1) | bD
;
15724 UInt fM
= (INSN(3,0) << 1) | bM
;
15725 UInt bZ
= (insn28
>> 7) & 1;
15726 UInt syned
= (insn28
>> 16) & 1;
15727 IRTemp rmode
= newTemp(Ity_I32
);
15728 assign(rmode
, bZ
? mkU32(Irrm_ZERO
)
15729 : mkexpr(mk_get_IR_rounding_mode()));
15732 putFReg(fD
, unop(Iop_ReinterpI32asF32
,
15733 binop(Iop_F64toI32S
, mkexpr(rmode
),
15734 unop(Iop_F32toF64
, getFReg(fM
)))),
15736 DIP("ftosi%ss%s s%u, d%u\n", bZ
? "z" : "",
15737 nCC(conq
), fD
, fM
);
15738 goto decode_success_vfp
;
15741 putFReg(fD
, unop(Iop_ReinterpI32asF32
,
15742 binop(Iop_F64toI32U
, mkexpr(rmode
),
15743 unop(Iop_F32toF64
, getFReg(fM
)))),
15745 DIP("ftoui%ss%s s%u, d%u\n", bZ
? "z" : "",
15746 nCC(conq
), fD
, fM
);
15747 goto decode_success_vfp
;
15751 /* ----------------- S <-> D conversions ----------------- */
15754 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15755 && BITS4(0,1,1,1) == INSN(19,16)
15756 && BITS4(1,0,1,0) == INSN(11,8)
15757 && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
15758 UInt dD
= INSN(15,12) | (INSN(22,22) << 4);
15759 UInt bM
= (insn28
>> 5) & 1;
15760 UInt fM
= (INSN(3,0) << 1) | bM
;
15761 putDReg(dD
, unop(Iop_F32toF64
, getFReg(fM
)), condT
);
15762 DIP("fcvtds%s d%u, s%u\n", nCC(conq
), dD
, fM
);
15763 goto decode_success_vfp
;
15767 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15768 && BITS4(0,1,1,1) == INSN(19,16)
15769 && BITS4(1,0,1,1) == INSN(11,8)
15770 && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
15771 UInt bD
= (insn28
>> 22) & 1;
15772 UInt fD
= (INSN(15,12) << 1) | bD
;
15773 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
15774 IRTemp rmode
= newTemp(Ity_I32
);
15775 assign(rmode
, mkexpr(mk_get_IR_rounding_mode()));
15776 putFReg(fD
, binop(Iop_F64toF32
, mkexpr(rmode
), getDReg(dM
)),
15778 DIP("fcvtsd%s s%u, d%u\n", nCC(conq
), fD
, dM
);
15779 goto decode_success_vfp
;
15782 /* --------------- VCVT fixed<->floating, VFP --------------- */
15783 /* 31 27 23 19 15 11 7 3
15784 28 24 20 16 12 8 4 0
15786 cond 1110 1D11 1p1U Vd 101f x1i0 imm4
15788 VCVT<c>.<Td>.F64 <Dd>, <Dd>, #fbits
15789 VCVT<c>.<Td>.F32 <Dd>, <Dd>, #fbits
15790 VCVT<c>.F64.<Td> <Dd>, <Dd>, #fbits
15791 VCVT<c>.F32.<Td> <Dd>, <Dd>, #fbits
15792 are of this form. We only handle a subset of the cases though.
15794 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15795 && BITS4(1,0,1,0) == (INSN(19,16) & BITS4(1,0,1,0))
15796 && BITS3(1,0,1) == INSN(11,9)
15797 && BITS3(1,0,0) == (INSN(6,4) & BITS3(1,0,1))) {
15798 UInt bD
= INSN(22,22);
15799 UInt bOP
= INSN(18,18);
15800 UInt bU
= INSN(16,16);
15801 UInt Vd
= INSN(15,12);
15802 UInt bSF
= INSN(8,8);
15803 UInt bSX
= INSN(7,7);
15804 UInt bI
= INSN(5,5);
15805 UInt imm4
= INSN(3,0);
15806 Bool to_fixed
= bOP
== 1;
15807 Bool dp_op
= bSF
== 1;
15808 Bool unsyned
= bU
== 1;
15809 UInt size
= bSX
== 0 ? 16 : 32;
15810 Int frac_bits
= size
- ((imm4
<< 1) | bI
);
15811 UInt d
= dp_op
? ((bD
<< 4) | Vd
) : ((Vd
<< 1) | bD
);
15813 IRExpr
* rm
= mkU32(Irrm_NEAREST
);
15814 IRTemp scale
= newTemp(Ity_F64
);
15815 assign(scale
, unop(Iop_I32UtoF64
, mkU32( ((UInt
)1) << (frac_bits
-1) )));
15817 if (frac_bits
>= 1 && frac_bits
<= 32 && !to_fixed
&& !dp_op
15819 /* VCVT.F32.{S,U}32 S[d], S[d], #frac_bits */
15820 /* This generates really horrible code. We could potentially
15822 IRTemp rmode
= newTemp(Ity_I32
);
15823 assign(rmode
, mkU32(Irrm_NEAREST
)); // per the spec
15824 IRTemp src32
= newTemp(Ity_I32
);
15825 assign(src32
, unop(Iop_ReinterpF32asI32
, getFReg(d
)));
15826 IRExpr
* as_F64
= unop( unsyned
? Iop_I32UtoF64
: Iop_I32StoF64
,
15828 IRExpr
* resF64
= triop(Iop_DivF64
,
15830 triop(Iop_AddF64
, rm
, mkexpr(scale
),
15832 IRExpr
* resF32
= binop(Iop_F64toF32
, mkexpr(rmode
), resF64
);
15833 putFReg(d
, resF32
, condT
);
15834 DIP("vcvt.f32.%c32, s%u, s%u, #%d\n",
15835 unsyned
? 'u' : 's', d
, d
, frac_bits
);
15836 goto decode_success_vfp
;
15838 if (frac_bits
>= 1 && frac_bits
<= 32 && !to_fixed
&& dp_op
15840 /* VCVT.F64.{S,U}32 D[d], D[d], #frac_bits */
15841 /* This generates really horrible code. We could potentially
15843 IRTemp src32
= newTemp(Ity_I32
);
15844 assign(src32
, unop(Iop_64to32
, getDRegI64(d
)));
15845 IRExpr
* as_F64
= unop( unsyned
? Iop_I32UtoF64
: Iop_I32StoF64
,
15847 IRExpr
* resF64
= triop(Iop_DivF64
,
15849 triop(Iop_AddF64
, rm
, mkexpr(scale
),
15851 putDReg(d
, resF64
, condT
);
15852 DIP("vcvt.f64.%c32, d%u, d%u, #%d\n",
15853 unsyned
? 'u' : 's', d
, d
, frac_bits
);
15854 goto decode_success_vfp
;
15856 if (frac_bits
>= 1 && frac_bits
<= 32 && to_fixed
&& dp_op
15858 /* VCVT.{S,U}32.F64 D[d], D[d], #frac_bits */
15859 IRTemp srcF64
= newTemp(Ity_F64
);
15860 assign(srcF64
, getDReg(d
));
15861 IRTemp scaledF64
= newTemp(Ity_F64
);
15862 assign(scaledF64
, triop(Iop_MulF64
,
15863 rm
, mkexpr(srcF64
),
15864 triop(Iop_AddF64
, rm
, mkexpr(scale
),
15866 IRTemp rmode
= newTemp(Ity_I32
);
15867 assign(rmode
, mkU32(Irrm_ZERO
)); // as per the spec
15868 IRTemp asI32
= newTemp(Ity_I32
);
15869 assign(asI32
, binop(unsyned
? Iop_F64toI32U
: Iop_F64toI32S
,
15870 mkexpr(rmode
), mkexpr(scaledF64
)));
15871 putDRegI64(d
, unop(unsyned
? Iop_32Uto64
: Iop_32Sto64
,
15872 mkexpr(asI32
)), condT
);
15874 DIP("vcvt.%c32.f64, d%u, d%u, #%d\n",
15875 unsyned
? 'u' : 's', d
, d
, frac_bits
);
15876 goto decode_success_vfp
;
15878 if (frac_bits
>= 1 && frac_bits
<= 32 && to_fixed
&& !dp_op
15880 /* VCVT.{S,U}32.F32 S[d], S[d], #frac_bits */
15881 IRTemp srcF32
= newTemp(Ity_F32
);
15882 assign(srcF32
, getFReg(d
));
15883 IRTemp scaledF64
= newTemp(Ity_F64
);
15884 assign(scaledF64
, triop(Iop_MulF64
,
15885 rm
, unop(Iop_F32toF64
, mkexpr(srcF32
)),
15886 triop(Iop_AddF64
, rm
, mkexpr(scale
),
15888 IRTemp rmode
= newTemp(Ity_I32
);
15889 assign(rmode
, mkU32(Irrm_ZERO
)); // as per the spec
15890 IRTemp asI32
= newTemp(Ity_I32
);
15891 assign(asI32
, binop(unsyned
? Iop_F64toI32U
: Iop_F64toI32S
,
15892 mkexpr(rmode
), mkexpr(scaledF64
)));
15893 putFReg(d
, unop(Iop_ReinterpI32asF32
, mkexpr(asI32
)), condT
);
15894 DIP("vcvt.%c32.f32, d%u, d%u, #%d\n",
15895 unsyned
? 'u' : 's', d
, d
, frac_bits
);
15896 goto decode_success_vfp
;
15904 decode_success_vfp
:
15905 /* Check that any accepted insn really is a CP10 or CP11 insn, iow,
15906 assert that we aren't accepting, in this fn, insns that actually
15907 should be handled somewhere else. */
15908 vassert(INSN(11,9) == BITS3(1,0,1)); // 11:8 = 1010 or 1011
15915 /*------------------------------------------------------------*/
15916 /*--- Instructions in NV (never) space ---*/
15917 /*------------------------------------------------------------*/
15920 /* Translate a NV space instruction. If successful, returns True and
15921 *dres may or may not be updated. If failure, returns False and
15922 doesn't change *dres nor create any IR.
15924 Note that all NEON instructions (in ARM mode) up to and including
15925 ARMv7, but not later, are handled through here, since they are all
15928 static Bool decode_NV_instruction_ARMv7_and_below
15929 ( /*MOD*/DisResult
* dres
,
15930 const VexArchInfo
* archinfo
,
15933 # define INSN(_bMax,_bMin) SLICE_UInt(insn, (_bMax), (_bMin))
15934 # define INSN_COND SLICE_UInt(insn, 31, 28)
15936 HChar dis_buf
[128];
15938 // Should only be called for NV instructions
15939 vassert(BITS4(1,1,1,1) == INSN_COND
);
15941 /* ------------------------ pld{w} ------------------------ */
15942 if (BITS8(0,1,0,1, 0,0, 0,1) == (INSN(27,20) & BITS8(1,1,1,1, 0,0, 1,1))
15943 && BITS4(1,1,1,1) == INSN(15,12)) {
15944 UInt rN
= INSN(19,16);
15945 UInt imm12
= INSN(11,0);
15946 UInt bU
= INSN(23,23);
15947 UInt bR
= INSN(22,22);
15948 DIP("pld%c [r%u, #%c%u]\n", bR
? ' ' : 'w', rN
, bU
? '+' : '-', imm12
);
15952 if (BITS8(0,1,1,1, 0,0, 0,1) == (INSN(27,20) & BITS8(1,1,1,1, 0,0, 1,1))
15953 && BITS4(1,1,1,1) == INSN(15,12)
15954 && 0 == INSN(4,4)) {
15955 UInt rN
= INSN(19,16);
15956 UInt rM
= INSN(3,0);
15957 UInt imm5
= INSN(11,7);
15958 UInt sh2
= INSN(6,5);
15959 UInt bU
= INSN(23,23);
15960 UInt bR
= INSN(22,22);
15961 if (rM
!= 15 && (rN
!= 15 || bR
)) {
15962 IRExpr
* eaE
= mk_EA_reg_plusminus_shifted_reg(rN
, bU
, rM
,
15963 sh2
, imm5
, dis_buf
);
15964 IRTemp eaT
= newTemp(Ity_I32
);
15965 /* Bind eaE to a temp merely for debugging-vex purposes, so we
15966 can check it's a plausible decoding. It will get removed
15967 by iropt a little later on. */
15970 DIP("pld%c %s\n", bR
? ' ' : 'w', dis_buf
);
15976 /* ------------------------ pli ------------------------ */
15977 if (BITS8(0,1,0,0, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
15978 && BITS4(1,1,1,1) == INSN(15,12)) {
15979 UInt rN
= INSN(19,16);
15980 UInt imm12
= INSN(11,0);
15981 UInt bU
= INSN(23,23);
15982 DIP("pli [r%u, #%c%u]\n", rN
, bU
? '+' : '-', imm12
);
15986 /* --------------------- Interworking branches --------------------- */
15988 // BLX (1), viz, unconditional branch and link to R15+simm24
15989 // and set CPSR.T = 1, that is, switch to Thumb mode
15990 if (INSN(31,25) == BITS7(1,1,1,1,1,0,1)) {
15991 UInt bitH
= INSN(24,24);
15992 UInt uimm24
= INSN(23,0); uimm24
<<= 8;
15993 Int simm24
= (Int
)uimm24
; simm24
>>= 8;
15994 simm24
= (((UInt
)simm24
) << 2) + (bitH
<< 1);
15995 /* Now this is a bit tricky. Since we're decoding an ARM insn,
15996 it is implies that CPSR.T == 0. Hence the current insn's
15997 address is guaranteed to be of the form X--(30)--X00. So, no
15998 need to mask any bits off it. But need to set the lowest bit
15999 to 1 to denote we're in Thumb mode after this, since
16000 guest_R15T has CPSR.T as the lowest bit. And we can't chase
16001 into the call, so end the block at this point. */
16002 UInt dst
= guest_R15_curr_instr_notENC
+ 8 + (simm24
| 1);
16003 putIRegA( 14, mkU32(guest_R15_curr_instr_notENC
+ 4),
16004 IRTemp_INVALID
/*because AL*/, Ijk_Boring
);
16005 llPutIReg(15, mkU32(dst
));
16006 dres
->jk_StopHere
= Ijk_Call
;
16007 dres
->whatNext
= Dis_StopHere
;
16008 DIP("blx 0x%x (and switch to Thumb mode)\n", dst
- 1);
16012 /* ------------------- v7 barrier insns ------------------- */
16014 case 0xF57FF06F: /* ISB */
16015 stmt( IRStmt_MBE(Imbe_Fence
) );
16018 case 0xF57FF04F: /* DSB sy */
16019 case 0xF57FF04E: /* DSB st */
16020 case 0xF57FF04B: /* DSB ish */
16021 case 0xF57FF04A: /* DSB ishst */
16022 case 0xF57FF047: /* DSB nsh */
16023 case 0xF57FF046: /* DSB nshst */
16024 case 0xF57FF043: /* DSB osh */
16025 case 0xF57FF042: /* DSB oshst */
16026 stmt( IRStmt_MBE(Imbe_Fence
) );
16029 case 0xF57FF05F: /* DMB sy */
16030 case 0xF57FF05E: /* DMB st */
16031 case 0xF57FF05B: /* DMB ish */
16032 case 0xF57FF05A: /* DMB ishst */
16033 case 0xF57FF057: /* DMB nsh */
16034 case 0xF57FF056: /* DMB nshst */
16035 case 0xF57FF053: /* DMB osh */
16036 case 0xF57FF052: /* DMB oshst */
16037 stmt( IRStmt_MBE(Imbe_Fence
) );
16044 /* ------------------- CLREX ------------------ */
16045 if (insn
== 0xF57FF01F) {
16046 /* AFAICS, this simply cancels a (all?) reservations made by a
16047 (any?) preceding LDREX(es). Arrange to hand it through to
16049 stmt( IRStmt_MBE(Imbe_CancelReservation
) );
16054 /* ------------------- NEON ------------------- */
16055 if (archinfo
->hwcaps
& VEX_HWCAPS_ARM_NEON
) {
16056 Bool ok_neon
= decode_NEON_instruction_ARMv7_and_below(
16057 dres
, insn
, IRTemp_INVALID
/*unconditional*/,
16072 /*------------------------------------------------------------*/
16073 /*--- Disassemble a single ARM instruction ---*/
16074 /*------------------------------------------------------------*/
16076 /* Disassemble a single ARM instruction into IR. The instruction is
16077 located in host memory at guest_instr, and has (decoded) guest IP
16078 of guest_R15_curr_instr_notENC, which will have been set before the
16082 DisResult
disInstr_ARM_WRK (
16083 Bool (*resteerOkFn
) ( /*opaque*/void*, Addr
),
16085 void* callback_opaque
,
16086 const UChar
* guest_instr
,
16087 const VexArchInfo
* archinfo
,
16088 const VexAbiInfo
* abiinfo
,
16092 // A macro to fish bits out of 'insn'.
16093 # define INSN(_bMax,_bMin) SLICE_UInt(insn, (_bMax), (_bMin))
16094 # define INSN_COND SLICE_UInt(insn, 31, 28)
16098 IRTemp condT
; /* :: Ity_I32 */
16100 HChar dis_buf
[128]; // big enough to hold LDMIA etc text
16102 /* Set result defaults. */
16103 dres
.whatNext
= Dis_Continue
;
16105 dres
.continueAt
= 0;
16106 dres
.jk_StopHere
= Ijk_INVALID
;
16107 dres
.hint
= Dis_HintNone
;
16109 /* Set default actions for post-insn handling of writes to r15, if
16111 r15written
= False
;
16112 r15guard
= IRTemp_INVALID
; /* unconditional */
16113 r15kind
= Ijk_Boring
;
16115 /* At least this is simple on ARM: insns are all 4 bytes long, and
16116 4-aligned. So just fish the whole thing out of memory right now
16118 insn
= getUIntLittleEndianly( guest_instr
);
16120 if (0) vex_printf("insn: 0x%x\n", insn
);
16122 DIP("\t(arm) 0x%x: ", (UInt
)guest_R15_curr_instr_notENC
);
16124 vassert(0 == (guest_R15_curr_instr_notENC
& 3));
16126 /* ----------------------------------------------------------- */
16128 /* Spot "Special" instructions (see comment at top of file). */
16130 const UChar
* code
= guest_instr
;
16131 /* Spot the 16-byte preamble:
16133 e1a0c1ec mov r12, r12, ROR #3
16134 e1a0c6ec mov r12, r12, ROR #13
16135 e1a0ceec mov r12, r12, ROR #29
16136 e1a0c9ec mov r12, r12, ROR #19
16138 UInt word1
= 0xE1A0C1EC;
16139 UInt word2
= 0xE1A0C6EC;
16140 UInt word3
= 0xE1A0CEEC;
16141 UInt word4
= 0xE1A0C9EC;
16142 if (getUIntLittleEndianly(code
+ 0) == word1
&&
16143 getUIntLittleEndianly(code
+ 4) == word2
&&
16144 getUIntLittleEndianly(code
+ 8) == word3
&&
16145 getUIntLittleEndianly(code
+12) == word4
) {
16146 /* Got a "Special" instruction preamble. Which one is it? */
16147 if (getUIntLittleEndianly(code
+16) == 0xE18AA00A
16148 /* orr r10,r10,r10 */) {
16149 /* R3 = client_request ( R4 ) */
16150 DIP("r3 = client_request ( %%r4 )\n");
16151 llPutIReg(15, mkU32( guest_R15_curr_instr_notENC
+ 20 ));
16152 dres
.jk_StopHere
= Ijk_ClientReq
;
16153 dres
.whatNext
= Dis_StopHere
;
16154 goto decode_success
;
16157 if (getUIntLittleEndianly(code
+16) == 0xE18BB00B
16158 /* orr r11,r11,r11 */) {
16159 /* R3 = guest_NRADDR */
16160 DIP("r3 = guest_NRADDR\n");
16162 llPutIReg(3, IRExpr_Get( OFFB_NRADDR
, Ity_I32
));
16163 goto decode_success
;
16166 if (getUIntLittleEndianly(code
+16) == 0xE18CC00C
16167 /* orr r12,r12,r12 */) {
16168 /* branch-and-link-to-noredir R4 */
16169 DIP("branch-and-link-to-noredir r4\n");
16170 llPutIReg(14, mkU32( guest_R15_curr_instr_notENC
+ 20) );
16171 llPutIReg(15, llGetIReg(4));
16172 dres
.jk_StopHere
= Ijk_NoRedir
;
16173 dres
.whatNext
= Dis_StopHere
;
16174 goto decode_success
;
16177 if (getUIntLittleEndianly(code
+16) == 0xE1899009
16178 /* orr r9,r9,r9 */) {
16180 DIP("IR injection\n");
16181 vex_inject_ir(irsb
, Iend_LE
);
16182 // Invalidate the current insn. The reason is that the IRop we're
16183 // injecting here can change. In which case the translation has to
16184 // be redone. For ease of handling, we simply invalidate all the
16186 stmt(IRStmt_Put(OFFB_CMSTART
, mkU32(guest_R15_curr_instr_notENC
)));
16187 stmt(IRStmt_Put(OFFB_CMLEN
, mkU32(20)));
16188 llPutIReg(15, mkU32( guest_R15_curr_instr_notENC
+ 20 ));
16189 dres
.whatNext
= Dis_StopHere
;
16190 dres
.jk_StopHere
= Ijk_InvalICache
;
16191 goto decode_success
;
16193 /* We don't know what it is. Set opc1/opc2 so decode_failure
16194 can print the insn following the Special-insn preamble. */
16195 insn
= getUIntLittleEndianly(code
+16);
16196 goto decode_failure
;
16202 /* ----------------------------------------------------------- */
16204 /* Main ARM instruction decoder starts here. */
16206 /* Deal with the condition. Strategy is to merely generate a
16207 condition temporary at this point (or IRTemp_INVALID, meaning
16208 unconditional). We leave it to lower-level instruction decoders
16209 to decide whether they can generate straight-line code, or
16210 whether they must generate a side exit before the instruction.
16211 condT :: Ity_I32 and is always either zero or one. */
16212 condT
= IRTemp_INVALID
;
16213 switch ( (ARMCondcode
)INSN_COND
) {
16215 // Illegal instruction prior to v5 (see ARM ARM A3-5), but
16216 // some cases are acceptable
16218 = decode_NV_instruction_ARMv7_and_below(&dres
, archinfo
, insn
);
16220 goto decode_success
;
16222 goto after_v7_decoder
;
16224 case ARMCondAL
: // Always executed
16226 case ARMCondEQ
: case ARMCondNE
: case ARMCondHS
: case ARMCondLO
:
16227 case ARMCondMI
: case ARMCondPL
: case ARMCondVS
: case ARMCondVC
:
16228 case ARMCondHI
: case ARMCondLS
: case ARMCondGE
: case ARMCondLT
:
16229 case ARMCondGT
: case ARMCondLE
:
16230 condT
= newTemp(Ity_I32
);
16231 assign( condT
, mk_armg_calculate_condition( INSN_COND
));
16235 /* ----------------------------------------------------------- */
16236 /* -- ARMv5 integer instructions -- */
16237 /* ----------------------------------------------------------- */
16239 /* ---------------- Data processing ops ------------------- */
16241 if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0))
16242 && !(INSN(25,25) == 0 && INSN(7,7) == 1 && INSN(4,4) == 1)) {
16243 IRTemp shop
= IRTemp_INVALID
; /* shifter operand */
16244 IRTemp shco
= IRTemp_INVALID
; /* shifter carry out */
16245 UInt rD
= (insn
>> 12) & 0xF; /* 15:12 */
16246 UInt rN
= (insn
>> 16) & 0xF; /* 19:16 */
16247 UInt bitS
= (insn
>> 20) & 1; /* 20:20 */
16248 IRTemp rNt
= IRTemp_INVALID
;
16249 IRTemp res
= IRTemp_INVALID
;
16250 IRTemp oldV
= IRTemp_INVALID
;
16251 IRTemp oldC
= IRTemp_INVALID
;
16252 const HChar
* name
= NULL
;
16253 IROp op
= Iop_INVALID
;
16256 switch (INSN(24,21)) {
16258 /* --------- ADD, SUB, AND, OR --------- */
16259 case BITS4(0,1,0,0): /* ADD: Rd = Rn + shifter_operand */
16260 name
= "add"; op
= Iop_Add32
; goto rd_eq_rn_op_SO
;
16261 case BITS4(0,0,1,0): /* SUB: Rd = Rn - shifter_operand */
16262 name
= "sub"; op
= Iop_Sub32
; goto rd_eq_rn_op_SO
;
16263 case BITS4(0,0,1,1): /* RSB: Rd = shifter_operand - Rn */
16264 name
= "rsb"; op
= Iop_Sub32
; goto rd_eq_rn_op_SO
;
16265 case BITS4(0,0,0,0): /* AND: Rd = Rn & shifter_operand */
16266 name
= "and"; op
= Iop_And32
; goto rd_eq_rn_op_SO
;
16267 case BITS4(1,1,0,0): /* OR: Rd = Rn | shifter_operand */
16268 name
= "orr"; op
= Iop_Or32
; goto rd_eq_rn_op_SO
;
16269 case BITS4(0,0,0,1): /* EOR: Rd = Rn ^ shifter_operand */
16270 name
= "eor"; op
= Iop_Xor32
; goto rd_eq_rn_op_SO
;
16271 case BITS4(1,1,1,0): /* BIC: Rd = Rn & ~shifter_operand */
16272 name
= "bic"; op
= Iop_And32
; goto rd_eq_rn_op_SO
;
16274 Bool isRSB
= False
;
16275 Bool isBIC
= False
;
16276 switch (INSN(24,21)) {
16277 case BITS4(0,0,1,1):
16278 vassert(op
== Iop_Sub32
); isRSB
= True
; break;
16279 case BITS4(1,1,1,0):
16280 vassert(op
== Iop_And32
); isBIC
= True
; break;
16284 rNt
= newTemp(Ity_I32
);
16285 assign(rNt
, getIRegA(rN
));
16286 ok
= mk_shifter_operand(
16287 INSN(25,25), INSN(11,0),
16288 &shop
, bitS
? &shco
: NULL
, dis_buf
16292 res
= newTemp(Ity_I32
);
16293 // compute the main result
16295 // reverse-subtract: shifter_operand - Rn
16296 vassert(op
== Iop_Sub32
);
16297 assign(res
, binop(op
, mkexpr(shop
), mkexpr(rNt
)) );
16298 } else if (isBIC
) {
16299 // andn: shifter_operand & ~Rn
16300 vassert(op
== Iop_And32
);
16301 assign(res
, binop(op
, mkexpr(rNt
),
16302 unop(Iop_Not32
, mkexpr(shop
))) );
16304 // normal: Rn op shifter_operand
16305 assign(res
, binop(op
, mkexpr(rNt
), mkexpr(shop
)) );
16307 // but don't commit it until after we've finished
16308 // all necessary reads from the guest state
16310 && (op
== Iop_And32
|| op
== Iop_Or32
|| op
== Iop_Xor32
)) {
16311 oldV
= newTemp(Ity_I32
);
16312 assign( oldV
, mk_armg_calculate_flag_v() );
16314 // can't safely read guest state after here
16315 // now safe to put the main result
16316 putIRegA( rD
, mkexpr(res
), condT
, Ijk_Boring
);
16317 // XXXX!! not safe to read any guest state after
16318 // this point (I think the code below doesn't do that).
16320 vassert(shco
== IRTemp_INVALID
);
16321 /* Update the flags thunk if necessary */
16323 vassert(shco
!= IRTemp_INVALID
);
16326 setFlags_D1_D2( ARMG_CC_OP_ADD
, rNt
, shop
, condT
);
16330 setFlags_D1_D2( ARMG_CC_OP_SUB
, shop
, rNt
, condT
);
16332 setFlags_D1_D2( ARMG_CC_OP_SUB
, rNt
, shop
, condT
);
16335 case Iop_And32
: /* BIC and AND set the flags the same */
16338 // oldV has been read just above
16339 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
,
16340 res
, shco
, oldV
, condT
);
16346 DIP("%s%s%s r%u, r%u, %s\n",
16347 name
, nCC(INSN_COND
), bitS
? "s" : "", rD
, rN
, dis_buf
);
16348 goto decode_success
;
16351 /* --------- MOV, MVN --------- */
16352 case BITS4(1,1,0,1): /* MOV: Rd = shifter_operand */
16353 case BITS4(1,1,1,1): { /* MVN: Rd = not(shifter_operand) */
16354 Bool isMVN
= INSN(24,21) == BITS4(1,1,1,1);
16355 IRTemp jk
= Ijk_Boring
;
16357 break; /* rN must be zero */
16358 ok
= mk_shifter_operand(
16359 INSN(25,25), INSN(11,0),
16360 &shop
, bitS
? &shco
: NULL
, dis_buf
16364 res
= newTemp(Ity_I32
);
16365 assign( res
, isMVN
? unop(Iop_Not32
, mkexpr(shop
))
16368 vassert(shco
!= IRTemp_INVALID
);
16369 oldV
= newTemp(Ity_I32
);
16370 assign( oldV
, mk_armg_calculate_flag_v() );
16372 vassert(shco
== IRTemp_INVALID
);
16374 /* According to the Cortex A8 TRM Sec. 5.2.1, MOV PC, r14 is a
16375 return for purposes of branch prediction. */
16376 if (!isMVN
&& INSN(11,0) == 14) {
16379 // can't safely read guest state after here
16380 putIRegA( rD
, mkexpr(res
), condT
, jk
);
16381 /* Update the flags thunk if necessary */
16383 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
,
16384 res
, shco
, oldV
, condT
);
16386 DIP("%s%s%s r%u, %s\n",
16387 isMVN
? "mvn" : "mov",
16388 nCC(INSN_COND
), bitS
? "s" : "", rD
, dis_buf
);
16389 goto decode_success
;
16392 /* --------- CMP --------- */
16393 case BITS4(1,0,1,0): /* CMP: (void) Rn - shifter_operand */
16394 case BITS4(1,0,1,1): { /* CMN: (void) Rn + shifter_operand */
16395 Bool isCMN
= INSN(24,21) == BITS4(1,0,1,1);
16397 break; /* rD must be zero */
16399 break; /* if S (bit 20) is not set, it's not CMP/CMN */
16400 rNt
= newTemp(Ity_I32
);
16401 assign(rNt
, getIRegA(rN
));
16402 ok
= mk_shifter_operand(
16403 INSN(25,25), INSN(11,0),
16404 &shop
, NULL
, dis_buf
16408 // can't safely read guest state after here
16409 /* Update the flags thunk. */
16410 setFlags_D1_D2( isCMN
? ARMG_CC_OP_ADD
: ARMG_CC_OP_SUB
,
16411 rNt
, shop
, condT
);
16412 DIP("%s%s r%u, %s\n",
16413 isCMN
? "cmn" : "cmp",
16414 nCC(INSN_COND
), rN
, dis_buf
);
16415 goto decode_success
;
16418 /* --------- TST --------- */
16419 case BITS4(1,0,0,0): /* TST: (void) Rn & shifter_operand */
16420 case BITS4(1,0,0,1): { /* TEQ: (void) Rn ^ shifter_operand */
16421 Bool isTEQ
= INSN(24,21) == BITS4(1,0,0,1);
16423 break; /* rD must be zero */
16425 break; /* if S (bit 20) is not set, it's not TST/TEQ */
16426 rNt
= newTemp(Ity_I32
);
16427 assign(rNt
, getIRegA(rN
));
16428 ok
= mk_shifter_operand(
16429 INSN(25,25), INSN(11,0),
16430 &shop
, &shco
, dis_buf
16434 /* Update the flags thunk. */
16435 res
= newTemp(Ity_I32
);
16436 assign( res
, binop(isTEQ
? Iop_Xor32
: Iop_And32
,
16437 mkexpr(rNt
), mkexpr(shop
)) );
16438 oldV
= newTemp(Ity_I32
);
16439 assign( oldV
, mk_armg_calculate_flag_v() );
16440 // can't safely read guest state after here
16441 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
,
16442 res
, shco
, oldV
, condT
);
16443 DIP("%s%s r%u, %s\n",
16444 isTEQ
? "teq" : "tst",
16445 nCC(INSN_COND
), rN
, dis_buf
);
16446 goto decode_success
;
16449 /* --------- ADC, SBC, RSC --------- */
16450 case BITS4(0,1,0,1): /* ADC: Rd = Rn + shifter_operand + oldC */
16451 name
= "adc"; goto rd_eq_rn_op_SO_op_oldC
;
16452 case BITS4(0,1,1,0): /* SBC: Rd = Rn - shifter_operand - (oldC ^ 1) */
16453 name
= "sbc"; goto rd_eq_rn_op_SO_op_oldC
;
16454 case BITS4(0,1,1,1): /* RSC: Rd = shifter_operand - Rn - (oldC ^ 1) */
16455 name
= "rsc"; goto rd_eq_rn_op_SO_op_oldC
;
16456 rd_eq_rn_op_SO_op_oldC
: {
16457 // FIXME: shco isn't used for anything. Get rid of it.
16458 rNt
= newTemp(Ity_I32
);
16459 assign(rNt
, getIRegA(rN
));
16460 ok
= mk_shifter_operand(
16461 INSN(25,25), INSN(11,0),
16462 &shop
, bitS
? &shco
: NULL
, dis_buf
16466 oldC
= newTemp(Ity_I32
);
16467 assign( oldC
, mk_armg_calculate_flag_c() );
16468 res
= newTemp(Ity_I32
);
16469 // compute the main result
16470 switch (INSN(24,21)) {
16471 case BITS4(0,1,0,1): /* ADC */
16474 binop(Iop_Add32
, mkexpr(rNt
), mkexpr(shop
)),
16477 case BITS4(0,1,1,0): /* SBC */
16480 binop(Iop_Sub32
, mkexpr(rNt
), mkexpr(shop
)),
16481 binop(Iop_Xor32
, mkexpr(oldC
), mkU32(1)) ));
16483 case BITS4(0,1,1,1): /* RSC */
16486 binop(Iop_Sub32
, mkexpr(shop
), mkexpr(rNt
)),
16487 binop(Iop_Xor32
, mkexpr(oldC
), mkU32(1)) ));
16492 // but don't commit it until after we've finished
16493 // all necessary reads from the guest state
16494 // now safe to put the main result
16495 putIRegA( rD
, mkexpr(res
), condT
, Ijk_Boring
);
16496 // XXXX!! not safe to read any guest state after
16497 // this point (I think the code below doesn't do that).
16499 vassert(shco
== IRTemp_INVALID
);
16500 /* Update the flags thunk if necessary */
16502 vassert(shco
!= IRTemp_INVALID
);
16503 switch (INSN(24,21)) {
16504 case BITS4(0,1,0,1): /* ADC */
16505 setFlags_D1_D2_ND( ARMG_CC_OP_ADC
,
16506 rNt
, shop
, oldC
, condT
);
16508 case BITS4(0,1,1,0): /* SBC */
16509 setFlags_D1_D2_ND( ARMG_CC_OP_SBB
,
16510 rNt
, shop
, oldC
, condT
);
16512 case BITS4(0,1,1,1): /* RSC */
16513 setFlags_D1_D2_ND( ARMG_CC_OP_SBB
,
16514 shop
, rNt
, oldC
, condT
);
16520 DIP("%s%s%s r%u, r%u, %s\n",
16521 name
, nCC(INSN_COND
), bitS
? "s" : "", rD
, rN
, dis_buf
);
16522 goto decode_success
;
16528 } /* if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) */
16530 /* --------------------- Load/store (ubyte & word) -------- */
16531 // LDR STR LDRB STRB
16532 /* 31 27 23 19 15 11 6 4 3 # highest bit
16534 A5-20 1 | 16 cond 0101 UB0L Rn Rd imm12
16535 A5-22 1 | 32 cond 0111 UBOL Rn Rd imm5 sh2 0 Rm
16536 A5-24 2 | 16 cond 0101 UB1L Rn Rd imm12
16537 A5-26 2 | 32 cond 0111 UB1L Rn Rd imm5 sh2 0 Rm
16538 A5-28 3 | 16 cond 0100 UB0L Rn Rd imm12
16539 A5-32 3 | 32 cond 0110 UB0L Rn Rd imm5 sh2 0 Rm
16542 1 at-ea (access at ea)
16543 2 at-ea-then-upd (access at ea, then Rn = ea)
16544 3 at-Rn-then-upd (access at Rn, then Rn = ea)
16547 32 Rn +/- Rm sh2 imm5
16549 /* Quickly skip over all of this for hopefully most instructions */
16550 if ((INSN(27,24) & BITS4(1,1,0,0)) != BITS4(0,1,0,0))
16551 goto after_load_store_ubyte_or_word
;
16555 /**/ if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 0) {
16558 else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 0
16559 && INSN(4,4) == 0) {
16562 else if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 1) {
16565 else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 1
16566 && INSN(4,4) == 0) {
16569 else if (INSN(27,24) == BITS4(0,1,0,0) && INSN(21,21) == 0) {
16572 else if (INSN(27,24) == BITS4(0,1,1,0) && INSN(21,21) == 0
16573 && INSN(4,4) == 0) {
16576 else goto after_load_store_ubyte_or_word
;
16578 { UInt rN
= (insn
>> 16) & 0xF; /* 19:16 */
16579 UInt rD
= (insn
>> 12) & 0xF; /* 15:12 */
16580 UInt rM
= (insn
>> 0) & 0xF; /* 3:0 */
16581 UInt bU
= (insn
>> 23) & 1; /* 23 */
16582 UInt bB
= (insn
>> 22) & 1; /* 22 */
16583 UInt bL
= (insn
>> 20) & 1; /* 20 */
16584 UInt imm12
= (insn
>> 0) & 0xFFF; /* 11:0 */
16585 UInt imm5
= (insn
>> 7) & 0x1F; /* 11:7 */
16586 UInt sh2
= (insn
>> 5) & 3; /* 6:5 */
16588 /* Skip some invalid cases, which would lead to two competing
16589 updates to the same register, or which are otherwise
16590 disallowed by the spec. */
16595 if (rM
== 15) goto after_load_store_ubyte_or_word
;
16597 case 2 | 16: case 3 | 16:
16598 if (rN
== 15) goto after_load_store_ubyte_or_word
;
16599 if (bL
== 1 && rN
== rD
) goto after_load_store_ubyte_or_word
;
16601 case 2 | 32: case 3 | 32:
16602 if (rM
== 15) goto after_load_store_ubyte_or_word
;
16603 if (rN
== 15) goto after_load_store_ubyte_or_word
;
16604 if (rN
== rM
) goto after_load_store_ubyte_or_word
;
16605 if (bL
== 1 && rN
== rD
) goto after_load_store_ubyte_or_word
;
16611 /* compute the effective address. Bind it to a tmp since we
16612 may need to use it twice. */
16613 IRExpr
* eaE
= NULL
;
16614 switch (summary
& 0xF0) {
16616 eaE
= mk_EA_reg_plusminus_imm12( rN
, bU
, imm12
, dis_buf
);
16619 eaE
= mk_EA_reg_plusminus_shifted_reg( rN
, bU
, rM
, sh2
, imm5
,
16624 IRTemp eaT
= newTemp(Ity_I32
);
16627 /* get the old Rn value */
16628 IRTemp rnT
= newTemp(Ity_I32
);
16629 assign(rnT
, getIRegA(rN
));
16631 /* decide on the transfer address */
16632 IRTemp taT
= IRTemp_INVALID
;
16633 switch (summary
& 0x0F) {
16634 case 1: case 2: taT
= eaT
; break;
16635 case 3: taT
= rnT
; break;
16637 vassert(taT
!= IRTemp_INVALID
);
16640 /* Store. If necessary, update the base register before the
16641 store itself, so that the common idiom of "str rX, [sp,
16642 #-4]!" (store rX at sp-4, then do new sp = sp-4, a.k.a "push
16643 rX") doesn't cause Memcheck to complain that the access is
16644 below the stack pointer. Also, not updating sp before the
16645 store confuses Valgrind's dynamic stack-extending logic. So
16646 do it before the store. Hence we need to snarf the store
16647 data before doing the basereg update. */
16649 /* get hold of the data to be stored */
16650 IRTemp rDt
= newTemp(Ity_I32
);
16651 assign(rDt
, getIRegA(rD
));
16653 /* Update Rn if necessary. */
16654 switch (summary
& 0x0F) {
16656 putIRegA( rN
, mkexpr(eaT
), condT
, Ijk_Boring
);
16660 /* generate the transfer */
16661 if (bB
== 0) { // word store
16662 storeGuardedLE( mkexpr(taT
), mkexpr(rDt
), condT
);
16663 } else { // byte store
16665 storeGuardedLE( mkexpr(taT
), unop(Iop_32to8
, mkexpr(rDt
)), condT
);
16672 /* generate the transfer */
16673 if (bB
== 0) { // word load
16674 IRTemp jk
= Ijk_Boring
;
16675 /* According to the Cortex A8 TRM Sec. 5.2.1, LDR(1) with r13 as the
16676 base register and PC as the destination register is a return for
16677 purposes of branch prediction.
16678 The ARM ARM Sec. C9.10.1 further specifies that it must use a
16679 post-increment by immediate addressing mode to be counted in
16680 event 0x0E (Procedure return).*/
16681 if (rN
== 13 && summary
== (3 | 16) && bB
== 0) {
16684 IRTemp tD
= newTemp(Ity_I32
);
16685 loadGuardedLE( tD
, ILGop_Ident32
,
16686 mkexpr(taT
), llGetIReg(rD
), condT
);
16687 /* "rD == 15 ? condT : IRTemp_INVALID": simply
16688 IRTemp_INVALID would be correct in all cases here, and
16689 for the non-r15 case it generates better code, by
16690 avoiding two tests of the cond (since it is already
16691 tested by loadGuardedLE). However, the logic at the end
16692 of this function, that deals with writes to r15, has an
16693 optimisation which depends on seeing whether or not the
16694 write is conditional. Hence in this particular case we
16695 let it "see" the guard condition. */
16696 putIRegA( rD
, mkexpr(tD
),
16697 rD
== 15 ? condT
: IRTemp_INVALID
, jk
);
16698 } else { // byte load
16700 IRTemp tD
= newTemp(Ity_I32
);
16701 loadGuardedLE( tD
, ILGop_8Uto32
, mkexpr(taT
), llGetIReg(rD
), condT
);
16702 /* No point in similar 3rd arg complexity here, since we
16703 can't sanely write anything to r15 like this. */
16704 putIRegA( rD
, mkexpr(tD
), IRTemp_INVALID
, Ijk_Boring
);
16707 /* Update Rn if necessary. */
16708 switch (summary
& 0x0F) {
16710 // should be assured by logic above:
16712 vassert(rD
!= rN
); /* since we just wrote rD */
16713 putIRegA( rN
, mkexpr(eaT
), condT
, Ijk_Boring
);
16718 switch (summary
& 0x0F) {
16719 case 1: DIP("%sr%s%s r%u, %s\n",
16720 bL
== 0 ? "st" : "ld",
16721 bB
== 0 ? "" : "b", nCC(INSN_COND
), rD
, dis_buf
);
16723 case 2: DIP("%sr%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
16724 bL
== 0 ? "st" : "ld",
16725 bB
== 0 ? "" : "b", nCC(INSN_COND
), rD
, dis_buf
);
16727 case 3: DIP("%sr%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
16728 bL
== 0 ? "st" : "ld",
16729 bB
== 0 ? "" : "b", nCC(INSN_COND
), rD
, dis_buf
);
16731 default: vassert(0);
16734 /* XXX deal with alignment constraints */
16736 goto decode_success
;
16740 For all loads: if the Amode specifies base register
16741 writeback, and the same register is specified for Rd and Rn,
16742 the results are UNPREDICTABLE.
16744 For all loads and stores: if R15 is written, branch to
16745 that address afterwards.
16747 STRB: straightforward
16748 LDRB: loaded data is zero extended
16749 STR: lowest 2 bits of address are ignored
16750 LDR: if the lowest 2 bits of the address are nonzero
16751 then the loaded value is rotated right by 8 * the lowest 2 bits
16755 after_load_store_ubyte_or_word
:
16757 /* --------------------- Load/store (sbyte & hword) -------- */
16758 // LDRH LDRSH STRH LDRSB
16759 /* 31 27 23 19 15 11 7 3 # highest bit
16760 28 24 20 16 12 8 4 0
16761 A5-36 1 | 16 cond 0001 U10L Rn Rd im4h 1SH1 im4l
16762 A5-38 1 | 32 cond 0001 U00L Rn Rd 0000 1SH1 Rm
16763 A5-40 2 | 16 cond 0001 U11L Rn Rd im4h 1SH1 im4l
16764 A5-42 2 | 32 cond 0001 U01L Rn Rd 0000 1SH1 Rm
16765 A5-44 3 | 16 cond 0000 U10L Rn Rd im4h 1SH1 im4l
16766 A5-46 3 | 32 cond 0000 U00L Rn Rd 0000 1SH1 Rm
16769 1 at-ea (access at ea)
16770 2 at-ea-then-upd (access at ea, then Rn = ea)
16771 3 at-Rn-then-upd (access at Rn, then Rn = ea)
16776 /* Quickly skip over all of this for hopefully most instructions */
16777 if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
16778 goto after_load_store_sbyte_or_hword
;
16780 /* Check the "1SH1" thing. */
16781 if ((INSN(7,4) & BITS4(1,0,0,1)) != BITS4(1,0,0,1))
16782 goto after_load_store_sbyte_or_hword
;
16786 /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,0)) {
16789 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,0)) {
16792 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,1)) {
16795 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,1)) {
16798 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(1,0)) {
16801 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(0,0)) {
16804 else goto after_load_store_sbyte_or_hword
;
16806 { UInt rN
= (insn
>> 16) & 0xF; /* 19:16 */
16807 UInt rD
= (insn
>> 12) & 0xF; /* 15:12 */
16808 UInt rM
= (insn
>> 0) & 0xF; /* 3:0 */
16809 UInt bU
= (insn
>> 23) & 1; /* 23 U=1 offset+, U=0 offset- */
16810 UInt bL
= (insn
>> 20) & 1; /* 20 L=1 load, L=0 store */
16811 UInt bH
= (insn
>> 5) & 1; /* H=1 halfword, H=0 byte */
16812 UInt bS
= (insn
>> 6) & 1; /* S=1 signed, S=0 unsigned */
16813 UInt imm8
= ((insn
>> 4) & 0xF0) | (insn
& 0xF); /* 11:8, 3:0 */
16815 /* Skip combinations that are either meaningless or already
16816 handled by main word-or-unsigned-byte load-store
16818 if (bS
== 0 && bH
== 0) /* "unsigned byte" */
16819 goto after_load_store_sbyte_or_hword
;
16820 if (bS
== 1 && bL
== 0) /* "signed store" */
16821 goto after_load_store_sbyte_or_hword
;
16823 /* Require 11:8 == 0 for Rn +/- Rm cases */
16824 if ((summary
& 32) != 0 && (imm8
& 0xF0) != 0)
16825 goto after_load_store_sbyte_or_hword
;
16827 /* Skip some invalid cases, which would lead to two competing
16828 updates to the same register, or which are otherwise
16829 disallowed by the spec. */
16834 if (rM
== 15) goto after_load_store_sbyte_or_hword
;
16836 case 2 | 16: case 3 | 16:
16837 if (rN
== 15) goto after_load_store_sbyte_or_hword
;
16838 if (bL
== 1 && rN
== rD
) goto after_load_store_sbyte_or_hword
;
16840 case 2 | 32: case 3 | 32:
16841 if (rM
== 15) goto after_load_store_sbyte_or_hword
;
16842 if (rN
== 15) goto after_load_store_sbyte_or_hword
;
16843 if (rN
== rM
) goto after_load_store_sbyte_or_hword
;
16844 if (bL
== 1 && rN
== rD
) goto after_load_store_sbyte_or_hword
;
16850 /* If this is a branch, make it unconditional at this point.
16851 Doing conditional branches in-line is too complex (for now).
16852 Note that you'd have to be insane to use any of these loads to
16853 do a branch, since they only load 16 bits at most, but we
16854 handle it just in case. */
16855 if (bL
== 1 && rD
== 15 && condT
!= IRTemp_INVALID
) {
16857 mk_skip_over_A32_if_cond_is_false( condT
);
16858 condT
= IRTemp_INVALID
;
16862 /* compute the effective address. Bind it to a tmp since we
16863 may need to use it twice. */
16864 IRExpr
* eaE
= NULL
;
16865 switch (summary
& 0xF0) {
16867 eaE
= mk_EA_reg_plusminus_imm8( rN
, bU
, imm8
, dis_buf
);
16870 eaE
= mk_EA_reg_plusminus_reg( rN
, bU
, rM
, dis_buf
);
16874 IRTemp eaT
= newTemp(Ity_I32
);
16877 /* get the old Rn value */
16878 IRTemp rnT
= newTemp(Ity_I32
);
16879 assign(rnT
, getIRegA(rN
));
16881 /* decide on the transfer address */
16882 IRTemp taT
= IRTemp_INVALID
;
16883 switch (summary
& 0x0F) {
16884 case 1: case 2: taT
= eaT
; break;
16885 case 3: taT
= rnT
; break;
16887 vassert(taT
!= IRTemp_INVALID
);
16889 /* ll previous value of rD, for dealing with conditional loads */
16890 IRTemp llOldRd
= newTemp(Ity_I32
);
16891 assign(llOldRd
, llGetIReg(rD
));
16893 /* halfword store H 1 L 0 S 0
16894 uhalf load H 1 L 1 S 0
16895 shalf load H 1 L 1 S 1
16896 sbyte load H 0 L 1 S 1
16898 const HChar
* name
= NULL
;
16899 /* generate the transfer */
16900 /**/ if (bH
== 1 && bL
== 0 && bS
== 0) { // halfword store
16901 storeGuardedLE( mkexpr(taT
),
16902 unop(Iop_32to16
, getIRegA(rD
)), condT
);
16905 else if (bH
== 1 && bL
== 1 && bS
== 0) { // uhalf load
16906 IRTemp newRd
= newTemp(Ity_I32
);
16907 loadGuardedLE( newRd
, ILGop_16Uto32
,
16908 mkexpr(taT
), mkexpr(llOldRd
), condT
);
16909 putIRegA( rD
, mkexpr(newRd
), IRTemp_INVALID
, Ijk_Boring
);
16912 else if (bH
== 1 && bL
== 1 && bS
== 1) { // shalf load
16913 IRTemp newRd
= newTemp(Ity_I32
);
16914 loadGuardedLE( newRd
, ILGop_16Sto32
,
16915 mkexpr(taT
), mkexpr(llOldRd
), condT
);
16916 putIRegA( rD
, mkexpr(newRd
), IRTemp_INVALID
, Ijk_Boring
);
16919 else if (bH
== 0 && bL
== 1 && bS
== 1) { // sbyte load
16920 IRTemp newRd
= newTemp(Ity_I32
);
16921 loadGuardedLE( newRd
, ILGop_8Sto32
,
16922 mkexpr(taT
), mkexpr(llOldRd
), condT
);
16923 putIRegA( rD
, mkexpr(newRd
), IRTemp_INVALID
, Ijk_Boring
);
16927 vassert(0); // should be assured by logic above
16929 /* Update Rn if necessary. */
16930 switch (summary
& 0x0F) {
16932 // should be assured by logic above:
16934 vassert(rD
!= rN
); /* since we just wrote rD */
16935 putIRegA( rN
, mkexpr(eaT
), condT
, Ijk_Boring
);
16939 switch (summary
& 0x0F) {
16940 case 1: DIP("%s%s r%u, %s\n", name
, nCC(INSN_COND
), rD
, dis_buf
);
16942 case 2: DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
16943 name
, nCC(INSN_COND
), rD
, dis_buf
);
16945 case 3: DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
16946 name
, nCC(INSN_COND
), rD
, dis_buf
);
16948 default: vassert(0);
16951 /* XXX deal with alignment constraints */
16953 goto decode_success
;
16957 For all loads: if the Amode specifies base register
16958 writeback, and the same register is specified for Rd and Rn,
16959 the results are UNPREDICTABLE.
16961 For all loads and stores: if R15 is written, branch to
16962 that address afterwards.
16964 Misaligned halfword stores => Unpredictable
16965 Misaligned halfword loads => Unpredictable
16969 after_load_store_sbyte_or_hword
:
16971 /* --------------------- Load/store multiple -------------- */
16972 // LD/STMIA LD/STMIB LD/STMDA LD/STMDB
16973 // Remarkably complex and difficult to get right
16974 // match 27:20 as 100XX0WL
16975 if (BITS8(1,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,1,0,0))) {
16976 // A5-50 LD/STMIA cond 1000 10WL Rn RegList
16977 // A5-51 LD/STMIB cond 1001 10WL Rn RegList
16978 // A5-53 LD/STMDA cond 1000 00WL Rn RegList
16979 // A5-53 LD/STMDB cond 1001 00WL Rn RegList
16982 UInt bINC
= (insn
>> 23) & 1;
16983 UInt bBEFORE
= (insn
>> 24) & 1;
16985 UInt bL
= (insn
>> 20) & 1; /* load=1, store=0 */
16986 UInt bW
= (insn
>> 21) & 1; /* Rn wback=1, no wback=0 */
16987 UInt rN
= (insn
>> 16) & 0xF;
16988 UInt regList
= insn
& 0xFFFF;
16989 /* Skip some invalid cases, which would lead to two competing
16990 updates to the same register, or which are otherwise
16991 disallowed by the spec. Note the test above has required
16992 that S == 0, since that looks like a kernel-mode only thing.
16993 Done by forcing the real pattern, viz 100XXSWL to actually be
16995 if (rN
== 15) goto after_load_store_multiple
;
16996 // reglist can't be empty
16997 if (regList
== 0) goto after_load_store_multiple
;
16998 // if requested to writeback Rn, and this is a load instruction,
16999 // then Rn can't appear in RegList, since we'd have two competing
17000 // new values for Rn. We do however accept this case for store
17002 if (bW
== 1 && bL
== 1 && ((1 << rN
) & regList
) > 0)
17003 goto after_load_store_multiple
;
17005 /* Now, we can't do a conditional load or store, since that very
17006 likely will generate an exception. So we have to take a side
17007 exit at this point if the condition is false. */
17008 if (condT
!= IRTemp_INVALID
) {
17009 mk_skip_over_A32_if_cond_is_false( condT
);
17010 condT
= IRTemp_INVALID
;
17013 /* Ok, now we're unconditional. Generate the IR. */
17014 mk_ldm_stm( True
/*arm*/, rN
, bINC
, bBEFORE
, bW
, bL
, regList
);
17016 DIP("%sm%c%c%s r%u%s, {0x%04x}\n",
17017 bL
== 1 ? "ld" : "st", bINC
? 'i' : 'd', bBEFORE
? 'b' : 'a',
17019 rN
, bW
? "!" : "", regList
);
17021 goto decode_success
;
17024 after_load_store_multiple
:
17026 /* --------------------- Control flow --------------------- */
17027 // B, BL (Branch, or Branch-and-Link, to immediate offset)
17029 if (BITS8(1,0,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))) {
17030 UInt link
= (insn
>> 24) & 1;
17031 UInt uimm24
= insn
& ((1<<24)-1); uimm24
<<= 8;
17032 Int simm24
= (Int
)uimm24
; simm24
>>= 8;
17033 UInt dst
= guest_R15_curr_instr_notENC
+ 8 + (((UInt
)simm24
) << 2);
17034 IRJumpKind jk
= link
? Ijk_Call
: Ijk_Boring
;
17036 putIRegA(14, mkU32(guest_R15_curr_instr_notENC
+ 4),
17037 condT
, Ijk_Boring
);
17039 if (condT
== IRTemp_INVALID
) {
17040 /* unconditional transfer to 'dst'. See if we can simply
17041 continue tracing at the destination. */
17042 if (resteerOkFn( callback_opaque
, dst
)) {
17044 dres
.whatNext
= Dis_ResteerU
;
17045 dres
.continueAt
= dst
;
17047 /* no; terminate the SB at this point. */
17048 llPutIReg(15, mkU32(dst
));
17049 dres
.jk_StopHere
= jk
;
17050 dres
.whatNext
= Dis_StopHere
;
17052 DIP("b%s 0x%x\n", link
? "l" : "", dst
);
17054 /* conditional transfer to 'dst' */
17055 const HChar
* comment
= "";
17057 /* First see if we can do some speculative chasing into one
17058 arm or the other. Be conservative and only chase if
17059 !link, that is, this is a normal conditional branch to a
17060 known destination. */
17063 && vex_control
.guest_chase_cond
17064 && dst
< guest_R15_curr_instr_notENC
17065 && resteerOkFn( callback_opaque
, dst
) ) {
17066 /* Speculation: assume this backward branch is taken. So
17067 we need to emit a side-exit to the insn following this
17068 one, on the negation of the condition, and continue at
17069 the branch target address (dst). */
17070 stmt( IRStmt_Exit( unop(Iop_Not1
,
17071 unop(Iop_32to1
, mkexpr(condT
))),
17073 IRConst_U32(guest_R15_curr_instr_notENC
+4),
17075 dres
.whatNext
= Dis_ResteerC
;
17076 dres
.continueAt
= (Addr32
)dst
;
17077 comment
= "(assumed taken)";
17082 && vex_control
.guest_chase_cond
17083 && dst
>= guest_R15_curr_instr_notENC
17084 && resteerOkFn( callback_opaque
,
17085 guest_R15_curr_instr_notENC
+4) ) {
17086 /* Speculation: assume this forward branch is not taken.
17087 So we need to emit a side-exit to dst (the dest) and
17088 continue disassembling at the insn immediately
17089 following this one. */
17090 stmt( IRStmt_Exit( unop(Iop_32to1
, mkexpr(condT
)),
17094 dres
.whatNext
= Dis_ResteerC
;
17095 dres
.continueAt
= guest_R15_curr_instr_notENC
+4;
17096 comment
= "(assumed not taken)";
17099 /* Conservative default translation - end the block at
17101 stmt( IRStmt_Exit( unop(Iop_32to1
, mkexpr(condT
)),
17102 jk
, IRConst_U32(dst
), OFFB_R15T
));
17103 llPutIReg(15, mkU32(guest_R15_curr_instr_notENC
+ 4));
17104 dres
.jk_StopHere
= Ijk_Boring
;
17105 dres
.whatNext
= Dis_StopHere
;
17107 DIP("b%s%s 0x%x %s\n", link
? "l" : "", nCC(INSN_COND
),
17110 goto decode_success
;
17113 // B, BL (Branch, or Branch-and-Link, to a register)
17114 // NB: interworking branch
17115 if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
17116 && INSN(19,12) == BITS8(1,1,1,1,1,1,1,1)
17117 && (INSN(11,4) == BITS8(1,1,1,1,0,0,1,1)
17118 || INSN(11,4) == BITS8(1,1,1,1,0,0,0,1))) {
17119 IRTemp dst
= newTemp(Ity_I32
);
17120 UInt link
= (INSN(11,4) >> 1) & 1;
17121 UInt rM
= INSN(3,0);
17122 // we don't decode the case (link && rM == 15), as that's
17124 if (!(link
&& rM
== 15)) {
17125 if (condT
!= IRTemp_INVALID
) {
17126 mk_skip_over_A32_if_cond_is_false( condT
);
17128 // rM contains an interworking address exactly as we require
17129 // (with continuation CPSR.T in bit 0), so we can use it
17130 // as-is, with no masking.
17131 assign( dst
, getIRegA(rM
) );
17133 putIRegA( 14, mkU32(guest_R15_curr_instr_notENC
+ 4),
17134 IRTemp_INVALID
/*because AL*/, Ijk_Boring
);
17136 llPutIReg(15, mkexpr(dst
));
17137 dres
.jk_StopHere
= link
? Ijk_Call
17138 : (rM
== 14 ? Ijk_Ret
: Ijk_Boring
);
17139 dres
.whatNext
= Dis_StopHere
;
17140 if (condT
== IRTemp_INVALID
) {
17141 DIP("b%sx r%u\n", link
? "l" : "", rM
);
17143 DIP("b%sx%s r%u\n", link
? "l" : "", nCC(INSN_COND
), rM
);
17145 goto decode_success
;
17147 /* else: (link && rM == 15): just fall through */
17150 /* --- NB: ARM interworking branches are in NV space, hence
17151 are handled elsewhere by decode_NV_instruction_ARMv7_and_below.
17155 /* --------------------- Clz --------------------- */
17157 if (INSN(27,20) == BITS8(0,0,0,1,0,1,1,0)
17158 && INSN(19,16) == BITS4(1,1,1,1)
17159 && INSN(11,4) == BITS8(1,1,1,1,0,0,0,1)) {
17160 UInt rD
= INSN(15,12);
17161 UInt rM
= INSN(3,0);
17162 IRTemp arg
= newTemp(Ity_I32
);
17163 IRTemp res
= newTemp(Ity_I32
);
17164 assign(arg
, getIRegA(rM
));
17165 assign(res
, IRExpr_ITE(
17166 binop(Iop_CmpEQ32
, mkexpr(arg
), mkU32(0)),
17168 unop(Iop_Clz32
, mkexpr(arg
))
17170 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
17171 DIP("clz%s r%u, r%u\n", nCC(INSN_COND
), rD
, rM
);
17172 goto decode_success
;
17175 /* --------------------- Mul etc --------------------- */
17177 if (BITS8(0,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
17178 && INSN(15,12) == BITS4(0,0,0,0)
17179 && INSN(7,4) == BITS4(1,0,0,1)) {
17180 UInt bitS
= (insn
>> 20) & 1; /* 20:20 */
17181 UInt rD
= INSN(19,16);
17182 UInt rS
= INSN(11,8);
17183 UInt rM
= INSN(3,0);
17184 if (rD
== 15 || rM
== 15 || rS
== 15) {
17185 /* Unpredictable; don't decode; fall through */
17187 IRTemp argL
= newTemp(Ity_I32
);
17188 IRTemp argR
= newTemp(Ity_I32
);
17189 IRTemp res
= newTemp(Ity_I32
);
17190 IRTemp oldC
= IRTemp_INVALID
;
17191 IRTemp oldV
= IRTemp_INVALID
;
17192 assign( argL
, getIRegA(rM
));
17193 assign( argR
, getIRegA(rS
));
17194 assign( res
, binop(Iop_Mul32
, mkexpr(argL
), mkexpr(argR
)) );
17196 oldC
= newTemp(Ity_I32
);
17197 assign(oldC
, mk_armg_calculate_flag_c());
17198 oldV
= newTemp(Ity_I32
);
17199 assign(oldV
, mk_armg_calculate_flag_v());
17201 // now update guest state
17202 putIRegA( rD
, mkexpr(res
), condT
, Ijk_Boring
);
17204 IRTemp pair
= newTemp(Ity_I32
);
17205 assign( pair
, binop(Iop_Or32
,
17206 binop(Iop_Shl32
, mkexpr(oldC
), mkU8(1)),
17208 setFlags_D1_ND( ARMG_CC_OP_MUL
, res
, pair
, condT
);
17210 DIP("mul%c%s r%u, r%u, r%u\n",
17211 bitS
? 's' : ' ', nCC(INSN_COND
), rD
, rM
, rS
);
17212 goto decode_success
;
17217 /* --------------------- Integer Divides --------------------- */
17219 if (BITS8(0,1,1,1,0,0,0,1) == INSN(27,20)
17220 && INSN(15,12) == BITS4(1,1,1,1)
17221 && INSN(7,4) == BITS4(0,0,0,1)) {
17222 UInt rD
= INSN(19,16);
17223 UInt rM
= INSN(11,8);
17224 UInt rN
= INSN(3,0);
17225 if (rD
== 15 || rM
== 15 || rN
== 15) {
17226 /* Unpredictable; don't decode; fall through */
17228 IRTemp res
= newTemp(Ity_I32
);
17229 IRTemp argL
= newTemp(Ity_I32
);
17230 IRTemp argR
= newTemp(Ity_I32
);
17231 assign(argL
, getIRegA(rN
));
17232 assign(argR
, getIRegA(rM
));
17233 assign(res
, binop(Iop_DivS32
, mkexpr(argL
), mkexpr(argR
)));
17234 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
17235 DIP("sdiv r%u, r%u, r%u\n", rD
, rN
, rM
);
17236 goto decode_success
;
17241 if (BITS8(0,1,1,1,0,0,1,1) == INSN(27,20)
17242 && INSN(15,12) == BITS4(1,1,1,1)
17243 && INSN(7,4) == BITS4(0,0,0,1)) {
17244 UInt rD
= INSN(19,16);
17245 UInt rM
= INSN(11,8);
17246 UInt rN
= INSN(3,0);
17247 if (rD
== 15 || rM
== 15 || rN
== 15) {
17248 /* Unpredictable; don't decode; fall through */
17250 IRTemp res
= newTemp(Ity_I32
);
17251 IRTemp argL
= newTemp(Ity_I32
);
17252 IRTemp argR
= newTemp(Ity_I32
);
17253 assign(argL
, getIRegA(rN
));
17254 assign(argR
, getIRegA(rM
));
17255 assign(res
, binop(Iop_DivU32
, mkexpr(argL
), mkexpr(argR
)));
17256 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
17257 DIP("udiv r%u, r%u, r%u\n", rD
, rN
, rM
);
17258 goto decode_success
;
17263 if (BITS8(0,0,0,0,0,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
17264 && INSN(7,4) == BITS4(1,0,0,1)) {
17265 UInt bitS
= (insn
>> 20) & 1; /* 20:20 */
17266 UInt isMLS
= (insn
>> 22) & 1; /* 22:22 */
17267 UInt rD
= INSN(19,16);
17268 UInt rN
= INSN(15,12);
17269 UInt rS
= INSN(11,8);
17270 UInt rM
= INSN(3,0);
17271 if (bitS
== 1 && isMLS
== 1) {
17272 /* This isn't allowed (MLS that sets flags). don't decode;
17276 if (rD
== 15 || rM
== 15 || rS
== 15 || rN
== 15) {
17277 /* Unpredictable; don't decode; fall through */
17279 IRTemp argL
= newTemp(Ity_I32
);
17280 IRTemp argR
= newTemp(Ity_I32
);
17281 IRTemp argP
= newTemp(Ity_I32
);
17282 IRTemp res
= newTemp(Ity_I32
);
17283 IRTemp oldC
= IRTemp_INVALID
;
17284 IRTemp oldV
= IRTemp_INVALID
;
17285 assign( argL
, getIRegA(rM
));
17286 assign( argR
, getIRegA(rS
));
17287 assign( argP
, getIRegA(rN
));
17288 assign( res
, binop(isMLS
? Iop_Sub32
: Iop_Add32
,
17290 binop(Iop_Mul32
, mkexpr(argL
), mkexpr(argR
)) ));
17292 vassert(!isMLS
); // guaranteed above
17293 oldC
= newTemp(Ity_I32
);
17294 assign(oldC
, mk_armg_calculate_flag_c());
17295 oldV
= newTemp(Ity_I32
);
17296 assign(oldV
, mk_armg_calculate_flag_v());
17298 // now update guest state
17299 putIRegA( rD
, mkexpr(res
), condT
, Ijk_Boring
);
17301 IRTemp pair
= newTemp(Ity_I32
);
17302 assign( pair
, binop(Iop_Or32
,
17303 binop(Iop_Shl32
, mkexpr(oldC
), mkU8(1)),
17305 setFlags_D1_ND( ARMG_CC_OP_MUL
, res
, pair
, condT
);
17307 DIP("ml%c%c%s r%u, r%u, r%u, r%u\n",
17308 isMLS
? 's' : 'a', bitS
? 's' : ' ',
17309 nCC(INSN_COND
), rD
, rM
, rS
, rN
);
17310 goto decode_success
;
17316 if (BITS8(0,0,0,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
17317 && INSN(7,4) == BITS4(1,0,0,1)) {
17318 UInt bitS
= (insn
>> 20) & 1; /* 20:20 */
17319 UInt rDhi
= INSN(19,16);
17320 UInt rDlo
= INSN(15,12);
17321 UInt rS
= INSN(11,8);
17322 UInt rM
= INSN(3,0);
17323 UInt isS
= (INSN(27,20) >> 2) & 1; /* 22:22 */
17324 if (rDhi
== 15 || rDlo
== 15 || rM
== 15 || rS
== 15 || rDhi
== rDlo
) {
17325 /* Unpredictable; don't decode; fall through */
17327 IRTemp argL
= newTemp(Ity_I32
);
17328 IRTemp argR
= newTemp(Ity_I32
);
17329 IRTemp res
= newTemp(Ity_I64
);
17330 IRTemp resHi
= newTemp(Ity_I32
);
17331 IRTemp resLo
= newTemp(Ity_I32
);
17332 IRTemp oldC
= IRTemp_INVALID
;
17333 IRTemp oldV
= IRTemp_INVALID
;
17334 IROp mulOp
= isS
? Iop_MullS32
: Iop_MullU32
;
17335 assign( argL
, getIRegA(rM
));
17336 assign( argR
, getIRegA(rS
));
17337 assign( res
, binop(mulOp
, mkexpr(argL
), mkexpr(argR
)) );
17338 assign( resHi
, unop(Iop_64HIto32
, mkexpr(res
)) );
17339 assign( resLo
, unop(Iop_64to32
, mkexpr(res
)) );
17341 oldC
= newTemp(Ity_I32
);
17342 assign(oldC
, mk_armg_calculate_flag_c());
17343 oldV
= newTemp(Ity_I32
);
17344 assign(oldV
, mk_armg_calculate_flag_v());
17346 // now update guest state
17347 putIRegA( rDhi
, mkexpr(resHi
), condT
, Ijk_Boring
);
17348 putIRegA( rDlo
, mkexpr(resLo
), condT
, Ijk_Boring
);
17350 IRTemp pair
= newTemp(Ity_I32
);
17351 assign( pair
, binop(Iop_Or32
,
17352 binop(Iop_Shl32
, mkexpr(oldC
), mkU8(1)),
17354 setFlags_D1_D2_ND( ARMG_CC_OP_MULL
, resLo
, resHi
, pair
, condT
);
17356 DIP("%cmull%c%s r%u, r%u, r%u, r%u\n",
17357 isS
? 's' : 'u', bitS
? 's' : ' ',
17358 nCC(INSN_COND
), rDlo
, rDhi
, rM
, rS
);
17359 goto decode_success
;
17365 if (BITS8(0,0,0,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
17366 && INSN(7,4) == BITS4(1,0,0,1)) {
17367 UInt bitS
= (insn
>> 20) & 1; /* 20:20 */
17368 UInt rDhi
= INSN(19,16);
17369 UInt rDlo
= INSN(15,12);
17370 UInt rS
= INSN(11,8);
17371 UInt rM
= INSN(3,0);
17372 UInt isS
= (INSN(27,20) >> 2) & 1; /* 22:22 */
17373 if (rDhi
== 15 || rDlo
== 15 || rM
== 15 || rS
== 15 || rDhi
== rDlo
) {
17374 /* Unpredictable; don't decode; fall through */
17376 IRTemp argL
= newTemp(Ity_I32
);
17377 IRTemp argR
= newTemp(Ity_I32
);
17378 IRTemp old
= newTemp(Ity_I64
);
17379 IRTemp res
= newTemp(Ity_I64
);
17380 IRTemp resHi
= newTemp(Ity_I32
);
17381 IRTemp resLo
= newTemp(Ity_I32
);
17382 IRTemp oldC
= IRTemp_INVALID
;
17383 IRTemp oldV
= IRTemp_INVALID
;
17384 IROp mulOp
= isS
? Iop_MullS32
: Iop_MullU32
;
17385 assign( argL
, getIRegA(rM
));
17386 assign( argR
, getIRegA(rS
));
17387 assign( old
, binop(Iop_32HLto64
, getIRegA(rDhi
), getIRegA(rDlo
)) );
17388 assign( res
, binop(Iop_Add64
,
17390 binop(mulOp
, mkexpr(argL
), mkexpr(argR
))) );
17391 assign( resHi
, unop(Iop_64HIto32
, mkexpr(res
)) );
17392 assign( resLo
, unop(Iop_64to32
, mkexpr(res
)) );
17394 oldC
= newTemp(Ity_I32
);
17395 assign(oldC
, mk_armg_calculate_flag_c());
17396 oldV
= newTemp(Ity_I32
);
17397 assign(oldV
, mk_armg_calculate_flag_v());
17399 // now update guest state
17400 putIRegA( rDhi
, mkexpr(resHi
), condT
, Ijk_Boring
);
17401 putIRegA( rDlo
, mkexpr(resLo
), condT
, Ijk_Boring
);
17403 IRTemp pair
= newTemp(Ity_I32
);
17404 assign( pair
, binop(Iop_Or32
,
17405 binop(Iop_Shl32
, mkexpr(oldC
), mkU8(1)),
17407 setFlags_D1_D2_ND( ARMG_CC_OP_MULL
, resLo
, resHi
, pair
, condT
);
17409 DIP("%cmlal%c%s r%u, r%u, r%u, r%u\n",
17410 isS
? 's' : 'u', bitS
? 's' : ' ', nCC(INSN_COND
),
17411 rDlo
, rDhi
, rM
, rS
);
17412 goto decode_success
;
17418 if (BITS8(0,0,0,0,0,1,0,0) == INSN(27,20) && INSN(7,4) == BITS4(1,0,0,1)) {
17419 UInt rDhi
= INSN(19,16);
17420 UInt rDlo
= INSN(15,12);
17421 UInt rM
= INSN(11,8);
17422 UInt rN
= INSN(3,0);
17423 if (rDlo
== 15 || rDhi
== 15 || rN
== 15 || rM
== 15 || rDhi
== rDlo
) {
17424 /* Unpredictable; don't decode; fall through */
17426 IRTemp argN
= newTemp(Ity_I32
);
17427 IRTemp argM
= newTemp(Ity_I32
);
17428 IRTemp argDhi
= newTemp(Ity_I32
);
17429 IRTemp argDlo
= newTemp(Ity_I32
);
17430 IRTemp res
= newTemp(Ity_I64
);
17431 IRTemp resHi
= newTemp(Ity_I32
);
17432 IRTemp resLo
= newTemp(Ity_I32
);
17433 assign( argN
, getIRegA(rN
) );
17434 assign( argM
, getIRegA(rM
) );
17435 assign( argDhi
, getIRegA(rDhi
) );
17436 assign( argDlo
, getIRegA(rDlo
) );
17440 binop(Iop_MullU32
, mkexpr(argN
), mkexpr(argM
)),
17441 unop(Iop_32Uto64
, mkexpr(argDhi
))),
17442 unop(Iop_32Uto64
, mkexpr(argDlo
))) );
17443 assign( resHi
, unop(Iop_64HIto32
, mkexpr(res
)) );
17444 assign( resLo
, unop(Iop_64to32
, mkexpr(res
)) );
17445 // now update guest state
17446 putIRegA( rDhi
, mkexpr(resHi
), condT
, Ijk_Boring
);
17447 putIRegA( rDlo
, mkexpr(resLo
), condT
, Ijk_Boring
);
17448 DIP("umaal %s r%u, r%u, r%u, r%u\n",
17449 nCC(INSN_COND
), rDlo
, rDhi
, rN
, rM
);
17450 goto decode_success
;
17455 /* --------------------- Msr etc --------------------- */
17458 if (INSN(27,20) == BITS8(0,0,1,1,0,0,1,0)
17459 && INSN(17,12) == BITS6(0,0,1,1,1,1)) {
17460 UInt write_ge
= INSN(18,18);
17461 UInt write_nzcvq
= INSN(19,19);
17462 if (write_nzcvq
|| write_ge
) {
17463 UInt imm
= (INSN(11,0) >> 0) & 0xFF;
17464 UInt rot
= 2 * ((INSN(11,0) >> 8) & 0xF);
17465 IRTemp immT
= newTemp(Ity_I32
);
17466 vassert(rot
<= 30);
17467 imm
= ROR32(imm
, rot
);
17468 assign(immT
, mkU32(imm
));
17469 desynthesise_APSR( write_nzcvq
, write_ge
, immT
, condT
);
17470 DIP("msr%s cpsr%s%sf, #0x%08x\n", nCC(INSN_COND
),
17471 write_nzcvq
? "f" : "", write_ge
? "g" : "", imm
);
17472 goto decode_success
;
17478 if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
17479 && INSN(17,12) == BITS6(0,0,1,1,1,1)
17480 && INSN(11,4) == BITS8(0,0,0,0,0,0,0,0)) {
17481 UInt rN
= INSN(3,0);
17482 UInt write_ge
= INSN(18,18);
17483 UInt write_nzcvq
= INSN(19,19);
17484 if (rN
!= 15 && (write_nzcvq
|| write_ge
)) {
17485 IRTemp rNt
= newTemp(Ity_I32
);
17486 assign(rNt
, getIRegA(rN
));
17487 desynthesise_APSR( write_nzcvq
, write_ge
, rNt
, condT
);
17488 DIP("msr%s cpsr_%s%s, r%u\n", nCC(INSN_COND
),
17489 write_nzcvq
? "f" : "", write_ge
? "g" : "", rN
);
17490 goto decode_success
;
17496 if ((insn
& 0x0FFF0FFF) == 0x010F0000) {
17497 UInt rD
= INSN(15,12);
17499 IRTemp apsr
= synthesise_APSR();
17500 putIRegA( rD
, mkexpr(apsr
), condT
, Ijk_Boring
);
17501 DIP("mrs%s r%u, cpsr\n", nCC(INSN_COND
), rD
);
17502 goto decode_success
;
17507 /* --------------------- Svc --------------------- */
17508 if (BITS8(1,1,1,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))) {
17509 UInt imm24
= (insn
>> 0) & 0xFFFFFF;
17511 /* A syscall. We can't do this conditionally, hence: */
17512 if (condT
!= IRTemp_INVALID
) {
17513 mk_skip_over_A32_if_cond_is_false( condT
);
17516 llPutIReg(15, mkU32( guest_R15_curr_instr_notENC
+ 4 ));
17517 dres
.jk_StopHere
= Ijk_Sys_syscall
;
17518 dres
.whatNext
= Dis_StopHere
;
17519 DIP("svc%s #0x%08x\n", nCC(INSN_COND
), imm24
);
17520 goto decode_success
;
17525 /* ------------------------ swp ------------------------ */
17528 if (BITS8(0,0,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
17529 && BITS4(0,0,0,0) == INSN(11,8)
17530 && BITS4(1,0,0,1) == INSN(7,4)) {
17531 UInt rN
= INSN(19,16);
17532 UInt rD
= INSN(15,12);
17533 UInt rM
= INSN(3,0);
17534 IRTemp tRn
= newTemp(Ity_I32
);
17535 IRTemp tNew
= newTemp(Ity_I32
);
17536 IRTemp tOld
= IRTemp_INVALID
;
17537 IRTemp tSC1
= newTemp(Ity_I1
);
17538 UInt isB
= (insn
>> 22) & 1;
17540 if (rD
== 15 || rN
== 15 || rM
== 15 || rN
== rM
|| rN
== rD
) {
17541 /* undecodable; fall through */
17543 /* make unconditional */
17544 if (condT
!= IRTemp_INVALID
) {
17545 mk_skip_over_A32_if_cond_is_false( condT
);
17546 condT
= IRTemp_INVALID
;
17548 /* Ok, now we're unconditional. Generate a LL-SC loop. */
17549 assign(tRn
, getIRegA(rN
));
17550 assign(tNew
, getIRegA(rM
));
17553 tOld
= newTemp(Ity_I8
);
17554 stmt( IRStmt_LLSC(Iend_LE
, tOld
, mkexpr(tRn
),
17556 stmt( IRStmt_LLSC(Iend_LE
, tSC1
, mkexpr(tRn
),
17557 unop(Iop_32to8
, mkexpr(tNew
))) );
17560 tOld
= newTemp(Ity_I32
);
17561 stmt( IRStmt_LLSC(Iend_LE
, tOld
, mkexpr(tRn
),
17563 stmt( IRStmt_LLSC(Iend_LE
, tSC1
, mkexpr(tRn
),
17566 stmt( IRStmt_Exit(unop(Iop_Not1
, mkexpr(tSC1
)),
17567 /*Ijk_NoRedir*/Ijk_Boring
,
17568 IRConst_U32(guest_R15_curr_instr_notENC
),
17570 putIRegA(rD
, isB
? unop(Iop_8Uto32
, mkexpr(tOld
)) : mkexpr(tOld
),
17571 IRTemp_INVALID
, Ijk_Boring
);
17572 DIP("swp%s%s r%u, r%u, [r%u]\n",
17573 isB
? "b" : "", nCC(INSN_COND
), rD
, rM
, rN
);
17574 goto decode_success
;
17579 /* ----------------------------------------------------------- */
17580 /* -- ARMv6 instructions -- */
17581 /* ----------------------------------------------------------- */
17583 /* ------------------- {ldr,str}ex{,b,h,d} ------------------- */
17585 // LDREXD, LDREX, LDREXH, LDREXB
17586 if (0x01900F9F == (insn
& 0x0F900FFF)) {
17587 UInt rT
= INSN(15,12);
17588 UInt rN
= INSN(19,16);
17589 IRType ty
= Ity_INVALID
;
17590 IROp widen
= Iop_INVALID
;
17591 const HChar
* nm
= NULL
;
17593 switch (INSN(22,21)) {
17594 case 0: nm
= ""; ty
= Ity_I32
; break;
17595 case 1: nm
= "d"; ty
= Ity_I64
; break;
17596 case 2: nm
= "b"; ty
= Ity_I8
; widen
= Iop_8Uto32
; break;
17597 case 3: nm
= "h"; ty
= Ity_I16
; widen
= Iop_16Uto32
; break;
17598 default: vassert(0);
17600 if (ty
== Ity_I32
|| ty
== Ity_I16
|| ty
== Ity_I8
) {
17601 if (rT
== 15 || rN
== 15)
17604 vassert(ty
== Ity_I64
);
17605 if ((rT
& 1) == 1 || rT
== 14 || rN
== 15)
17610 /* make unconditional */
17611 if (condT
!= IRTemp_INVALID
) {
17612 mk_skip_over_A32_if_cond_is_false( condT
);
17613 condT
= IRTemp_INVALID
;
17615 /* Ok, now we're unconditional. Do the load. */
17617 // FIXME: assumes little-endian guest
17618 stmt( IRStmt_LLSC(Iend_LE
, res
, getIRegA(rN
),
17619 NULL
/*this is a load*/) );
17620 if (ty
== Ity_I64
) {
17621 // FIXME: assumes little-endian guest
17622 putIRegA(rT
+0, unop(Iop_64to32
, mkexpr(res
)),
17623 IRTemp_INVALID
, Ijk_Boring
);
17624 putIRegA(rT
+1, unop(Iop_64HIto32
, mkexpr(res
)),
17625 IRTemp_INVALID
, Ijk_Boring
);
17626 DIP("ldrex%s%s r%u, r%u, [r%u]\n",
17627 nm
, nCC(INSN_COND
), rT
+0, rT
+1, rN
);
17629 putIRegA(rT
, widen
== Iop_INVALID
17630 ? mkexpr(res
) : unop(widen
, mkexpr(res
)),
17631 IRTemp_INVALID
, Ijk_Boring
);
17632 DIP("ldrex%s%s r%u, [r%u]\n", nm
, nCC(INSN_COND
), rT
, rN
);
17634 goto decode_success
;
17636 /* undecodable; fall through */
17639 // STREXD, STREX, STREXH, STREXB
17640 if (0x01800F90 == (insn
& 0x0F900FF0)) {
17641 UInt rT
= INSN(3,0);
17642 UInt rN
= INSN(19,16);
17643 UInt rD
= INSN(15,12);
17644 IRType ty
= Ity_INVALID
;
17645 IROp narrow
= Iop_INVALID
;
17646 const HChar
* nm
= NULL
;
17648 switch (INSN(22,21)) {
17649 case 0: nm
= ""; ty
= Ity_I32
; break;
17650 case 1: nm
= "d"; ty
= Ity_I64
; break;
17651 case 2: nm
= "b"; ty
= Ity_I8
; narrow
= Iop_32to8
; break;
17652 case 3: nm
= "h"; ty
= Ity_I16
; narrow
= Iop_32to16
; break;
17653 default: vassert(0);
17655 if (ty
== Ity_I32
|| ty
== Ity_I16
|| ty
== Ity_I8
) {
17656 if (rD
== 15 || rN
== 15 || rT
== 15
17657 || rD
== rN
|| rD
== rT
)
17660 vassert(ty
== Ity_I64
);
17661 if (rD
== 15 || (rT
& 1) == 1 || rT
== 14 || rN
== 15
17662 || rD
== rN
|| rD
== rT
|| rD
== rT
+1)
17666 IRTemp resSC1
, resSC32
, data
;
17667 /* make unconditional */
17668 if (condT
!= IRTemp_INVALID
) {
17669 mk_skip_over_A32_if_cond_is_false( condT
);
17670 condT
= IRTemp_INVALID
;
17672 /* Ok, now we're unconditional. Do the store. */
17673 data
= newTemp(ty
);
17676 // FIXME: assumes little-endian guest
17677 ? binop(Iop_32HLto64
, getIRegA(rT
+1), getIRegA(rT
+0))
17678 : narrow
== Iop_INVALID
17680 : unop(narrow
, getIRegA(rT
)));
17681 resSC1
= newTemp(Ity_I1
);
17682 // FIXME: assumes little-endian guest
17683 stmt( IRStmt_LLSC(Iend_LE
, resSC1
, getIRegA(rN
), mkexpr(data
)) );
17685 /* Set rD to 1 on failure, 0 on success. Currently we have
17686 resSC1 == 0 on failure, 1 on success. */
17687 resSC32
= newTemp(Ity_I32
);
17689 unop(Iop_1Uto32
, unop(Iop_Not1
, mkexpr(resSC1
))));
17691 putIRegA(rD
, mkexpr(resSC32
),
17692 IRTemp_INVALID
, Ijk_Boring
);
17693 if (ty
== Ity_I64
) {
17694 DIP("strex%s%s r%u, r%u, r%u, [r%u]\n",
17695 nm
, nCC(INSN_COND
), rD
, rT
, rT
+1, rN
);
17697 DIP("strex%s%s r%u, r%u, [r%u]\n",
17698 nm
, nCC(INSN_COND
), rD
, rT
, rN
);
17700 goto decode_success
;
17705 /* --------------------- movw, movt --------------------- */
17706 if (0x03000000 == (insn
& 0x0FF00000)
17707 || 0x03400000 == (insn
& 0x0FF00000)) /* pray for CSE */ {
17708 UInt rD
= INSN(15,12);
17709 UInt imm16
= (insn
& 0xFFF) | ((insn
>> 4) & 0x0000F000);
17710 UInt isT
= (insn
>> 22) & 1;
17717 binop(Iop_And32
, getIRegA(rD
), mkU32(0xFFFF)),
17718 mkU32(imm16
<< 16)),
17719 condT
, Ijk_Boring
);
17720 DIP("movt%s r%u, #0x%04x\n", nCC(INSN_COND
), rD
, imm16
);
17721 goto decode_success
;
17723 putIRegA(rD
, mkU32(imm16
), condT
, Ijk_Boring
);
17724 DIP("movw%s r%u, #0x%04x\n", nCC(INSN_COND
), rD
, imm16
);
17725 goto decode_success
;
17731 /* ----------- uxtb, sxtb, uxth, sxth, uxtb16, sxtb16 ----------- */
17732 /* FIXME: this is an exact duplicate of the Thumb version. They
17733 should be commoned up. */
17734 if (BITS8(0,1,1,0,1, 0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,0))
17735 && BITS4(1,1,1,1) == INSN(19,16)
17736 && BITS4(0,1,1,1) == INSN(7,4)
17737 && BITS4(0,0, 0,0) == (INSN(11,8) & BITS4(0,0,1,1))) {
17738 UInt subopc
= INSN(27,20) & BITS8(0,0,0,0,0, 1,1,1);
17739 if (subopc
!= BITS4(0,0,0,1) && subopc
!= BITS4(0,1,0,1)) {
17740 Int rot
= (INSN(11,8) >> 2) & 3;
17741 UInt rM
= INSN(3,0);
17742 UInt rD
= INSN(15,12);
17743 IRTemp srcT
= newTemp(Ity_I32
);
17744 IRTemp rotT
= newTemp(Ity_I32
);
17745 IRTemp dstT
= newTemp(Ity_I32
);
17746 const HChar
* nm
= "???";
17747 assign(srcT
, getIRegA(rM
));
17748 assign(rotT
, genROR32(srcT
, 8 * rot
)); /* 0, 8, 16 or 24 only */
17750 case BITS4(0,1,1,0): // UXTB
17751 assign(dstT
, unop(Iop_8Uto32
, unop(Iop_32to8
, mkexpr(rotT
))));
17754 case BITS4(0,0,1,0): // SXTB
17755 assign(dstT
, unop(Iop_8Sto32
, unop(Iop_32to8
, mkexpr(rotT
))));
17758 case BITS4(0,1,1,1): // UXTH
17759 assign(dstT
, unop(Iop_16Uto32
, unop(Iop_32to16
, mkexpr(rotT
))));
17762 case BITS4(0,0,1,1): // SXTH
17763 assign(dstT
, unop(Iop_16Sto32
, unop(Iop_32to16
, mkexpr(rotT
))));
17766 case BITS4(0,1,0,0): // UXTB16
17767 assign(dstT
, binop(Iop_And32
, mkexpr(rotT
), mkU32(0x00FF00FF)));
17770 case BITS4(0,0,0,0): { // SXTB16
17771 IRTemp lo32
= newTemp(Ity_I32
);
17772 IRTemp hi32
= newTemp(Ity_I32
);
17773 assign(lo32
, binop(Iop_And32
, mkexpr(rotT
), mkU32(0xFF)));
17774 assign(hi32
, binop(Iop_Shr32
, mkexpr(rotT
), mkU8(16)));
17780 unop(Iop_32to8
, mkexpr(lo32
))),
17784 unop(Iop_32to8
, mkexpr(hi32
))),
17791 vassert(0); // guarded by "if" above
17793 putIRegA(rD
, mkexpr(dstT
), condT
, Ijk_Boring
);
17794 DIP("%s%s r%u, r%u, ROR #%d\n", nm
, nCC(INSN_COND
), rD
, rM
, rot
);
17795 goto decode_success
;
17800 /* ------------------- bfi, bfc ------------------- */
17801 if (BITS8(0,1,1,1,1,1,0, 0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
17802 && BITS4(0, 0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
17803 UInt rD
= INSN(15,12);
17804 UInt rN
= INSN(3,0);
17805 UInt msb
= (insn
>> 16) & 0x1F; /* 20:16 */
17806 UInt lsb
= (insn
>> 7) & 0x1F; /* 11:7 */
17807 if (rD
== 15 || msb
< lsb
) {
17808 /* undecodable; fall through */
17810 IRTemp src
= newTemp(Ity_I32
);
17811 IRTemp olddst
= newTemp(Ity_I32
);
17812 IRTemp newdst
= newTemp(Ity_I32
);
17813 UInt mask
= ((UInt
)1) << (msb
- lsb
);
17814 mask
= (mask
- 1) + mask
;
17815 vassert(mask
!= 0); // guaranteed by "msb < lsb" check above
17818 assign(src
, rN
== 15 ? mkU32(0) : getIRegA(rN
));
17819 assign(olddst
, getIRegA(rD
));
17823 binop(Iop_Shl32
, mkexpr(src
), mkU8(lsb
)),
17830 putIRegA(rD
, mkexpr(newdst
), condT
, Ijk_Boring
);
17833 DIP("bfc%s r%u, #%u, #%u\n",
17834 nCC(INSN_COND
), rD
, lsb
, msb
-lsb
+1);
17836 DIP("bfi%s r%u, r%u, #%u, #%u\n",
17837 nCC(INSN_COND
), rD
, rN
, lsb
, msb
-lsb
+1);
17839 goto decode_success
;
17844 /* ------------------- {u,s}bfx ------------------- */
17845 if (BITS8(0,1,1,1,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
17846 && BITS4(0,1,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
17847 UInt rD
= INSN(15,12);
17848 UInt rN
= INSN(3,0);
17849 UInt wm1
= (insn
>> 16) & 0x1F; /* 20:16 */
17850 UInt lsb
= (insn
>> 7) & 0x1F; /* 11:7 */
17851 UInt msb
= lsb
+ wm1
;
17852 UInt isU
= (insn
>> 22) & 1; /* 22:22 */
17853 if (rD
== 15 || rN
== 15 || msb
>= 32) {
17854 /* undecodable; fall through */
17856 IRTemp src
= newTemp(Ity_I32
);
17857 IRTemp tmp
= newTemp(Ity_I32
);
17858 IRTemp res
= newTemp(Ity_I32
);
17859 UInt mask
= ((1 << wm1
) - 1) + (1 << wm1
);
17860 vassert(msb
>= 0 && msb
<= 31);
17861 vassert(mask
!= 0); // guaranteed by msb being in 0 .. 31 inclusive
17863 assign(src
, getIRegA(rN
));
17864 assign(tmp
, binop(Iop_And32
,
17865 binop(Iop_Shr32
, mkexpr(src
), mkU8(lsb
)),
17867 assign(res
, binop(isU
? Iop_Shr32
: Iop_Sar32
,
17868 binop(Iop_Shl32
, mkexpr(tmp
), mkU8(31-wm1
)),
17871 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
17873 DIP("%s%s r%u, r%u, #%u, #%u\n",
17874 isU
? "ubfx" : "sbfx",
17875 nCC(INSN_COND
), rD
, rN
, lsb
, wm1
+ 1);
17876 goto decode_success
;
17881 /* --------------------- Load/store doubleword ------------- */
17883 /* 31 27 23 19 15 11 7 3 # highest bit
17884 28 24 20 16 12 8 4 0
17885 A5-36 1 | 16 cond 0001 U100 Rn Rd im4h 11S1 im4l
17886 A5-38 1 | 32 cond 0001 U000 Rn Rd 0000 11S1 Rm
17887 A5-40 2 | 16 cond 0001 U110 Rn Rd im4h 11S1 im4l
17888 A5-42 2 | 32 cond 0001 U010 Rn Rd 0000 11S1 Rm
17889 A5-44 3 | 16 cond 0000 U100 Rn Rd im4h 11S1 im4l
17890 A5-46 3 | 32 cond 0000 U000 Rn Rd 0000 11S1 Rm
17893 1 at-ea (access at ea)
17894 2 at-ea-then-upd (access at ea, then Rn = ea)
17895 3 at-Rn-then-upd (access at Rn, then Rn = ea)
17900 /* Quickly skip over all of this for hopefully most instructions */
17901 if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
17902 goto after_load_store_doubleword
;
17904 /* Check the "11S1" thing. */
17905 if ((INSN(7,4) & BITS4(1,1,0,1)) != BITS4(1,1,0,1))
17906 goto after_load_store_doubleword
;
17910 /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,0,0)) {
17913 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,0,0)) {
17916 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,1,0)) {
17919 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,1,0)) {
17922 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(1,0,0)) {
17925 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(0,0,0)) {
17928 else goto after_load_store_doubleword
;
17930 { UInt rN
= (insn
>> 16) & 0xF; /* 19:16 */
17931 UInt rD
= (insn
>> 12) & 0xF; /* 15:12 */
17932 UInt rM
= (insn
>> 0) & 0xF; /* 3:0 */
17933 UInt bU
= (insn
>> 23) & 1; /* 23 U=1 offset+, U=0 offset- */
17934 UInt bS
= (insn
>> 5) & 1; /* S=1 store, S=0 load */
17935 UInt imm8
= ((insn
>> 4) & 0xF0) | (insn
& 0xF); /* 11:8, 3:0 */
17937 /* Require rD to be an even numbered register */
17939 goto after_load_store_doubleword
;
17941 /* Require 11:8 == 0 for Rn +/- Rm cases */
17942 if ((summary
& 32) != 0 && (imm8
& 0xF0) != 0)
17943 goto after_load_store_doubleword
;
17945 /* Skip some invalid cases, which would lead to two competing
17946 updates to the same register, or which are otherwise
17947 disallowed by the spec. */
17952 if (rM
== 15) goto after_load_store_doubleword
;
17954 case 2 | 16: case 3 | 16:
17955 if (rN
== 15) goto after_load_store_doubleword
;
17956 if (bS
== 0 && (rN
== rD
|| rN
== rD
+1))
17957 goto after_load_store_doubleword
;
17959 case 2 | 32: case 3 | 32:
17960 if (rM
== 15) goto after_load_store_doubleword
;
17961 if (rN
== 15) goto after_load_store_doubleword
;
17962 if (rN
== rM
) goto after_load_store_doubleword
;
17963 if (bS
== 0 && (rN
== rD
|| rN
== rD
+1))
17964 goto after_load_store_doubleword
;
17970 /* If this is a branch, make it unconditional at this point.
17971 Doing conditional branches in-line is too complex (for
17973 vassert((rD
& 1) == 0); /* from tests above */
17974 if (bS
== 0 && rD
+1 == 15 && condT
!= IRTemp_INVALID
) {
17976 mk_skip_over_A32_if_cond_is_false( condT
);
17977 condT
= IRTemp_INVALID
;
17981 /* compute the effective address. Bind it to a tmp since we
17982 may need to use it twice. */
17983 IRExpr
* eaE
= NULL
;
17984 switch (summary
& 0xF0) {
17986 eaE
= mk_EA_reg_plusminus_imm8( rN
, bU
, imm8
, dis_buf
);
17989 eaE
= mk_EA_reg_plusminus_reg( rN
, bU
, rM
, dis_buf
);
17993 IRTemp eaT
= newTemp(Ity_I32
);
17996 /* get the old Rn value */
17997 IRTemp rnT
= newTemp(Ity_I32
);
17998 assign(rnT
, getIRegA(rN
));
18000 /* decide on the transfer address */
18001 IRTemp taT
= IRTemp_INVALID
;
18002 switch (summary
& 0x0F) {
18003 case 1: case 2: taT
= eaT
; break;
18004 case 3: taT
= rnT
; break;
18006 vassert(taT
!= IRTemp_INVALID
);
18008 /* XXX deal with alignment constraints */
18009 /* XXX: but the A8 doesn't seem to trap for misaligned loads, so,
18010 ignore alignment issues for the time being. */
18012 /* For almost all cases, we do the writeback after the transfers.
18013 However, that leaves the stack "uncovered" in cases like:
18015 strd rD, [sp, #-16]
18016 In which case, do the writeback to SP now, instead of later.
18017 This is bad in that it makes the insn non-restartable if the
18018 accesses fault, but at least keeps Memcheck happy. */
18019 Bool writeback_already_done
= False
;
18020 if (bS
== 1 /*store*/ && summary
== (2 | 16)
18021 && rN
== 13 && rN
!= rD
&& rN
!= rD
+1
18022 && bU
== 0/*minus*/
18023 && (imm8
== 8 || imm8
== 16)) {
18024 putIRegA( rN
, mkexpr(eaT
), condT
, Ijk_Boring
);
18025 writeback_already_done
= True
;
18028 /* doubleword store S 1
18029 doubleword load S 0
18031 const HChar
* name
= NULL
;
18032 /* generate the transfers */
18033 if (bS
== 1) { // doubleword store
18034 storeGuardedLE( binop(Iop_Add32
, mkexpr(taT
), mkU32(0)),
18035 getIRegA(rD
+0), condT
);
18036 storeGuardedLE( binop(Iop_Add32
, mkexpr(taT
), mkU32(4)),
18037 getIRegA(rD
+1), condT
);
18039 } else { // doubleword load
18040 IRTemp oldRd0
= newTemp(Ity_I32
);
18041 IRTemp oldRd1
= newTemp(Ity_I32
);
18042 assign(oldRd0
, llGetIReg(rD
+0));
18043 assign(oldRd1
, llGetIReg(rD
+1));
18044 IRTemp newRd0
= newTemp(Ity_I32
);
18045 IRTemp newRd1
= newTemp(Ity_I32
);
18046 loadGuardedLE( newRd0
, ILGop_Ident32
,
18047 binop(Iop_Add32
, mkexpr(taT
), mkU32(0)),
18048 mkexpr(oldRd0
), condT
);
18049 putIRegA( rD
+0, mkexpr(newRd0
), IRTemp_INVALID
, Ijk_Boring
);
18050 loadGuardedLE( newRd1
, ILGop_Ident32
,
18051 binop(Iop_Add32
, mkexpr(taT
), mkU32(4)),
18052 mkexpr(oldRd1
), condT
);
18053 putIRegA( rD
+1, mkexpr(newRd1
), IRTemp_INVALID
, Ijk_Boring
);
18057 /* Update Rn if necessary. */
18058 switch (summary
& 0x0F) {
18060 // should be assured by logic above:
18061 vassert(rN
!= 15); /* from checks above */
18063 vassert(rD
+0 != rN
); /* since we just wrote rD+0 */
18064 vassert(rD
+1 != rN
); /* since we just wrote rD+1 */
18066 if (!writeback_already_done
)
18067 putIRegA( rN
, mkexpr(eaT
), condT
, Ijk_Boring
);
18071 switch (summary
& 0x0F) {
18072 case 1: DIP("%s%s r%u, %s\n", name
, nCC(INSN_COND
), rD
, dis_buf
);
18074 case 2: DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
18075 name
, nCC(INSN_COND
), rD
, dis_buf
);
18077 case 3: DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
18078 name
, nCC(INSN_COND
), rD
, dis_buf
);
18080 default: vassert(0);
18083 goto decode_success
;
18086 after_load_store_doubleword
:
18088 /* ------------------- {s,u}xtab ------------- */
18089 if (BITS8(0,1,1,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
18090 && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
18091 && BITS4(0,1,1,1) == INSN(7,4)) {
18092 UInt rN
= INSN(19,16);
18093 UInt rD
= INSN(15,12);
18094 UInt rM
= INSN(3,0);
18095 UInt rot
= (insn
>> 10) & 3;
18096 UInt isU
= INSN(22,22);
18097 if (rN
== 15/*it's {S,U}XTB*/ || rD
== 15 || rM
== 15) {
18098 /* undecodable; fall through */
18100 IRTemp srcL
= newTemp(Ity_I32
);
18101 IRTemp srcR
= newTemp(Ity_I32
);
18102 IRTemp res
= newTemp(Ity_I32
);
18103 assign(srcR
, getIRegA(rM
));
18104 assign(srcL
, getIRegA(rN
));
18105 assign(res
, binop(Iop_Add32
,
18107 unop(isU
? Iop_8Uto32
: Iop_8Sto32
,
18109 genROR32(srcR
, 8 * rot
)))));
18110 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
18111 DIP("%cxtab%s r%u, r%u, r%u, ror #%u\n",
18112 isU
? 'u' : 's', nCC(INSN_COND
), rD
, rN
, rM
, rot
);
18113 goto decode_success
;
18118 /* ------------------- {s,u}xtah ------------- */
18119 if (BITS8(0,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
18120 && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
18121 && BITS4(0,1,1,1) == INSN(7,4)) {
18122 UInt rN
= INSN(19,16);
18123 UInt rD
= INSN(15,12);
18124 UInt rM
= INSN(3,0);
18125 UInt rot
= (insn
>> 10) & 3;
18126 UInt isU
= INSN(22,22);
18127 if (rN
== 15/*it's {S,U}XTH*/ || rD
== 15 || rM
== 15) {
18128 /* undecodable; fall through */
18130 IRTemp srcL
= newTemp(Ity_I32
);
18131 IRTemp srcR
= newTemp(Ity_I32
);
18132 IRTemp res
= newTemp(Ity_I32
);
18133 assign(srcR
, getIRegA(rM
));
18134 assign(srcL
, getIRegA(rN
));
18135 assign(res
, binop(Iop_Add32
,
18137 unop(isU
? Iop_16Uto32
: Iop_16Sto32
,
18139 genROR32(srcR
, 8 * rot
)))));
18140 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
18142 DIP("%cxtah%s r%u, r%u, r%u, ror #%u\n",
18143 isU
? 'u' : 's', nCC(INSN_COND
), rD
, rN
, rM
, rot
);
18144 goto decode_success
;
18149 /* ------------------- rev16, rev ------------------ */
18150 if (INSN(27,16) == 0x6BF
18151 && (INSN(11,4) == 0xFB/*rev16*/ || INSN(11,4) == 0xF3/*rev*/)) {
18152 Bool isREV
= INSN(11,4) == 0xF3;
18153 UInt rM
= INSN(3,0);
18154 UInt rD
= INSN(15,12);
18155 if (rM
!= 15 && rD
!= 15) {
18156 IRTemp rMt
= newTemp(Ity_I32
);
18157 assign(rMt
, getIRegA(rM
));
18158 IRTemp res
= isREV
? gen_REV(rMt
) : gen_REV16(rMt
);
18159 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
18160 DIP("rev%s%s r%u, r%u\n", isREV
? "" : "16",
18161 nCC(INSN_COND
), rD
, rM
);
18162 goto decode_success
;
18166 /* ------------------- revsh ----------------------- */
18167 if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xFB) {
18168 UInt rM
= INSN(3,0);
18169 UInt rD
= INSN(15,12);
18170 if (rM
!= 15 && rD
!= 15) {
18171 IRTemp irt_rM
= newTemp(Ity_I32
);
18172 IRTemp irt_hi
= newTemp(Ity_I32
);
18173 IRTemp irt_low
= newTemp(Ity_I32
);
18174 IRTemp irt_res
= newTemp(Ity_I32
);
18175 assign(irt_rM
, getIRegA(rM
));
18178 binop(Iop_Shl32
, mkexpr(irt_rM
), mkU8(24)),
18184 binop(Iop_Shr32
, mkexpr(irt_rM
), mkU8(8)),
18189 binop(Iop_Or32
, mkexpr(irt_hi
), mkexpr(irt_low
))
18191 putIRegA(rD
, mkexpr(irt_res
), condT
, Ijk_Boring
);
18192 DIP("revsh%s r%u, r%u\n", nCC(INSN_COND
), rD
, rM
);
18193 goto decode_success
;
18197 /* ------------------- rbit ------------------ */
18198 if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) {
18199 UInt rD
= INSN(15,12);
18200 UInt rM
= INSN(3,0);
18201 if (rD
!= 15 && rM
!= 15) {
18202 IRTemp arg
= newTemp(Ity_I32
);
18203 assign(arg
, getIRegA(rM
));
18204 IRTemp res
= gen_BITREV(arg
);
18205 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
18206 DIP("rbit r%u, r%u\n", rD
, rM
);
18207 goto decode_success
;
18211 /* ------------------- smmul ------------------ */
18212 if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
18213 && INSN(15,12) == BITS4(1,1,1,1)
18214 && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
18215 UInt bitR
= INSN(5,5);
18216 UInt rD
= INSN(19,16);
18217 UInt rM
= INSN(11,8);
18218 UInt rN
= INSN(3,0);
18219 if (rD
!= 15 && rM
!= 15 && rN
!= 15) {
18221 = unop(Iop_64HIto32
,
18223 binop(Iop_MullS32
, getIRegA(rN
), getIRegA(rM
)),
18224 mkU64(bitR
? 0x80000000ULL
: 0ULL)));
18225 putIRegA(rD
, res
, condT
, Ijk_Boring
);
18226 DIP("smmul%s%s r%u, r%u, r%u\n",
18227 nCC(INSN_COND
), bitR
? "r" : "", rD
, rN
, rM
);
18228 goto decode_success
;
18232 /* ------------------- smmla ------------------ */
18233 if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
18234 && INSN(15,12) != BITS4(1,1,1,1)
18235 && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
18236 UInt bitR
= INSN(5,5);
18237 UInt rD
= INSN(19,16);
18238 UInt rA
= INSN(15,12);
18239 UInt rM
= INSN(11,8);
18240 UInt rN
= INSN(3,0);
18241 if (rD
!= 15 && rM
!= 15 && rN
!= 15) {
18243 = unop(Iop_64HIto32
,
18246 binop(Iop_32HLto64
, getIRegA(rA
), mkU32(0)),
18247 binop(Iop_MullS32
, getIRegA(rN
), getIRegA(rM
))),
18248 mkU64(bitR
? 0x80000000ULL
: 0ULL)));
18249 putIRegA(rD
, res
, condT
, Ijk_Boring
);
18250 DIP("smmla%s%s r%u, r%u, r%u, r%u\n",
18251 nCC(INSN_COND
), bitR
? "r" : "", rD
, rN
, rM
, rA
);
18252 goto decode_success
;
18256 /* -------------- (A1) LDRT reg+/-#imm12 -------------- */
18257 /* Load Register Unprivileged:
18258 ldrt<c> Rt, [Rn] {, #+/-imm12}
18260 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,0,0,0,0,1,1) ) {
18261 UInt rT
= INSN(15,12);
18262 UInt rN
= INSN(19,16);
18263 UInt imm12
= INSN(11,0);
18264 UInt bU
= INSN(23,23);
18266 if (rT
== 15 || rN
== 15 || rN
== rT
) valid
= False
;
18268 IRTemp newRt
= newTemp(Ity_I32
);
18269 loadGuardedLE( newRt
,
18270 ILGop_Ident32
, getIRegA(rN
), getIRegA(rT
), condT
);
18271 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18272 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18273 getIRegA(rN
), mkU32(imm12
));
18274 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18275 DIP("ldrt%s r%u, [r%u], #%c%u\n",
18276 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm12
);
18277 goto decode_success
;
18281 /* -------------- (A2) LDRT reg+/-reg with shift -------------- */
18282 /* Load Register Unprivileged:
18283 ldrt<c> Rt, [Rn], +/-Rm{, shift}
18285 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,1,0,0,0,1,1)
18286 && INSN(4,4) == 0 ) {
18287 UInt rT
= INSN(15,12);
18288 UInt rN
= INSN(19,16);
18289 UInt rM
= INSN(3,0);
18290 UInt imm5
= INSN(11,7);
18291 UInt bU
= INSN(23,23);
18292 UInt type
= INSN(6,5);
18294 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15
18295 /* || (ArchVersion() < 6 && rM == rN) */)
18298 IRTemp newRt
= newTemp(Ity_I32
);
18299 loadGuardedLE( newRt
,
18300 ILGop_Ident32
, getIRegA(rN
), getIRegA(rT
), condT
);
18301 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18302 // dis_buf generated is slightly bogus, in fact.
18303 IRExpr
* erN
= mk_EA_reg_plusminus_shifted_reg(rN
, bU
, rM
,
18304 type
, imm5
, dis_buf
);
18305 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18306 DIP("ldrt%s r%u, %s\n", nCC(INSN_COND
), rT
, dis_buf
);
18307 goto decode_success
;
18311 /* -------------- (A1) LDRBT reg+/-#imm12 -------------- */
18312 /* Load Register Byte Unprivileged:
18313 ldrbt<c> Rt, [Rn], #+/-imm12
18315 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,0,0,0,1,1,1) ) {
18316 UInt rT
= INSN(15,12);
18317 UInt rN
= INSN(19,16);
18318 UInt imm12
= INSN(11,0);
18319 UInt bU
= INSN(23,23);
18321 if (rT
== 15 || rN
== 15 || rN
== rT
) valid
= False
;
18323 IRTemp newRt
= newTemp(Ity_I32
);
18324 loadGuardedLE( newRt
,
18325 ILGop_8Uto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18326 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18327 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18328 getIRegA(rN
), mkU32(imm12
));
18329 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18330 DIP("ldrbt%s r%u, [r%u], #%c%u\n",
18331 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm12
);
18332 goto decode_success
;
18336 /* -------------- (A2) LDRBT reg+/-reg with shift -------------- */
18337 /* Load Register Byte Unprivileged:
18338 ldrbt<c> Rt, [Rn], +/-Rm{, shift}
18340 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,1,0,0,1,1,1)
18341 && INSN(4,4) == 0 ) {
18342 UInt rT
= INSN(15,12);
18343 UInt rN
= INSN(19,16);
18344 UInt rM
= INSN(3,0);
18345 UInt imm5
= INSN(11,7);
18346 UInt bU
= INSN(23,23);
18347 UInt type
= INSN(6,5);
18349 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15
18350 /* || (ArchVersion() < 6 && rM == rN) */)
18353 IRTemp newRt
= newTemp(Ity_I32
);
18354 loadGuardedLE( newRt
,
18355 ILGop_8Uto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18356 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18357 // dis_buf generated is slightly bogus, in fact.
18358 IRExpr
* erN
= mk_EA_reg_plusminus_shifted_reg(rN
, bU
, rM
,
18359 type
, imm5
, dis_buf
);
18360 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18361 DIP("ldrbt%s r%u, %s\n", nCC(INSN_COND
), rT
, dis_buf
);
18362 goto decode_success
;
18366 /* -------------- (A1) LDRHT reg+#imm8 -------------- */
18367 /* Load Register Halfword Unprivileged:
18368 ldrht<c> Rt, [Rn] {, #+/-imm8}
18370 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,1,1,1)
18371 && INSN(7,4) == BITS4(1,0,1,1) ) {
18372 UInt rT
= INSN(15,12);
18373 UInt rN
= INSN(19,16);
18374 UInt bU
= INSN(23,23);
18375 UInt imm4H
= INSN(11,8);
18376 UInt imm4L
= INSN(3,0);
18377 UInt imm8
= (imm4H
<< 4) | imm4L
;
18379 if (rT
== 15 || rN
== 15 || rN
== rT
)
18382 IRTemp newRt
= newTemp(Ity_I32
);
18383 loadGuardedLE( newRt
,
18384 ILGop_16Uto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18385 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18386 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18387 getIRegA(rN
), mkU32(imm8
));
18388 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18389 DIP("ldrht%s r%u, [r%u], #%c%u\n",
18390 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm8
);
18391 goto decode_success
;
18395 /* -------------- (A2) LDRHT reg+/-reg -------------- */
18396 /* Load Register Halfword Unprivileged:
18397 ldrht<c> Rt, [Rn], +/-Rm
18399 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,0,1,1)
18400 && INSN(11,4) == BITS8(0,0,0,0,1,0,1,1) ) {
18401 UInt rT
= INSN(15,12);
18402 UInt rN
= INSN(19,16);
18403 UInt rM
= INSN(3,0);
18404 UInt bU
= INSN(23,23);
18406 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15)
18409 IRTemp newRt
= newTemp(Ity_I32
);
18410 loadGuardedLE( newRt
,
18411 ILGop_16Uto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18412 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18413 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18414 getIRegA(rN
), getIRegA(rM
));
18415 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18416 DIP("ldrht%s r%u, [r%u], %cr%u\n",
18417 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', rM
);
18418 goto decode_success
;
18422 /* -------------- (A1) LDRSHT reg+#imm8 -------------- */
18423 /* Load Register Signed Halfword Unprivileged:
18424 ldrsht<c> Rt, [Rn] {, #+/-imm8}
18426 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,1,1,1)
18427 && INSN(7,4) == BITS4(1,1,1,1)) {
18428 UInt rT
= INSN(15,12);
18429 UInt rN
= INSN(19,16);
18430 UInt bU
= INSN(23,23);
18431 UInt imm4H
= INSN(11,8);
18432 UInt imm4L
= INSN(3,0);
18433 UInt imm8
= (imm4H
<< 4) | imm4L
;
18435 if (rN
== 15 || rT
== 15 || rN
== rT
)
18438 IRTemp newRt
= newTemp(Ity_I32
);
18439 loadGuardedLE( newRt
,
18440 ILGop_16Sto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18441 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18442 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18443 getIRegA(rN
), mkU32(imm8
));
18444 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18445 DIP("ldrsht%s r%u, [r%u], #%c%u\n",
18446 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm8
);
18447 goto decode_success
;
18451 /* -------------- (A2) LDRSHT reg+/-reg -------------- */
18452 /* Load Register Signed Halfword Unprivileged:
18453 ldrsht<c> Rt, [Rn], +/-Rm
18455 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,0,1,1)
18456 && INSN(11,4) == BITS8(0,0,0,0,1,1,1,1)) {
18457 UInt rT
= INSN(15,12);
18458 UInt rN
= INSN(19,16);
18459 UInt rM
= INSN(3,0);
18460 UInt bU
= INSN(23,23);
18462 if (rN
== 15 || rT
== 15 || rN
== rT
|| rM
== 15)
18465 IRTemp newRt
= newTemp(Ity_I32
);
18466 loadGuardedLE( newRt
,
18467 ILGop_16Sto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18468 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18469 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18470 getIRegA(rN
), getIRegA(rM
));
18471 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18472 DIP("ldrsht%s r%u, [r%u], %cr%u\n",
18473 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', rM
);
18474 goto decode_success
;
18478 /* -------------- (A1) LDRSBT reg+#imm8 -------------- */
18479 /* Load Register Signed Byte Unprivileged:
18480 ldrsbt<c> Rt, [Rn] {, #+/-imm8}
18482 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,1,1,1)
18483 && INSN(7,4) == BITS4(1,1,0,1)) {
18484 UInt rT
= INSN(15,12);
18485 UInt rN
= INSN(19,16);
18486 UInt bU
= INSN(23,23);
18487 UInt imm4H
= INSN(11,8);
18488 UInt imm4L
= INSN(3,0);
18489 UInt imm8
= (imm4H
<< 4) | imm4L
;
18491 if (rT
== 15 || rN
== 15 || rN
== rT
)
18494 IRTemp newRt
= newTemp(Ity_I32
);
18495 loadGuardedLE( newRt
,
18496 ILGop_8Sto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18497 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18498 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18499 getIRegA(rN
), mkU32(imm8
));
18500 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18501 DIP("ldrsbt%s r%u, [r%u], #%c%u\n",
18502 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm8
);
18503 goto decode_success
;
18507 /* -------------- (A2) LDRSBT reg+/-reg -------------- */
18508 /* Load Register Signed Byte Unprivileged:
18509 ldrsbt<c> Rt, [Rn], +/-Rm
18511 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,0,1,1)
18512 && INSN(11,4) == BITS8(0,0,0,0,1,1,0,1)) {
18513 UInt rT
= INSN(15,12);
18514 UInt rN
= INSN(19,16);
18515 UInt bU
= INSN(23,23);
18516 UInt rM
= INSN(3,0);
18518 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15)
18521 IRTemp newRt
= newTemp(Ity_I32
);
18522 loadGuardedLE( newRt
,
18523 ILGop_8Sto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18524 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18525 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18526 getIRegA(rN
), getIRegA(rM
));
18527 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18528 DIP("ldrsbt%s r%u, [r%u], %cr%u\n",
18529 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', rM
);
18530 goto decode_success
;
18534 /* -------------- (A1) STRBT reg+#imm12 -------------- */
18535 /* Store Register Byte Unprivileged:
18536 strbt<c> Rt, [Rn], #+/-imm12
18538 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,0,0,0,1,1,0) ) {
18539 UInt rT
= INSN(15,12);
18540 UInt rN
= INSN(19,16);
18541 UInt imm12
= INSN(11,0);
18542 UInt bU
= INSN(23,23);
18544 if (rT
== 15 || rN
== 15 || rN
== rT
) valid
= False
;
18546 IRExpr
* address
= getIRegA(rN
);
18547 IRExpr
* data
= unop(Iop_32to8
, getIRegA(rT
));
18548 storeGuardedLE( address
, data
, condT
);
18549 IRExpr
* newRn
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18550 getIRegA(rN
), mkU32(imm12
));
18551 putIRegA(rN
, newRn
, condT
, Ijk_Boring
);
18552 DIP("strbt%s r%u, [r%u], #%c%u\n",
18553 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm12
);
18554 goto decode_success
;
18558 /* -------------- (A2) STRBT reg+/-reg -------------- */
18559 /* Store Register Byte Unprivileged:
18560 strbt<c> Rt, [Rn], +/-Rm{, shift}
18562 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,1,0,0,1,1,0)
18563 && INSN(4,4) == 0) {
18564 UInt rT
= INSN(15,12);
18565 UInt rN
= INSN(19,16);
18566 UInt imm5
= INSN(11,7);
18567 UInt type
= INSN(6,5);
18568 UInt rM
= INSN(3,0);
18569 UInt bU
= INSN(23,23);
18571 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15) valid
= False
;
18573 IRExpr
* address
= getIRegA(rN
);
18574 IRExpr
* data
= unop(Iop_32to8
, getIRegA(rT
));
18575 storeGuardedLE( address
, data
, condT
);
18576 // dis_buf generated is slightly bogus, in fact.
18577 IRExpr
* erN
= mk_EA_reg_plusminus_shifted_reg(rN
, bU
, rM
,
18578 type
, imm5
, dis_buf
);
18579 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18580 DIP("strbt%s r%u, %s\n", nCC(INSN_COND
), rT
, dis_buf
);
18581 goto decode_success
;
18585 /* -------------- (A1) STRHT reg+#imm8 -------------- */
18586 /* Store Register Halfword Unprivileged:
18587 strht<c> Rt, [Rn], #+/-imm8
18589 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,1,1,0)
18590 && INSN(7,4) == BITS4(1,0,1,1) ) {
18591 UInt rT
= INSN(15,12);
18592 UInt rN
= INSN(19,16);
18593 UInt imm4H
= INSN(11,8);
18594 UInt imm4L
= INSN(3,0);
18595 UInt imm8
= (imm4H
<< 4) | imm4L
;
18596 UInt bU
= INSN(23,23);
18598 if (rT
== 15 || rN
== 15 || rN
== rT
) valid
= False
;
18600 IRExpr
* address
= getIRegA(rN
);
18601 IRExpr
* data
= unop(Iop_32to16
, getIRegA(rT
));
18602 storeGuardedLE( address
, data
, condT
);
18603 IRExpr
* newRn
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18604 getIRegA(rN
), mkU32(imm8
));
18605 putIRegA(rN
, newRn
, condT
, Ijk_Boring
);
18606 DIP("strht%s r%u, [r%u], #%c%u\n",
18607 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm8
);
18608 goto decode_success
;
18612 /* -------------- (A2) STRHT reg+reg -------------- */
18613 /* Store Register Halfword Unprivileged:
18614 strht<c> Rt, [Rn], +/-Rm
18616 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,0,1,0)
18617 && INSN(11,4) == BITS8(0,0,0,0,1,0,1,1) ) {
18618 UInt rT
= INSN(15,12);
18619 UInt rN
= INSN(19,16);
18620 UInt rM
= INSN(3,0);
18621 UInt bU
= INSN(23,23);
18623 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15) valid
= False
;
18625 IRExpr
* address
= getIRegA(rN
);
18626 IRExpr
* data
= unop(Iop_32to16
, getIRegA(rT
));
18627 storeGuardedLE( address
, data
, condT
);
18628 IRExpr
* newRn
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18629 getIRegA(rN
), getIRegA(rM
));
18630 putIRegA(rN
, newRn
, condT
, Ijk_Boring
);
18631 DIP("strht%s r%u, [r%u], %cr%u\n",
18632 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', rM
);
18633 goto decode_success
;
18637 /* -------------- (A1) STRT reg+imm12 -------------- */
18638 /* Store Register Unprivileged:
18639 strt<c> Rt, [Rn], #+/-imm12
18641 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,0,0,0,0,1,0) ) {
18642 UInt rT
= INSN(15,12);
18643 UInt rN
= INSN(19,16);
18644 UInt imm12
= INSN(11,0);
18645 UInt bU
= INSN(23,23);
18647 if (rN
== 15 || rN
== rT
) valid
= False
;
18649 IRExpr
* address
= getIRegA(rN
);
18650 storeGuardedLE( address
, getIRegA(rT
), condT
);
18651 IRExpr
* newRn
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18652 getIRegA(rN
), mkU32(imm12
));
18653 putIRegA(rN
, newRn
, condT
, Ijk_Boring
);
18654 DIP("strt%s r%u, [r%u], %c%u\n",
18655 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm12
);
18656 goto decode_success
;
18660 /* -------------- (A2) STRT reg+reg -------------- */
18661 /* Store Register Unprivileged:
18662 strt<c> Rt, [Rn], +/-Rm{, shift}
18664 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,1,0,0,0,1,0)
18665 && INSN(4,4) == 0 ) {
18666 UInt rT
= INSN(15,12);
18667 UInt rN
= INSN(19,16);
18668 UInt rM
= INSN(3,0);
18669 UInt type
= INSN(6,5);
18670 UInt imm5
= INSN(11,7);
18671 UInt bU
= INSN(23,23);
18673 if (rN
== 15 || rN
== rT
|| rM
== 15) valid
= False
;
18674 /* FIXME We didn't do:
18675 if ArchVersion() < 6 && rM == rN then UNPREDICTABLE */
18677 storeGuardedLE( getIRegA(rN
), getIRegA(rT
), condT
);
18678 // dis_buf generated is slightly bogus, in fact.
18679 IRExpr
* erN
= mk_EA_reg_plusminus_shifted_reg(rN
, bU
, rM
,
18680 type
, imm5
, dis_buf
);
18681 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18682 DIP("strt%s r%u, %s\n", nCC(INSN_COND
), rT
, dis_buf
);
18683 goto decode_success
;
18687 /* ----------------------------------------------------------- */
18688 /* -- ARMv7 instructions -- */
18689 /* ----------------------------------------------------------- */
18691 /* -------------- read CP15 TPIDRURO register ------------- */
18692 /* mrc p15, 0, r0, c13, c0, 3 up to
18693 mrc p15, 0, r14, c13, c0, 3
18695 /* I don't know whether this is really v7-only. But anyway, we
18696 have to support it since arm-linux uses TPIDRURO as a thread
18698 if (0x0E1D0F70 == (insn
& 0x0FFF0FFF)) {
18699 UInt rD
= INSN(15,12);
18701 /* skip r15, that's too stupid to handle */
18702 putIRegA(rD
, IRExpr_Get(OFFB_TPIDRURO
, Ity_I32
),
18703 condT
, Ijk_Boring
);
18704 DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND
), rD
);
18705 goto decode_success
;
18710 /* ------------ read/write CP15 TPIDRURW register ----------- */
18711 /* mcr p15, 0, r0, c13, c0, 2 (r->cr xfer) up to
18712 mcr p15, 0, r14, c13, c0, 2
18714 mrc p15, 0, r0, c13, c0, 2 (rc->r xfer) up to
18715 mrc p15, 0, r14, c13, c0, 2
18717 if (0x0E0D0F50 == (insn
& 0x0FFF0FFF)) { // MCR
18718 UInt rS
= INSN(15,12);
18720 /* skip r15, that's too stupid to handle */
18721 putMiscReg32(OFFB_TPIDRURW
, getIRegA(rS
), condT
);
18722 DIP("mcr%s p15,0, r%u, c13, c0, 2\n", nCC(INSN_COND
), rS
);
18723 goto decode_success
;
18727 if (0x0E1D0F50 == (insn
& 0x0FFF0FFF)) { // MRC
18728 UInt rD
= INSN(15,12);
18730 /* skip r15, that's too stupid to handle */
18731 putIRegA(rD
, IRExpr_Get(OFFB_TPIDRURW
, Ity_I32
),
18732 condT
, Ijk_Boring
);
18733 DIP("mrc%s p15,0, r%u, c13, c0, 2\n", nCC(INSN_COND
), rD
);
18734 goto decode_success
;
18739 /* -------------- read CP15 PMUSRENR register ------------- */
18740 /* mrc p15, 0, r0, c9, c14, 0 up to
18741 mrc p15, 0, r14, c9, c14, 0
18743 /* A program reading this register is really asking "which
18744 performance monitoring registes are available in user space?
18745 The simple answer here is to return zero, meaning "none". See
18747 if (0x0E190F1E == (insn
& 0x0FFF0FFF)) {
18748 UInt rD
= INSN(15,12);
18750 /* skip r15, that's too stupid to handle */
18751 putIRegA(rD
, mkU32(0), condT
, Ijk_Boring
);
18752 DIP("mrc%s p15,0, r%u, c9, c14, 0\n", nCC(INSN_COND
), rD
);
18753 goto decode_success
;
18758 /* Handle various kinds of barriers. This is rather indiscriminate
18759 in the sense that they are all turned into an IR Fence, which
18760 means we don't know which they are, so the back end has to
18761 re-emit them all when it comes acrosss an IR Fence.
18763 /* v6 */ /* mcr 15, 0, rT, c7, c10, 5 */
18764 if (0xEE070FBA == (insn
& 0xFFFF0FFF)) {
18765 UInt rT
= INSN(15,12);
18767 /* mcr 15, 0, rT, c7, c10, 5 (v6) equiv to DMB (v7). Data
18768 Memory Barrier -- ensures ordering of memory accesses. */
18769 stmt( IRStmt_MBE(Imbe_Fence
) );
18770 DIP("mcr 15, 0, r%u, c7, c10, 5 (data memory barrier)\n", rT
);
18771 goto decode_success
;
18775 /* other flavours of barrier */
18777 case 0xEE070F9A: /* v6 */
18778 /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7). Data
18779 Synch Barrier -- ensures completion of memory accesses. */
18780 stmt( IRStmt_MBE(Imbe_Fence
) );
18781 DIP("mcr 15, 0, r0, c7, c10, 4 (data synch barrier)\n");
18782 goto decode_success
;
18783 case 0xEE070F95: /* v6 */
18784 /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7).
18785 Instruction Synchronisation Barrier (or Flush Prefetch
18786 Buffer) -- a pipe flush, I think. I suspect we could
18787 ignore those, but to be on the safe side emit a fence
18789 stmt( IRStmt_MBE(Imbe_Fence
) );
18790 DIP("mcr 15, 0, r0, c7, c5, 4 (insn synch barrier)\n");
18791 goto decode_success
;
18796 /* ----------------------------------------------------------- */
18798 /* ----------------------------------------------------------- */
18800 switch (insn
& 0x0FFFFFFF) {
18801 /* ------------------- NOP ------------------ */
18803 DIP("nop%s\n", nCC(INSN_COND
));
18804 goto decode_success
;
18805 /* ------------------- YIELD ------------------ */
18807 /* Continue after conditionally yielding. */
18808 DIP("yield%s\n", nCC(INSN_COND
));
18809 stmt( IRStmt_Exit( unop(Iop_32to1
,
18810 condT
== IRTemp_INVALID
18811 ? mkU32(1) : mkexpr(condT
)),
18813 IRConst_U32(guest_R15_curr_instr_notENC
+ 4),
18815 goto decode_success
;
18820 /* ----------------------------------------------------------- */
18821 /* -- VFP (CP 10, CP 11) instructions (in ARM mode) -- */
18822 /* ----------------------------------------------------------- */
18824 if (INSN_COND
!= ARMCondNV
) {
18825 Bool ok_vfp
= decode_CP10_CP11_instruction (
18826 &dres
, INSN(27,0), condT
, INSN_COND
,
18830 goto decode_success
;
18833 /* ----------------------------------------------------------- */
18834 /* -- NEON instructions (in ARM mode) -- */
18835 /* ----------------------------------------------------------- */
18837 /* These are all in NV space, and so are taken care of (far) above,
18838 by a call from this function to
18839 decode_NV_instruction_ARMv7_and_below(). */
18841 /* ----------------------------------------------------------- */
18842 /* -- v6 media instructions (in ARM mode) -- */
18843 /* ----------------------------------------------------------- */
18845 { Bool ok_v6m
= decode_V6MEDIA_instruction(
18846 &dres
, INSN(27,0), condT
, INSN_COND
,
18850 goto decode_success
;
18853 /* ----------------------------------------------------------- */
18854 /* -- v8 instructions (in ARM mode) -- */
18855 /* ----------------------------------------------------------- */
18859 /* If we get here, it means that all attempts to decode the
18860 instruction as ARMv7 or earlier have failed. So, if we're doing
18861 ARMv8 or later, here is the point to try for it. */
18863 if (VEX_ARM_ARCHLEVEL(archinfo
->hwcaps
) >= 8) {
18865 = decode_V8_instruction( &dres
, insn
, condT
, False
/*!isT*/,
18866 IRTemp_INVALID
, IRTemp_INVALID
);
18868 goto decode_success
;
18871 /* ----------------------------------------------------------- */
18872 /* -- Undecodable -- */
18873 /* ----------------------------------------------------------- */
18875 goto decode_failure
;
18879 /* All decode failures end up here. */
18881 vex_printf("disInstr(arm): unhandled instruction: "
18883 vex_printf(" cond=%d(0x%x) 27:20=%d(0x%02x) "
18886 (Int
)INSN_COND
, (UInt
)INSN_COND
,
18887 (Int
)INSN(27,20), (UInt
)INSN(27,20),
18889 (Int
)INSN(3,0), (UInt
)INSN(3,0) );
18892 /* Tell the dispatcher that this insn cannot be decoded, and so has
18893 not been executed, and (is currently) the next to be executed.
18894 R15 should be up-to-date since it made so at the start of each
18895 insn, but nevertheless be paranoid and update it again right
18897 vassert(0 == (guest_R15_curr_instr_notENC
& 3));
18898 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC
) );
18900 dres
.whatNext
= Dis_StopHere
;
18901 dres
.jk_StopHere
= Ijk_NoDecode
;
18902 dres
.continueAt
= 0;
18906 /* All decode successes end up here. */
18909 vassert(dres
.len
== 4 || dres
.len
== 20);
18911 /* Now then. Do we have an implicit jump to r15 to deal with? */
18913 /* If we get jump to deal with, we assume that there's been no
18914 other competing branch stuff previously generated for this
18915 insn. That's reasonable, in the sense that the ARM insn set
18916 appears to declare as "Unpredictable" any instruction which
18917 generates more than one possible new value for r15. Hence
18918 just assert. The decoders themselves should check against
18919 all such instructions which are thusly Unpredictable, and
18920 decline to decode them. Hence we should never get here if we
18921 have competing new values for r15, and hence it is safe to
18923 vassert(dres
.whatNext
== Dis_Continue
);
18924 vassert(irsb
->next
== NULL
);
18925 vassert(irsb
->jumpkind
== Ijk_Boring
);
18926 /* If r15 is unconditionally written, terminate the block by
18927 jumping to it. If it's conditionally written, still
18928 terminate the block (a shame, but we can't do side exits to
18929 arbitrary destinations), but first jump to the next
18930 instruction if the condition doesn't hold. */
18931 /* We can't use getIReg(15) to get the destination, since that
18932 will produce r15+8, which isn't what we want. Must use
18933 llGetIReg(15) instead. */
18934 if (r15guard
== IRTemp_INVALID
) {
18935 /* unconditional */
18941 mkexpr(r15guard
), mkU32(1))),
18943 IRConst_U32(guest_R15_curr_instr_notENC
+ 4),
18947 /* This seems crazy, but we're required to finish the insn with
18948 a write to the guest PC. As usual we rely on ir_opt to tidy
18950 llPutIReg(15, llGetIReg(15));
18951 dres
.whatNext
= Dis_StopHere
;
18952 dres
.jk_StopHere
= r15kind
;
18954 /* Set up the end-state in the normal way. */
18955 switch (dres
.whatNext
) {
18957 llPutIReg(15, mkU32(dres
.len
+ guest_R15_curr_instr_notENC
));
18961 llPutIReg(15, mkU32(dres
.continueAt
));
18977 /*------------------------------------------------------------*/
18978 /*--- Disassemble a single Thumb2 instruction ---*/
18979 /*------------------------------------------------------------*/
18981 static const UChar it_length_table
[256]; /* fwds */
18983 /* NB: in Thumb mode we do fetches of regs with getIRegT, which
18984 automagically adds 4 to fetches of r15. However, writes to regs
18985 are done with putIRegT, which disallows writes to r15. Hence any
18986 r15 writes and associated jumps have to be done "by hand". */
18988 /* Disassemble a single Thumb instruction into IR. The instruction is
18989 located in host memory at guest_instr, and has (decoded) guest IP
18990 of guest_R15_curr_instr_notENC, which will have been set before the
18994 DisResult
disInstr_THUMB_WRK (
18995 Bool (*resteerOkFn
) ( /*opaque*/void*, Addr
),
18997 void* callback_opaque
,
18998 const UChar
* guest_instr
,
18999 const VexArchInfo
* archinfo
,
19000 const VexAbiInfo
* abiinfo
,
19004 /* A macro to fish bits out of insn0. There's also INSN1, to fish
19005 bits out of insn1, but that's defined only after the end of the
19006 16-bit insn decoder, so as to stop it mistakenly being used
19008 # define INSN0(_bMax,_bMin) SLICE_UInt(((UInt)insn0), (_bMax), (_bMin))
19011 UShort insn0
; /* first 16 bits of the insn */
19012 UShort insn1
; /* second 16 bits of the insn */
19013 HChar dis_buf
[128]; // big enough to hold LDMIA etc text
19015 /* Summary result of the ITxxx backwards analysis: False == safe
19017 Bool guaranteedUnconditional
= False
;
19019 /* Set result defaults. */
19020 dres
.whatNext
= Dis_Continue
;
19022 dres
.continueAt
= 0;
19023 dres
.jk_StopHere
= Ijk_INVALID
;
19024 dres
.hint
= Dis_HintNone
;
19026 /* Set default actions for post-insn handling of writes to r15, if
19028 r15written
= False
;
19029 r15guard
= IRTemp_INVALID
; /* unconditional */
19030 r15kind
= Ijk_Boring
;
19032 /* Insns could be 2 or 4 bytes long. Just get the first 16 bits at
19033 this point. If we need the second 16, get them later. We can't
19034 get them both out immediately because it risks a fault (very
19035 unlikely, but ..) if the second 16 bits aren't actually
19037 insn0
= getUShortLittleEndianly( guest_instr
);
19038 insn1
= 0; /* We'll get it later, once we know we need it. */
19040 /* Similarly, will set this later. */
19041 IRTemp old_itstate
= IRTemp_INVALID
;
19043 if (0) vex_printf("insn: 0x%x\n", insn0
);
19045 DIP("\t(thumb) 0x%x: ", (UInt
)guest_R15_curr_instr_notENC
);
19047 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
19049 /* ----------------------------------------------------------- */
19050 /* Spot "Special" instructions (see comment at top of file). */
19052 const UChar
* code
= guest_instr
;
19053 /* Spot the 16-byte preamble:
19055 ea4f 0cfc mov.w ip, ip, ror #3
19056 ea4f 3c7c mov.w ip, ip, ror #13
19057 ea4f 7c7c mov.w ip, ip, ror #29
19058 ea4f 4cfc mov.w ip, ip, ror #19
19060 UInt word1
= 0x0CFCEA4F;
19061 UInt word2
= 0x3C7CEA4F;
19062 UInt word3
= 0x7C7CEA4F;
19063 UInt word4
= 0x4CFCEA4F;
19064 if (getUIntLittleEndianly(code
+ 0) == word1
&&
19065 getUIntLittleEndianly(code
+ 4) == word2
&&
19066 getUIntLittleEndianly(code
+ 8) == word3
&&
19067 getUIntLittleEndianly(code
+12) == word4
) {
19068 /* Got a "Special" instruction preamble. Which one is it? */
19070 if (getUIntLittleEndianly(code
+16) == 0x0A0AEA4A
19071 /* orr.w r10,r10,r10 */) {
19072 /* R3 = client_request ( R4 ) */
19073 DIP("r3 = client_request ( %%r4 )\n");
19074 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC
+ 20) | 1 ));
19075 dres
.jk_StopHere
= Ijk_ClientReq
;
19076 dres
.whatNext
= Dis_StopHere
;
19077 goto decode_success
;
19081 if (getUIntLittleEndianly(code
+16) == 0x0B0BEA4B
19082 /* orr r11,r11,r11 */) {
19083 /* R3 = guest_NRADDR */
19084 DIP("r3 = guest_NRADDR\n");
19086 llPutIReg(3, IRExpr_Get( OFFB_NRADDR
, Ity_I32
));
19087 goto decode_success
;
19091 if (getUIntLittleEndianly(code
+16) == 0x0C0CEA4C
19092 /* orr r12,r12,r12 */) {
19093 /* branch-and-link-to-noredir R4 */
19094 DIP("branch-and-link-to-noredir r4\n");
19095 llPutIReg(14, mkU32( (guest_R15_curr_instr_notENC
+ 20) | 1 ));
19096 llPutIReg(15, getIRegT(4));
19097 dres
.jk_StopHere
= Ijk_NoRedir
;
19098 dres
.whatNext
= Dis_StopHere
;
19099 goto decode_success
;
19103 if (getUIntLittleEndianly(code
+16) == 0x0909EA49
19104 /* orr r9,r9,r9 */) {
19106 DIP("IR injection\n");
19107 vex_inject_ir(irsb
, Iend_LE
);
19108 // Invalidate the current insn. The reason is that the IRop we're
19109 // injecting here can change. In which case the translation has to
19110 // be redone. For ease of handling, we simply invalidate all the
19112 stmt(IRStmt_Put(OFFB_CMSTART
, mkU32(guest_R15_curr_instr_notENC
)));
19113 stmt(IRStmt_Put(OFFB_CMLEN
, mkU32(20)));
19114 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC
+ 20) | 1 ));
19115 dres
.whatNext
= Dis_StopHere
;
19116 dres
.jk_StopHere
= Ijk_InvalICache
;
19117 goto decode_success
;
19119 /* We don't know what it is. Set insn0 so decode_failure
19120 can print the insn following the Special-insn preamble. */
19121 insn0
= getUShortLittleEndianly(code
+16);
19122 goto decode_failure
;
19128 /* ----------------------------------------------------------- */
19130 /* Main Thumb instruction decoder starts here. It's a series of
19131 switches which examine ever longer bit sequences at the MSB of
19132 the instruction word, first for 16-bit insns, then for 32-bit
19135 /* --- BEGIN ITxxx optimisation analysis --- */
19136 /* This is a crucial optimisation for the ITState boilerplate that
19137 follows. Examine the 9 halfwords preceding this instruction,
19138 and if we are absolutely sure that none of them constitute an
19139 'it' instruction, then we can be sure that this instruction is
19140 not under the control of any 'it' instruction, and so
19141 guest_ITSTATE must be zero. So write zero into ITSTATE right
19142 now, so that iropt can fold out almost all of the resulting
19145 If we aren't sure, we can always safely skip this step. So be a
19146 bit conservative about it: only poke around in the same page as
19147 this instruction, lest we get a fault from the previous page
19148 that would not otherwise have happened. The saving grace is
19149 that such skipping is pretty rare -- it only happens,
19150 statistically, 18/4096ths of the time, so is judged unlikely to
19151 be a performance problems.
19153 FIXME: do better. Take into account the number of insns covered
19154 by any IT insns we find, to rule out cases where an IT clearly
19155 cannot cover this instruction. This would improve behaviour for
19156 branch targets immediately following an IT-guarded group that is
19157 not of full length. Eg, (and completely ignoring issues of 16-
19158 vs 32-bit insn length):
19166 The 'it' only conditionalises insn1 and insn2. However, the
19167 current analysis is conservative and considers insn3 and insn4
19168 also possibly guarded. Hence if 'label:' is the start of a hot
19169 loop we will get a big performance hit.
19172 /* Summary result of this analysis: False == safe but
19174 vassert(guaranteedUnconditional
== False
);
19176 UInt pc
= guest_R15_curr_instr_notENC
;
19177 vassert(0 == (pc
& 1));
19179 UInt pageoff
= pc
& 0xFFF;
19180 if (pageoff
>= 18) {
19181 /* It's safe to poke about in the 9 halfwords preceding this
19182 insn. So, have a look at them. */
19183 guaranteedUnconditional
= True
; /* assume no 'it' insn found,
19185 UShort
* hwp
= (UShort
*)(HWord
)pc
;
19187 for (i
= -1; i
>= -9; i
--) {
19188 /* We're in the same page. (True, but commented out due
19191 vassert( ( ((UInt)(&hwp[i])) & 0xFFFFF000 )
19192 == ( pc & 0xFFFFF000 ) );
19194 /* All valid IT instructions must have the form 0xBFxy,
19195 where x can be anything, but y must be nonzero. Find
19196 the number of insns covered by it (1 .. 4) and check to
19197 see if it can possibly reach up to the instruction in
19198 question. Some (x,y) combinations mean UNPREDICTABLE,
19199 and the table is constructed to be conservative by
19200 returning 4 for those cases, so the analysis is safe
19201 even if the code uses unpredictable IT instructions (in
19202 which case its authors are nuts, but hey.) */
19203 UShort hwp_i
= hwp
[i
];
19204 if (UNLIKELY((hwp_i
& 0xFF00) == 0xBF00 && (hwp_i
& 0xF) != 0)) {
19205 /* might be an 'it' insn. */
19206 /* # guarded insns */
19207 Int n_guarded
= (Int
)it_length_table
[hwp_i
& 0xFF];
19208 vassert(n_guarded
>= 1 && n_guarded
<= 4);
19209 if (n_guarded
* 2 /* # guarded HWs, worst case */
19210 > (-(i
+1))) /* -(i+1): # remaining HWs after the IT */
19211 /* -(i+0) also seems to work, even though I think
19212 it's wrong. I don't understand that. */
19213 guaranteedUnconditional
= False
;
19219 /* --- END ITxxx optimisation analysis --- */
19221 /* Generate the guarding condition for this insn, by examining
19222 ITSTATE. Assign it to condT. Also, generate new
19223 values for ITSTATE ready for stuffing back into the
19224 guest state, but don't actually do the Put yet, since it will
19225 need to stuffed back in only after the instruction gets to a
19226 point where it is sure to complete. Mostly we let the code at
19227 decode_success handle this, but in cases where the insn contains
19228 a side exit, we have to update them before the exit. */
19230 /* If the ITxxx optimisation analysis above could not prove that
19231 this instruction is guaranteed unconditional, we insert a
19232 lengthy IR preamble to compute the guarding condition at
19233 runtime. If it can prove it (which obviously we hope is the
19234 normal case) then we insert a minimal preamble, which is
19235 equivalent to setting guest_ITSTATE to zero and then folding
19236 that through the full preamble (which completely disappears). */
19238 IRTemp condT
= IRTemp_INVALID
;
19239 IRTemp cond_AND_notInIT_T
= IRTemp_INVALID
;
19241 IRTemp new_itstate
= IRTemp_INVALID
;
19242 vassert(old_itstate
== IRTemp_INVALID
);
19244 if (guaranteedUnconditional
) {
19245 /* BEGIN "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
19247 // ITSTATE = 0 :: I32
19248 IRTemp z32
= newTemp(Ity_I32
);
19249 assign(z32
, mkU32(0));
19252 // old_itstate = 0 :: I32
19254 // old_itstate = get_ITSTATE();
19255 old_itstate
= z32
; /* 0 :: I32 */
19257 // new_itstate = old_itstate >> 8
19261 // new_itstate = newTemp(Ity_I32);
19262 // assign(new_itstate,
19263 // binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
19266 // ITSTATE = 0 :: I32(again)
19268 // put_ITSTATE(new_itstate);
19270 // condT1 = calc_cond_dyn( xor(and(old_istate,0xF0), 0xE0) )
19271 // = calc_cond_dyn( xor(0,0xE0) )
19272 // = calc_cond_dyn ( 0xE0 )
19274 // Not that this matters, since the computed value is not used:
19275 // see condT folding below
19277 // IRTemp condT1 = newTemp(Ity_I32);
19279 // mk_armg_calculate_condition_dyn(
19280 // binop(Iop_Xor32,
19281 // binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
19286 // condT = 32to8(and32(old_itstate,0xF0)) == 0 ? 1 : condT1
19287 // = 32to8(and32(0,0xF0)) == 0 ? 1 : condT1
19288 // = 32to8(0) == 0 ? 1 : condT1
19289 // = 0 == 0 ? 1 : condT1
19292 // condT = newTemp(Ity_I32);
19293 // assign(condT, IRExpr_ITE(
19294 // unop(Iop_32to8, binop(Iop_And32,
19295 // mkexpr(old_itstate),
19300 condT
= newTemp(Ity_I32
);
19301 assign(condT
, mkU32(1));
19303 // notInITt = xor32(and32(old_itstate, 1), 1)
19304 // = xor32(and32(0, 1), 1)
19308 // IRTemp notInITt = newTemp(Ity_I32);
19309 // assign(notInITt,
19310 // binop(Iop_Xor32,
19311 // binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
19314 // cond_AND_notInIT_T = and32(notInITt, condT)
19318 // cond_AND_notInIT_T = newTemp(Ity_I32);
19319 // assign(cond_AND_notInIT_T,
19320 // binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
19321 cond_AND_notInIT_T
= condT
; /* 1 :: I32 */
19323 /* END "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
19325 /* BEGIN { STANDARD PREAMBLE; } */
19327 old_itstate
= get_ITSTATE();
19329 new_itstate
= newTemp(Ity_I32
);
19330 assign(new_itstate
,
19331 binop(Iop_Shr32
, mkexpr(old_itstate
), mkU8(8)));
19333 put_ITSTATE(new_itstate
);
19335 /* Same strategy as for ARM insns: generate a condition
19336 temporary at this point (or IRTemp_INVALID, meaning
19337 unconditional). We leave it to lower-level instruction
19338 decoders to decide whether they can generate straight-line
19339 code, or whether they must generate a side exit before the
19340 instruction. condT :: Ity_I32 and is always either zero or
19342 IRTemp condT1
= newTemp(Ity_I32
);
19344 mk_armg_calculate_condition_dyn(
19346 binop(Iop_And32
, mkexpr(old_itstate
), mkU32(0xF0)),
19351 /* This is a bit complex, but needed to make Memcheck understand
19352 that, if the condition in old_itstate[7:4] denotes AL (that
19353 is, if this instruction is to be executed unconditionally),
19354 then condT does not depend on the results of calling the
19357 We test explicitly for old_itstate[7:4] == AL ^ 0xE, and in
19358 that case set condT directly to 1. Else we use the results
19359 of the helper. Since old_itstate is always defined and
19360 because Memcheck does lazy V-bit propagation through ITE,
19361 this will cause condT to always be a defined 1 if the
19362 condition is 'AL'. From an execution semantics point of view
19363 this is irrelevant since we're merely duplicating part of the
19364 behaviour of the helper. But it makes it clear to Memcheck,
19365 in this case, that condT does not in fact depend on the
19366 contents of the condition code thunk. Without it, we get
19367 quite a lot of false errors.
19369 So, just to clarify: from a straight semantics point of view,
19370 we can simply do "assign(condT, mkexpr(condT1))", and the
19371 simulator still runs fine. It's just that we get loads of
19372 false errors from Memcheck. */
19373 condT
= newTemp(Ity_I32
);
19374 assign(condT
, IRExpr_ITE(
19375 binop(Iop_CmpNE32
, binop(Iop_And32
,
19376 mkexpr(old_itstate
),
19383 /* Something we don't have in ARM: generate a 0 or 1 value
19384 indicating whether or not we are in an IT block (NB: 0 = in
19385 IT block, 1 = not in IT block). This is used to gate
19386 condition code updates in 16-bit Thumb instructions. */
19387 IRTemp notInITt
= newTemp(Ity_I32
);
19390 binop(Iop_And32
, mkexpr(old_itstate
), mkU32(1)),
19393 /* Compute 'condT && notInITt' -- that is, the instruction is
19394 going to execute, and we're not in an IT block. This is the
19395 gating condition for updating condition codes in 16-bit Thumb
19396 instructions, except for CMP, CMN and TST. */
19397 cond_AND_notInIT_T
= newTemp(Ity_I32
);
19398 assign(cond_AND_notInIT_T
,
19399 binop(Iop_And32
, mkexpr(notInITt
), mkexpr(condT
)));
19400 /* END { STANDARD PREAMBLE; } */
19405 * ITSTATE has been updated
19406 * condT holds the guarding condition for this instruction (0 or 1),
19407 * notInITt is 1 if we're in "normal" code, 0 if in an IT block
19408 * cond_AND_notInIT_T is the AND of the above two.
19410 If the instruction proper can't trap, then there's nothing else
19411 to do w.r.t. ITSTATE -- just go and and generate IR for the
19412 insn, taking into account the guarding condition.
19414 If, however, the instruction might trap, then we must back up
19415 ITSTATE to the old value, and re-update it after the potentially
19416 trapping IR section. A trap can happen either via a memory
19417 reference or because we need to throw SIGILL.
19419 If an instruction has a side exit, we need to be sure that any
19420 ITSTATE backup is re-updated before the side exit.
19423 /* ----------------------------------------------------------- */
19425 /* -- Thumb 16-bit integer instructions -- */
19427 /* -- IMPORTANT: references to insn1 or INSN1 are -- */
19428 /* -- not allowed in this section -- */
19430 /* ----------------------------------------------------------- */
19432 /* 16-bit instructions inside an IT block, apart from CMP, CMN and
19433 TST, do not set the condition codes. Hence we must dynamically
19434 test for this case for every condition code update. */
19436 IROp anOp
= Iop_INVALID
;
19437 const HChar
* anOpNm
= NULL
;
19439 /* ================ 16-bit 15:6 cases ================ */
19441 switch (INSN0(15,6)) {
19444 case 0x10b: { // CMN
19445 /* ---------------- CMP Rn, Rm ---------------- */
19446 Bool isCMN
= INSN0(15,6) == 0x10b;
19447 UInt rN
= INSN0(2,0);
19448 UInt rM
= INSN0(5,3);
19449 IRTemp argL
= newTemp(Ity_I32
);
19450 IRTemp argR
= newTemp(Ity_I32
);
19451 assign( argL
, getIRegT(rN
) );
19452 assign( argR
, getIRegT(rM
) );
19453 /* Update flags regardless of whether in an IT block or not. */
19454 setFlags_D1_D2( isCMN
? ARMG_CC_OP_ADD
: ARMG_CC_OP_SUB
,
19455 argL
, argR
, condT
);
19456 DIP("%s r%u, r%u\n", isCMN
? "cmn" : "cmp", rN
, rM
);
19457 goto decode_success
;
19461 /* ---------------- TST Rn, Rm ---------------- */
19462 UInt rN
= INSN0(2,0);
19463 UInt rM
= INSN0(5,3);
19464 IRTemp oldC
= newTemp(Ity_I32
);
19465 IRTemp oldV
= newTemp(Ity_I32
);
19466 IRTemp res
= newTemp(Ity_I32
);
19467 assign( oldC
, mk_armg_calculate_flag_c() );
19468 assign( oldV
, mk_armg_calculate_flag_v() );
19469 assign( res
, binop(Iop_And32
, getIRegT(rN
), getIRegT(rM
)) );
19470 /* Update flags regardless of whether in an IT block or not. */
19471 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
, condT
);
19472 DIP("tst r%u, r%u\n", rN
, rM
);
19473 goto decode_success
;
19477 /* ---------------- NEGS Rd, Rm ---------------- */
19479 UInt rM
= INSN0(5,3);
19480 UInt rD
= INSN0(2,0);
19481 IRTemp arg
= newTemp(Ity_I32
);
19482 IRTemp zero
= newTemp(Ity_I32
);
19483 assign(arg
, getIRegT(rM
));
19484 assign(zero
, mkU32(0));
19485 // rD can never be r15
19486 putIRegT(rD
, binop(Iop_Sub32
, mkexpr(zero
), mkexpr(arg
)), condT
);
19487 setFlags_D1_D2( ARMG_CC_OP_SUB
, zero
, arg
, cond_AND_notInIT_T
);
19488 DIP("negs r%u, r%u\n", rD
, rM
);
19489 goto decode_success
;
19493 /* ---------------- MVNS Rd, Rm ---------------- */
19495 UInt rM
= INSN0(5,3);
19496 UInt rD
= INSN0(2,0);
19497 IRTemp oldV
= newTemp(Ity_I32
);
19498 IRTemp oldC
= newTemp(Ity_I32
);
19499 IRTemp res
= newTemp(Ity_I32
);
19500 assign( oldV
, mk_armg_calculate_flag_v() );
19501 assign( oldC
, mk_armg_calculate_flag_c() );
19502 assign(res
, unop(Iop_Not32
, getIRegT(rM
)));
19503 // rD can never be r15
19504 putIRegT(rD
, mkexpr(res
), condT
);
19505 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
19506 cond_AND_notInIT_T
);
19507 DIP("mvns r%u, r%u\n", rD
, rM
);
19508 goto decode_success
;
19512 /* ---------------- ORRS Rd, Rm ---------------- */
19513 anOp
= Iop_Or32
; anOpNm
= "orr"; goto and_orr_eor_mul
;
19515 /* ---------------- ANDS Rd, Rm ---------------- */
19516 anOp
= Iop_And32
; anOpNm
= "and"; goto and_orr_eor_mul
;
19518 /* ---------------- EORS Rd, Rm ---------------- */
19519 anOp
= Iop_Xor32
; anOpNm
= "eor"; goto and_orr_eor_mul
;
19521 /* ---------------- MULS Rd, Rm ---------------- */
19522 anOp
= Iop_Mul32
; anOpNm
= "mul"; goto and_orr_eor_mul
;
19524 /* Rd = Rd `op` Rm */
19525 UInt rM
= INSN0(5,3);
19526 UInt rD
= INSN0(2,0);
19527 IRTemp res
= newTemp(Ity_I32
);
19528 IRTemp oldV
= newTemp(Ity_I32
);
19529 IRTemp oldC
= newTemp(Ity_I32
);
19530 assign( oldV
, mk_armg_calculate_flag_v() );
19531 assign( oldC
, mk_armg_calculate_flag_c() );
19532 assign( res
, binop(anOp
, getIRegT(rD
), getIRegT(rM
) ));
19533 // not safe to read guest state after here
19534 // rD can never be r15
19535 putIRegT(rD
, mkexpr(res
), condT
);
19536 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
19537 cond_AND_notInIT_T
);
19538 DIP("%s r%u, r%u\n", anOpNm
, rD
, rM
);
19539 goto decode_success
;
19543 /* ---------------- BICS Rd, Rm ---------------- */
19544 /* Rd = Rd & ~Rm */
19545 UInt rM
= INSN0(5,3);
19546 UInt rD
= INSN0(2,0);
19547 IRTemp res
= newTemp(Ity_I32
);
19548 IRTemp oldV
= newTemp(Ity_I32
);
19549 IRTemp oldC
= newTemp(Ity_I32
);
19550 assign( oldV
, mk_armg_calculate_flag_v() );
19551 assign( oldC
, mk_armg_calculate_flag_c() );
19552 assign( res
, binop(Iop_And32
, getIRegT(rD
),
19553 unop(Iop_Not32
, getIRegT(rM
) )));
19554 // not safe to read guest state after here
19555 // rD can never be r15
19556 putIRegT(rD
, mkexpr(res
), condT
);
19557 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
19558 cond_AND_notInIT_T
);
19559 DIP("bics r%u, r%u\n", rD
, rM
);
19560 goto decode_success
;
19564 /* ---------------- ADCS Rd, Rm ---------------- */
19565 /* Rd = Rd + Rm + oldC */
19566 UInt rM
= INSN0(5,3);
19567 UInt rD
= INSN0(2,0);
19568 IRTemp argL
= newTemp(Ity_I32
);
19569 IRTemp argR
= newTemp(Ity_I32
);
19570 IRTemp oldC
= newTemp(Ity_I32
);
19571 IRTemp res
= newTemp(Ity_I32
);
19572 assign(argL
, getIRegT(rD
));
19573 assign(argR
, getIRegT(rM
));
19574 assign(oldC
, mk_armg_calculate_flag_c());
19575 assign(res
, binop(Iop_Add32
,
19576 binop(Iop_Add32
, mkexpr(argL
), mkexpr(argR
)),
19578 // rD can never be r15
19579 putIRegT(rD
, mkexpr(res
), condT
);
19580 setFlags_D1_D2_ND( ARMG_CC_OP_ADC
, argL
, argR
, oldC
,
19581 cond_AND_notInIT_T
);
19582 DIP("adcs r%u, r%u\n", rD
, rM
);
19583 goto decode_success
;
19587 /* ---------------- SBCS Rd, Rm ---------------- */
19588 /* Rd = Rd - Rm - (oldC ^ 1) */
19589 UInt rM
= INSN0(5,3);
19590 UInt rD
= INSN0(2,0);
19591 IRTemp argL
= newTemp(Ity_I32
);
19592 IRTemp argR
= newTemp(Ity_I32
);
19593 IRTemp oldC
= newTemp(Ity_I32
);
19594 IRTemp res
= newTemp(Ity_I32
);
19595 assign(argL
, getIRegT(rD
));
19596 assign(argR
, getIRegT(rM
));
19597 assign(oldC
, mk_armg_calculate_flag_c());
19598 assign(res
, binop(Iop_Sub32
,
19599 binop(Iop_Sub32
, mkexpr(argL
), mkexpr(argR
)),
19600 binop(Iop_Xor32
, mkexpr(oldC
), mkU32(1))));
19601 // rD can never be r15
19602 putIRegT(rD
, mkexpr(res
), condT
);
19603 setFlags_D1_D2_ND( ARMG_CC_OP_SBB
, argL
, argR
, oldC
,
19604 cond_AND_notInIT_T
);
19605 DIP("sbcs r%u, r%u\n", rD
, rM
);
19606 goto decode_success
;
19610 /* ---------------- UXTB Rd, Rm ---------------- */
19611 /* Rd = 8Uto32(Rm) */
19612 UInt rM
= INSN0(5,3);
19613 UInt rD
= INSN0(2,0);
19614 putIRegT(rD
, binop(Iop_And32
, getIRegT(rM
), mkU32(0xFF)),
19616 DIP("uxtb r%u, r%u\n", rD
, rM
);
19617 goto decode_success
;
19621 /* ---------------- SXTB Rd, Rm ---------------- */
19622 /* Rd = 8Sto32(Rm) */
19623 UInt rM
= INSN0(5,3);
19624 UInt rD
= INSN0(2,0);
19625 putIRegT(rD
, binop(Iop_Sar32
,
19626 binop(Iop_Shl32
, getIRegT(rM
), mkU8(24)),
19629 DIP("sxtb r%u, r%u\n", rD
, rM
);
19630 goto decode_success
;
19634 /* ---------------- UXTH Rd, Rm ---------------- */
19635 /* Rd = 16Uto32(Rm) */
19636 UInt rM
= INSN0(5,3);
19637 UInt rD
= INSN0(2,0);
19638 putIRegT(rD
, binop(Iop_And32
, getIRegT(rM
), mkU32(0xFFFF)),
19640 DIP("uxth r%u, r%u\n", rD
, rM
);
19641 goto decode_success
;
19645 /* ---------------- SXTH Rd, Rm ---------------- */
19646 /* Rd = 16Sto32(Rm) */
19647 UInt rM
= INSN0(5,3);
19648 UInt rD
= INSN0(2,0);
19649 putIRegT(rD
, binop(Iop_Sar32
,
19650 binop(Iop_Shl32
, getIRegT(rM
), mkU8(16)),
19653 DIP("sxth r%u, r%u\n", rD
, rM
);
19654 goto decode_success
;
19657 case 0x102: // LSLS
19658 case 0x103: // LSRS
19659 case 0x104: // ASRS
19660 case 0x107: { // RORS
19661 /* ---------------- LSLS Rs, Rd ---------------- */
19662 /* ---------------- LSRS Rs, Rd ---------------- */
19663 /* ---------------- ASRS Rs, Rd ---------------- */
19664 /* ---------------- RORS Rs, Rd ---------------- */
19665 /* Rd = Rd `op` Rs, and set flags */
19666 UInt rS
= INSN0(5,3);
19667 UInt rD
= INSN0(2,0);
19668 IRTemp oldV
= newTemp(Ity_I32
);
19669 IRTemp rDt
= newTemp(Ity_I32
);
19670 IRTemp rSt
= newTemp(Ity_I32
);
19671 IRTemp res
= newTemp(Ity_I32
);
19672 IRTemp resC
= newTemp(Ity_I32
);
19673 const HChar
* wot
= "???";
19674 assign(rSt
, getIRegT(rS
));
19675 assign(rDt
, getIRegT(rD
));
19676 assign(oldV
, mk_armg_calculate_flag_v());
19677 /* Does not appear to be the standard 'how' encoding. */
19678 switch (INSN0(15,6)) {
19680 compute_result_and_C_after_LSL_by_reg(
19681 dis_buf
, &res
, &resC
, rDt
, rSt
, rD
, rS
19686 compute_result_and_C_after_LSR_by_reg(
19687 dis_buf
, &res
, &resC
, rDt
, rSt
, rD
, rS
19692 compute_result_and_C_after_ASR_by_reg(
19693 dis_buf
, &res
, &resC
, rDt
, rSt
, rD
, rS
19698 compute_result_and_C_after_ROR_by_reg(
19699 dis_buf
, &res
, &resC
, rDt
, rSt
, rD
, rS
19704 /*NOTREACHED*/vassert(0);
19706 // not safe to read guest state after this point
19707 putIRegT(rD
, mkexpr(res
), condT
);
19708 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, resC
, oldV
,
19709 cond_AND_notInIT_T
);
19710 DIP("%ss r%u, r%u\n", wot
, rS
, rD
);
19711 goto decode_success
;
19715 case 0x2E9: { // REV16
19716 /* ---------------- REV Rd, Rm ---------------- */
19717 /* ---------------- REV16 Rd, Rm ---------------- */
19718 UInt rM
= INSN0(5,3);
19719 UInt rD
= INSN0(2,0);
19720 Bool isREV
= INSN0(15,6) == 0x2E8;
19721 IRTemp arg
= newTemp(Ity_I32
);
19722 assign(arg
, getIRegT(rM
));
19723 IRTemp res
= isREV
? gen_REV(arg
) : gen_REV16(arg
);
19724 putIRegT(rD
, mkexpr(res
), condT
);
19725 DIP("rev%s r%u, r%u\n", isREV
? "" : "16", rD
, rM
);
19726 goto decode_success
;
19729 case 0x2EB: { // REVSH
19730 /* ---------------- REVSH Rd, Rn ---------------- */
19731 UInt rM
= INSN0(5,3);
19732 UInt rD
= INSN0(2,0);
19733 IRTemp irt_rM
= newTemp(Ity_I32
);
19734 IRTemp irt_hi
= newTemp(Ity_I32
);
19735 IRTemp irt_low
= newTemp(Ity_I32
);
19736 IRTemp irt_res
= newTemp(Ity_I32
);
19737 assign(irt_rM
, getIRegT(rM
));
19740 binop(Iop_Shl32
, mkexpr(irt_rM
), mkU8(24)),
19746 binop(Iop_Shr32
, mkexpr(irt_rM
), mkU8(8)),
19751 binop(Iop_Or32
, mkexpr(irt_hi
), mkexpr(irt_low
))
19753 putIRegT(rD
, mkexpr(irt_res
), condT
);
19754 DIP("revsh r%u, r%u\n", rD
, rM
);
19755 goto decode_success
;
19759 break; /* examine the next shortest prefix */
19764 /* ================ 16-bit 15:7 cases ================ */
19766 switch (INSN0(15,7)) {
19768 case BITS9(1,0,1,1,0,0,0,0,0): {
19769 /* ------------ ADD SP, #imm7 * 4 ------------ */
19770 UInt uimm7
= INSN0(6,0);
19771 putIRegT(13, binop(Iop_Add32
, getIRegT(13), mkU32(uimm7
* 4)),
19773 DIP("add sp, #%u\n", uimm7
* 4);
19774 goto decode_success
;
19777 case BITS9(1,0,1,1,0,0,0,0,1): {
19778 /* ------------ SUB SP, #imm7 * 4 ------------ */
19779 UInt uimm7
= INSN0(6,0);
19780 putIRegT(13, binop(Iop_Sub32
, getIRegT(13), mkU32(uimm7
* 4)),
19782 DIP("sub sp, #%u\n", uimm7
* 4);
19783 goto decode_success
;
19786 case BITS9(0,1,0,0,0,1,1,1,0): {
19787 /* ---------------- BX rM ---------------- */
19788 /* Branch to reg, and optionally switch modes. Reg contains a
19789 suitably encoded address therefore (w CPSR.T at the bottom).
19790 Have to special-case r15, as usual. */
19791 UInt rM
= (INSN0(6,6) << 3) | INSN0(5,3);
19792 if (BITS3(0,0,0) == INSN0(2,0)) {
19793 IRTemp dst
= newTemp(Ity_I32
);
19794 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
19795 mk_skip_over_T16_if_cond_is_false(condT
);
19796 condT
= IRTemp_INVALID
;
19799 assign( dst
, getIRegT(rM
) );
19802 assign( dst
, mkU32(guest_R15_curr_instr_notENC
+ 4) );
19804 llPutIReg(15, mkexpr(dst
));
19805 dres
.jk_StopHere
= rM
== 14 ? Ijk_Ret
: Ijk_Boring
;
19806 dres
.whatNext
= Dis_StopHere
;
19807 DIP("bx r%u (possibly switch to ARM mode)\n", rM
);
19808 goto decode_success
;
19813 /* ---------------- BLX rM ---------------- */
19814 /* Branch and link to interworking address in rM. */
19815 case BITS9(0,1,0,0,0,1,1,1,1): {
19816 if (BITS3(0,0,0) == INSN0(2,0)) {
19817 UInt rM
= (INSN0(6,6) << 3) | INSN0(5,3);
19818 IRTemp dst
= newTemp(Ity_I32
);
19820 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
19821 mk_skip_over_T16_if_cond_is_false(condT
);
19822 condT
= IRTemp_INVALID
;
19824 /* We're returning to Thumb code, hence "| 1" */
19825 assign( dst
, getIRegT(rM
) );
19826 putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC
+ 2) | 1 ),
19828 llPutIReg(15, mkexpr(dst
));
19829 dres
.jk_StopHere
= Ijk_Call
;
19830 dres
.whatNext
= Dis_StopHere
;
19831 DIP("blx r%u (possibly switch to ARM mode)\n", rM
);
19832 goto decode_success
;
19834 /* else unpredictable, fall through */
19840 break; /* examine the next shortest prefix */
19845 /* ================ 16-bit 15:8 cases ================ */
19847 switch (INSN0(15,8)) {
19849 case BITS8(1,1,0,1,1,1,1,1): {
19850 /* ---------------- SVC ---------------- */
19851 UInt imm8
= INSN0(7,0);
19853 /* A syscall. We can't do this conditionally, hence: */
19854 mk_skip_over_T16_if_cond_is_false( condT
);
19855 // FIXME: what if we have to back up and restart this insn?
19856 // then ITSTATE will be wrong (we'll have it as "used")
19857 // when it isn't. Correct is to save ITSTATE in a
19858 // stash pseudo-reg, and back up from that if we have to
19860 // uncond after here
19861 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC
+ 2) | 1 ));
19862 dres
.jk_StopHere
= Ijk_Sys_syscall
;
19863 dres
.whatNext
= Dis_StopHere
;
19864 DIP("svc #0x%08x\n", imm8
);
19865 goto decode_success
;
19867 /* else fall through */
19871 case BITS8(0,1,0,0,0,1,0,0): {
19872 /* ---------------- ADD(HI) Rd, Rm ---------------- */
19873 UInt h1
= INSN0(7,7);
19874 UInt h2
= INSN0(6,6);
19875 UInt rM
= (h2
<< 3) | INSN0(5,3);
19876 UInt rD
= (h1
<< 3) | INSN0(2,0);
19877 //if (h1 == 0 && h2 == 0) { // Original T1 was more restrictive
19878 if (rD
== 15 && rM
== 15) {
19879 // then it's invalid
19881 IRTemp res
= newTemp(Ity_I32
);
19882 assign( res
, binop(Iop_Add32
, getIRegT(rD
), getIRegT(rM
) ));
19884 putIRegT( rD
, mkexpr(res
), condT
);
19886 /* Only allowed outside or last-in IT block; SIGILL if not so. */
19887 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
19888 /* jump over insn if not selected */
19889 mk_skip_over_T16_if_cond_is_false(condT
);
19890 condT
= IRTemp_INVALID
;
19892 /* non-interworking branch */
19893 llPutIReg(15, binop(Iop_Or32
, mkexpr(res
), mkU32(1)));
19894 dres
.jk_StopHere
= Ijk_Boring
;
19895 dres
.whatNext
= Dis_StopHere
;
19897 DIP("add(hi) r%u, r%u\n", rD
, rM
);
19898 goto decode_success
;
19903 case BITS8(0,1,0,0,0,1,0,1): {
19904 /* ---------------- CMP(HI) Rd, Rm ---------------- */
19905 UInt h1
= INSN0(7,7);
19906 UInt h2
= INSN0(6,6);
19907 UInt rM
= (h2
<< 3) | INSN0(5,3);
19908 UInt rN
= (h1
<< 3) | INSN0(2,0);
19909 if (h1
!= 0 || h2
!= 0) {
19910 IRTemp argL
= newTemp(Ity_I32
);
19911 IRTemp argR
= newTemp(Ity_I32
);
19912 assign( argL
, getIRegT(rN
) );
19913 assign( argR
, getIRegT(rM
) );
19914 /* Update flags regardless of whether in an IT block or not. */
19915 setFlags_D1_D2( ARMG_CC_OP_SUB
, argL
, argR
, condT
);
19916 DIP("cmphi r%u, r%u\n", rN
, rM
);
19917 goto decode_success
;
19922 case BITS8(0,1,0,0,0,1,1,0): {
19923 /* ---------------- MOV(HI) Rd, Rm ---------------- */
19924 UInt h1
= INSN0(7,7);
19925 UInt h2
= INSN0(6,6);
19926 UInt rM
= (h2
<< 3) | INSN0(5,3);
19927 UInt rD
= (h1
<< 3) | INSN0(2,0);
19928 /* The old ARM ARM seems to disallow the case where both Rd and
19929 Rm are "low" registers, but newer versions allow it. */
19930 if (1 /*h1 != 0 || h2 != 0*/) {
19931 IRTemp val
= newTemp(Ity_I32
);
19932 assign( val
, getIRegT(rM
) );
19934 putIRegT( rD
, mkexpr(val
), condT
);
19936 /* Only allowed outside or last-in IT block; SIGILL if not so. */
19937 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
19938 /* jump over insn if not selected */
19939 mk_skip_over_T16_if_cond_is_false(condT
);
19940 condT
= IRTemp_INVALID
;
19942 /* non-interworking branch */
19943 llPutIReg(15, binop(Iop_Or32
, mkexpr(val
), mkU32(1)));
19944 dres
.jk_StopHere
= rM
== 14 ? Ijk_Ret
: Ijk_Boring
;
19945 dres
.whatNext
= Dis_StopHere
;
19947 DIP("mov r%u, r%u\n", rD
, rM
);
19948 goto decode_success
;
19953 case BITS8(1,0,1,1,1,1,1,1): {
19954 /* ---------------- IT (if-then) ---------------- */
19955 UInt firstcond
= INSN0(7,4);
19956 UInt mask
= INSN0(3,0);
19957 UInt newITSTATE
= 0;
19958 /* This is the ITSTATE represented as described in
19959 libvex_guest_arm.h. It is not the ARM ARM representation. */
19963 Bool valid
= compute_ITSTATE( &newITSTATE
, &c1
, &c2
, &c3
,
19965 if (valid
&& firstcond
!= 0xF/*NV*/) {
19966 /* Not allowed in an IT block; SIGILL if so. */
19967 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
19969 IRTemp t
= newTemp(Ity_I32
);
19970 assign(t
, mkU32(newITSTATE
));
19973 DIP("it%c%c%c %s\n", c1
, c2
, c3
, nCC(firstcond
));
19974 goto decode_success
;
19979 case BITS8(1,0,1,1,0,0,0,1):
19980 case BITS8(1,0,1,1,0,0,1,1):
19981 case BITS8(1,0,1,1,1,0,0,1):
19982 case BITS8(1,0,1,1,1,0,1,1): {
19983 /* ---------------- CB{N}Z ---------------- */
19984 UInt rN
= INSN0(2,0);
19985 UInt bOP
= INSN0(11,11);
19986 UInt imm32
= (INSN0(9,9) << 6) | (INSN0(7,3) << 1);
19987 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
19988 /* It's a conditional branch forward. */
19989 IRTemp kond
= newTemp(Ity_I1
);
19990 assign( kond
, binop(bOP
? Iop_CmpNE32
: Iop_CmpEQ32
,
19991 getIRegT(rN
), mkU32(0)) );
19993 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
19994 /* Looks like the nearest insn we can branch to is the one after
19995 next. That makes sense, as there's no point in being able to
19996 encode a conditional branch to the next instruction. */
19997 UInt dst
= (guest_R15_curr_instr_notENC
+ 4 + imm32
) | 1;
19998 stmt(IRStmt_Exit( mkexpr(kond
),
20000 IRConst_U32(toUInt(dst
)),
20002 DIP("cb%s r%u, 0x%x\n", bOP
? "nz" : "z", rN
, dst
- 1);
20003 goto decode_success
;
20007 break; /* examine the next shortest prefix */
20012 /* ================ 16-bit 15:9 cases ================ */
20014 switch (INSN0(15,9)) {
20016 case BITS7(1,0,1,1,0,1,0): {
20017 /* ---------------- PUSH ---------------- */
20018 /* This is a bit like STMxx, but way simpler. Complications we
20019 don't have to deal with:
20020 * SP being one of the transferred registers
20021 * direction (increment vs decrement)
20022 * before-vs-after-ness
20025 UInt bitR
= INSN0(8,8);
20026 UInt regList
= INSN0(7,0);
20027 if (bitR
) regList
|= (1 << 14);
20029 /* At least one register must be transferred, else result is
20031 if (regList
!= 0) {
20032 /* Since we can't generate a guaranteed non-trapping IR
20033 sequence, (1) jump over the insn if it is gated false, and
20034 (2) back out the ITSTATE update. */
20035 mk_skip_over_T16_if_cond_is_false(condT
);
20036 condT
= IRTemp_INVALID
;
20037 put_ITSTATE(old_itstate
);
20041 for (i
= 0; i
< 16; i
++) {
20042 if ((regList
& (1 << i
)) != 0)
20045 vassert(nRegs
>= 1 && nRegs
<= 9);
20047 /* Move SP down first of all, so we're "covered". And don't
20048 mess with its alignment. */
20049 IRTemp newSP
= newTemp(Ity_I32
);
20050 assign(newSP
, binop(Iop_Sub32
, getIRegT(13), mkU32(4 * nRegs
)));
20051 putIRegT(13, mkexpr(newSP
), IRTemp_INVALID
);
20053 /* Generate a transfer base address as a forced-aligned
20054 version of the final SP value. */
20055 IRTemp base
= newTemp(Ity_I32
);
20056 assign(base
, binop(Iop_And32
, mkexpr(newSP
), mkU32(~3)));
20058 /* Now the transfers */
20060 for (i
= 0; i
< 16; i
++) {
20061 if ((regList
& (1 << i
)) != 0) {
20062 storeLE( binop(Iop_Add32
, mkexpr(base
), mkU32(4 * nRegs
)),
20068 /* Reinstate the ITSTATE update. */
20069 put_ITSTATE(new_itstate
);
20071 DIP("push {%s0x%04x}\n", bitR
? "lr," : "", regList
& 0xFF);
20072 goto decode_success
;
20077 case BITS7(1,0,1,1,1,1,0): {
20078 /* ---------------- POP ---------------- */
20080 UInt bitR
= INSN0(8,8);
20081 UInt regList
= INSN0(7,0);
20083 /* At least one register must be transferred, else result is
20085 if (regList
!= 0 || bitR
) {
20086 /* Since we can't generate a guaranteed non-trapping IR
20087 sequence, (1) jump over the insn if it is gated false, and
20088 (2) back out the ITSTATE update. */
20089 mk_skip_over_T16_if_cond_is_false(condT
);
20090 condT
= IRTemp_INVALID
;
20091 put_ITSTATE(old_itstate
);
20095 for (i
= 0; i
< 8; i
++) {
20096 if ((regList
& (1 << i
)) != 0)
20099 vassert(nRegs
>= 0 && nRegs
<= 8);
20100 vassert(bitR
== 0 || bitR
== 1);
20102 IRTemp oldSP
= newTemp(Ity_I32
);
20103 assign(oldSP
, getIRegT(13));
20105 /* Generate a transfer base address as a forced-aligned
20106 version of the original SP value. */
20107 IRTemp base
= newTemp(Ity_I32
);
20108 assign(base
, binop(Iop_And32
, mkexpr(oldSP
), mkU32(~3)));
20110 /* Compute a new value for SP, but don't install it yet, so
20111 that we're "covered" until all the transfers are done.
20112 And don't mess with its alignment. */
20113 IRTemp newSP
= newTemp(Ity_I32
);
20114 assign(newSP
, binop(Iop_Add32
, mkexpr(oldSP
),
20115 mkU32(4 * (nRegs
+ bitR
))));
20117 /* Now the transfers, not including PC */
20119 for (i
= 0; i
< 8; i
++) {
20120 if ((regList
& (1 << i
)) != 0) {
20121 putIRegT(i
, loadLE( Ity_I32
,
20122 binop(Iop_Add32
, mkexpr(base
),
20123 mkU32(4 * nRegs
))),
20129 IRTemp newPC
= IRTemp_INVALID
;
20131 newPC
= newTemp(Ity_I32
);
20132 assign( newPC
, loadLE( Ity_I32
,
20133 binop(Iop_Add32
, mkexpr(base
),
20134 mkU32(4 * nRegs
))));
20137 /* Now we can safely install the new SP value */
20138 putIRegT(13, mkexpr(newSP
), IRTemp_INVALID
);
20140 /* Reinstate the ITSTATE update. */
20141 put_ITSTATE(new_itstate
);
20143 /* now, do we also have to do a branch? If so, it turns out
20144 that the new PC value is encoded exactly as we need it to
20145 be -- with CPSR.T in the bottom bit. So we can simply use
20146 it as is, no need to mess with it. Note, therefore, this
20147 is an interworking return. */
20149 llPutIReg(15, mkexpr(newPC
));
20150 dres
.jk_StopHere
= Ijk_Ret
;
20151 dres
.whatNext
= Dis_StopHere
;
20154 DIP("pop {%s0x%04x}\n", bitR
? "pc," : "", regList
& 0xFF);
20155 goto decode_success
;
20160 case BITS7(0,0,0,1,1,1,0): /* ADDS */
20161 case BITS7(0,0,0,1,1,1,1): { /* SUBS */
20162 /* ---------------- ADDS Rd, Rn, #uimm3 ---------------- */
20163 /* ---------------- SUBS Rd, Rn, #uimm3 ---------------- */
20164 UInt uimm3
= INSN0(8,6);
20165 UInt rN
= INSN0(5,3);
20166 UInt rD
= INSN0(2,0);
20167 UInt isSub
= INSN0(9,9);
20168 IRTemp argL
= newTemp(Ity_I32
);
20169 IRTemp argR
= newTemp(Ity_I32
);
20170 assign( argL
, getIRegT(rN
) );
20171 assign( argR
, mkU32(uimm3
) );
20172 putIRegT(rD
, binop(isSub
? Iop_Sub32
: Iop_Add32
,
20173 mkexpr(argL
), mkexpr(argR
)),
20175 setFlags_D1_D2( isSub
? ARMG_CC_OP_SUB
: ARMG_CC_OP_ADD
,
20176 argL
, argR
, cond_AND_notInIT_T
);
20177 DIP("%s r%u, r%u, #%u\n", isSub
? "subs" : "adds", rD
, rN
, uimm3
);
20178 goto decode_success
;
20181 case BITS7(0,0,0,1,1,0,0): /* ADDS */
20182 case BITS7(0,0,0,1,1,0,1): { /* SUBS */
20183 /* ---------------- ADDS Rd, Rn, Rm ---------------- */
20184 /* ---------------- SUBS Rd, Rn, Rm ---------------- */
20185 UInt rM
= INSN0(8,6);
20186 UInt rN
= INSN0(5,3);
20187 UInt rD
= INSN0(2,0);
20188 UInt isSub
= INSN0(9,9);
20189 IRTemp argL
= newTemp(Ity_I32
);
20190 IRTemp argR
= newTemp(Ity_I32
);
20191 assign( argL
, getIRegT(rN
) );
20192 assign( argR
, getIRegT(rM
) );
20193 putIRegT( rD
, binop(isSub
? Iop_Sub32
: Iop_Add32
,
20194 mkexpr(argL
), mkexpr(argR
)),
20196 setFlags_D1_D2( isSub
? ARMG_CC_OP_SUB
: ARMG_CC_OP_ADD
,
20197 argL
, argR
, cond_AND_notInIT_T
);
20198 DIP("%s r%u, r%u, r%u\n", isSub
? "subs" : "adds", rD
, rN
, rM
);
20199 goto decode_success
;
20202 case BITS7(0,1,0,1,0,0,0): /* STR */
20203 case BITS7(0,1,0,1,1,0,0): { /* LDR */
20204 /* ------------- LDR Rd, [Rn, Rm] ------------- */
20205 /* ------------- STR Rd, [Rn, Rm] ------------- */
20206 /* LDR/STR Rd, [Rn + Rm] */
20207 UInt rD
= INSN0(2,0);
20208 UInt rN
= INSN0(5,3);
20209 UInt rM
= INSN0(8,6);
20210 UInt isLD
= INSN0(11,11);
20212 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), getIRegT(rM
));
20213 put_ITSTATE(old_itstate
); // backout
20215 IRTemp tD
= newTemp(Ity_I32
);
20216 loadGuardedLE( tD
, ILGop_Ident32
, ea
, llGetIReg(rD
), condT
);
20217 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20219 storeGuardedLE(ea
, getIRegT(rD
), condT
);
20221 put_ITSTATE(new_itstate
); // restore
20223 DIP("%s r%u, [r%u, r%u]\n", isLD
? "ldr" : "str", rD
, rN
, rM
);
20224 goto decode_success
;
20227 case BITS7(0,1,0,1,0,0,1):
20228 case BITS7(0,1,0,1,1,0,1): {
20229 /* ------------- LDRH Rd, [Rn, Rm] ------------- */
20230 /* ------------- STRH Rd, [Rn, Rm] ------------- */
20231 /* LDRH/STRH Rd, [Rn + Rm] */
20232 UInt rD
= INSN0(2,0);
20233 UInt rN
= INSN0(5,3);
20234 UInt rM
= INSN0(8,6);
20235 UInt isLD
= INSN0(11,11);
20237 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), getIRegT(rM
));
20238 put_ITSTATE(old_itstate
); // backout
20240 IRTemp tD
= newTemp(Ity_I32
);
20241 loadGuardedLE(tD
, ILGop_16Uto32
, ea
, llGetIReg(rD
), condT
);
20242 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20244 storeGuardedLE( ea
, unop(Iop_32to16
, getIRegT(rD
)), condT
);
20246 put_ITSTATE(new_itstate
); // restore
20248 DIP("%sh r%u, [r%u, r%u]\n", isLD
? "ldr" : "str", rD
, rN
, rM
);
20249 goto decode_success
;
20252 case BITS7(0,1,0,1,1,1,1): {
20253 /* ------------- LDRSH Rd, [Rn, Rm] ------------- */
20254 /* LDRSH Rd, [Rn + Rm] */
20255 UInt rD
= INSN0(2,0);
20256 UInt rN
= INSN0(5,3);
20257 UInt rM
= INSN0(8,6);
20259 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), getIRegT(rM
));
20260 put_ITSTATE(old_itstate
); // backout
20261 IRTemp tD
= newTemp(Ity_I32
);
20262 loadGuardedLE(tD
, ILGop_16Sto32
, ea
, llGetIReg(rD
), condT
);
20263 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20264 put_ITSTATE(new_itstate
); // restore
20266 DIP("ldrsh r%u, [r%u, r%u]\n", rD
, rN
, rM
);
20267 goto decode_success
;
20270 case BITS7(0,1,0,1,0,1,1): {
20271 /* ------------- LDRSB Rd, [Rn, Rm] ------------- */
20272 /* LDRSB Rd, [Rn + Rm] */
20273 UInt rD
= INSN0(2,0);
20274 UInt rN
= INSN0(5,3);
20275 UInt rM
= INSN0(8,6);
20277 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), getIRegT(rM
));
20278 put_ITSTATE(old_itstate
); // backout
20279 IRTemp tD
= newTemp(Ity_I32
);
20280 loadGuardedLE(tD
, ILGop_8Sto32
, ea
, llGetIReg(rD
), condT
);
20281 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20282 put_ITSTATE(new_itstate
); // restore
20284 DIP("ldrsb r%u, [r%u, r%u]\n", rD
, rN
, rM
);
20285 goto decode_success
;
20288 case BITS7(0,1,0,1,0,1,0):
20289 case BITS7(0,1,0,1,1,1,0): {
20290 /* ------------- LDRB Rd, [Rn, Rm] ------------- */
20291 /* ------------- STRB Rd, [Rn, Rm] ------------- */
20292 /* LDRB/STRB Rd, [Rn + Rm] */
20293 UInt rD
= INSN0(2,0);
20294 UInt rN
= INSN0(5,3);
20295 UInt rM
= INSN0(8,6);
20296 UInt isLD
= INSN0(11,11);
20298 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), getIRegT(rM
));
20299 put_ITSTATE(old_itstate
); // backout
20301 IRTemp tD
= newTemp(Ity_I32
);
20302 loadGuardedLE(tD
, ILGop_8Uto32
, ea
, llGetIReg(rD
), condT
);
20303 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20305 storeGuardedLE( ea
, unop(Iop_32to8
, getIRegT(rD
)), condT
);
20307 put_ITSTATE(new_itstate
); // restore
20309 DIP("%sb r%u, [r%u, r%u]\n", isLD
? "ldr" : "str", rD
, rN
, rM
);
20310 goto decode_success
;
20314 break; /* examine the next shortest prefix */
20319 /* ================ 16-bit 15:11 cases ================ */
20321 switch (INSN0(15,11)) {
20323 case BITS5(0,0,1,1,0):
20324 case BITS5(0,0,1,1,1): {
20325 /* ---------------- ADDS Rn, #uimm8 ---------------- */
20326 /* ---------------- SUBS Rn, #uimm8 ---------------- */
20327 UInt isSub
= INSN0(11,11);
20328 UInt rN
= INSN0(10,8);
20329 UInt uimm8
= INSN0(7,0);
20330 IRTemp argL
= newTemp(Ity_I32
);
20331 IRTemp argR
= newTemp(Ity_I32
);
20332 assign( argL
, getIRegT(rN
) );
20333 assign( argR
, mkU32(uimm8
) );
20334 putIRegT( rN
, binop(isSub
? Iop_Sub32
: Iop_Add32
,
20335 mkexpr(argL
), mkexpr(argR
)), condT
);
20336 setFlags_D1_D2( isSub
? ARMG_CC_OP_SUB
: ARMG_CC_OP_ADD
,
20337 argL
, argR
, cond_AND_notInIT_T
);
20338 DIP("%s r%u, #%u\n", isSub
? "subs" : "adds", rN
, uimm8
);
20339 goto decode_success
;
20342 case BITS5(1,0,1,0,0): {
20343 /* ---------------- ADD rD, PC, #imm8 * 4 ---------------- */
20345 /* rD = align4(PC) + imm8 * 4 */
20346 UInt rD
= INSN0(10,8);
20347 UInt imm8
= INSN0(7,0);
20348 putIRegT(rD
, binop(Iop_Add32
,
20349 binop(Iop_And32
, getIRegT(15), mkU32(~3U)),
20352 DIP("add r%u, pc, #%u\n", rD
, imm8
* 4);
20353 goto decode_success
;
20356 case BITS5(1,0,1,0,1): {
20357 /* ---------------- ADD rD, SP, #imm8 * 4 ---------------- */
20358 UInt rD
= INSN0(10,8);
20359 UInt imm8
= INSN0(7,0);
20360 putIRegT(rD
, binop(Iop_Add32
, getIRegT(13), mkU32(imm8
* 4)),
20362 DIP("add r%u, r13, #%u\n", rD
, imm8
* 4);
20363 goto decode_success
;
20366 case BITS5(0,0,1,0,1): {
20367 /* ---------------- CMP Rn, #uimm8 ---------------- */
20368 UInt rN
= INSN0(10,8);
20369 UInt uimm8
= INSN0(7,0);
20370 IRTemp argL
= newTemp(Ity_I32
);
20371 IRTemp argR
= newTemp(Ity_I32
);
20372 assign( argL
, getIRegT(rN
) );
20373 assign( argR
, mkU32(uimm8
) );
20374 /* Update flags regardless of whether in an IT block or not. */
20375 setFlags_D1_D2( ARMG_CC_OP_SUB
, argL
, argR
, condT
);
20376 DIP("cmp r%u, #%u\n", rN
, uimm8
);
20377 goto decode_success
;
20380 case BITS5(0,0,1,0,0): {
20381 /* -------------- (T1) MOVS Rn, #uimm8 -------------- */
20382 UInt rD
= INSN0(10,8);
20383 UInt uimm8
= INSN0(7,0);
20384 IRTemp oldV
= newTemp(Ity_I32
);
20385 IRTemp oldC
= newTemp(Ity_I32
);
20386 IRTemp res
= newTemp(Ity_I32
);
20387 assign( oldV
, mk_armg_calculate_flag_v() );
20388 assign( oldC
, mk_armg_calculate_flag_c() );
20389 assign( res
, mkU32(uimm8
) );
20390 putIRegT(rD
, mkexpr(res
), condT
);
20391 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
20392 cond_AND_notInIT_T
);
20393 DIP("movs r%u, #%u\n", rD
, uimm8
);
20394 goto decode_success
;
20397 case BITS5(0,1,0,0,1): {
20398 /* ------------- LDR Rd, [PC, #imm8 * 4] ------------- */
20399 /* LDR Rd, [align4(PC) + imm8 * 4] */
20400 UInt rD
= INSN0(10,8);
20401 UInt imm8
= INSN0(7,0);
20402 IRTemp ea
= newTemp(Ity_I32
);
20404 assign(ea
, binop(Iop_Add32
,
20405 binop(Iop_And32
, getIRegT(15), mkU32(~3U)),
20407 put_ITSTATE(old_itstate
); // backout
20408 IRTemp tD
= newTemp(Ity_I32
);
20409 loadGuardedLE( tD
, ILGop_Ident32
, mkexpr(ea
), llGetIReg(rD
), condT
);
20410 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20411 put_ITSTATE(new_itstate
); // restore
20413 DIP("ldr r%u, [pc, #%u]\n", rD
, imm8
* 4);
20414 goto decode_success
;
20417 case BITS5(0,1,1,0,0): /* STR */
20418 case BITS5(0,1,1,0,1): { /* LDR */
20419 /* ------------- LDR Rd, [Rn, #imm5 * 4] ------------- */
20420 /* ------------- STR Rd, [Rn, #imm5 * 4] ------------- */
20421 /* LDR/STR Rd, [Rn + imm5 * 4] */
20422 UInt rD
= INSN0(2,0);
20423 UInt rN
= INSN0(5,3);
20424 UInt imm5
= INSN0(10,6);
20425 UInt isLD
= INSN0(11,11);
20427 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm5
* 4));
20428 put_ITSTATE(old_itstate
); // backout
20430 IRTemp tD
= newTemp(Ity_I32
);
20431 loadGuardedLE( tD
, ILGop_Ident32
, ea
, llGetIReg(rD
), condT
);
20432 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20434 storeGuardedLE( ea
, getIRegT(rD
), condT
);
20436 put_ITSTATE(new_itstate
); // restore
20438 DIP("%s r%u, [r%u, #%u]\n", isLD
? "ldr" : "str", rD
, rN
, imm5
* 4);
20439 goto decode_success
;
20442 case BITS5(1,0,0,0,0): /* STRH */
20443 case BITS5(1,0,0,0,1): { /* LDRH */
20444 /* ------------- LDRH Rd, [Rn, #imm5 * 2] ------------- */
20445 /* ------------- STRH Rd, [Rn, #imm5 * 2] ------------- */
20446 /* LDRH/STRH Rd, [Rn + imm5 * 2] */
20447 UInt rD
= INSN0(2,0);
20448 UInt rN
= INSN0(5,3);
20449 UInt imm5
= INSN0(10,6);
20450 UInt isLD
= INSN0(11,11);
20452 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm5
* 2));
20453 put_ITSTATE(old_itstate
); // backout
20455 IRTemp tD
= newTemp(Ity_I32
);
20456 loadGuardedLE( tD
, ILGop_16Uto32
, ea
, llGetIReg(rD
), condT
);
20457 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20459 storeGuardedLE( ea
, unop(Iop_32to16
, getIRegT(rD
)), condT
);
20461 put_ITSTATE(new_itstate
); // restore
20463 DIP("%sh r%u, [r%u, #%u]\n", isLD
? "ldr" : "str", rD
, rN
, imm5
* 2);
20464 goto decode_success
;
20467 case BITS5(0,1,1,1,0): /* STRB */
20468 case BITS5(0,1,1,1,1): { /* LDRB */
20469 /* ------------- LDRB Rd, [Rn, #imm5] ------------- */
20470 /* ------------- STRB Rd, [Rn, #imm5] ------------- */
20471 /* LDRB/STRB Rd, [Rn + imm5] */
20472 UInt rD
= INSN0(2,0);
20473 UInt rN
= INSN0(5,3);
20474 UInt imm5
= INSN0(10,6);
20475 UInt isLD
= INSN0(11,11);
20477 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm5
));
20478 put_ITSTATE(old_itstate
); // backout
20480 IRTemp tD
= newTemp(Ity_I32
);
20481 loadGuardedLE( tD
, ILGop_8Uto32
, ea
, llGetIReg(rD
), condT
);
20482 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20484 storeGuardedLE( ea
, unop(Iop_32to8
, getIRegT(rD
)), condT
);
20486 put_ITSTATE(new_itstate
); // restore
20488 DIP("%sb r%u, [r%u, #%u]\n", isLD
? "ldr" : "str", rD
, rN
, imm5
);
20489 goto decode_success
;
20492 case BITS5(1,0,0,1,0): /* STR */
20493 case BITS5(1,0,0,1,1): { /* LDR */
20494 /* ------------- LDR Rd, [SP, #imm8 * 4] ------------- */
20495 /* ------------- STR Rd, [SP, #imm8 * 4] ------------- */
20496 /* LDR/STR Rd, [SP + imm8 * 4] */
20497 UInt rD
= INSN0(10,8);
20498 UInt imm8
= INSN0(7,0);
20499 UInt isLD
= INSN0(11,11);
20501 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(13), mkU32(imm8
* 4));
20502 put_ITSTATE(old_itstate
); // backout
20504 IRTemp tD
= newTemp(Ity_I32
);
20505 loadGuardedLE( tD
, ILGop_Ident32
, ea
, llGetIReg(rD
), condT
);
20506 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20508 storeGuardedLE(ea
, getIRegT(rD
), condT
);
20510 put_ITSTATE(new_itstate
); // restore
20512 DIP("%s r%u, [sp, #%u]\n", isLD
? "ldr" : "str", rD
, imm8
* 4);
20513 goto decode_success
;
20516 case BITS5(1,1,0,0,1): {
20517 /* ------------- LDMIA Rn!, {reglist} ------------- */
20519 UInt rN
= INSN0(10,8);
20520 UInt list
= INSN0(7,0);
20521 /* Empty lists aren't allowed. */
20523 mk_skip_over_T16_if_cond_is_false(condT
);
20524 condT
= IRTemp_INVALID
;
20525 put_ITSTATE(old_itstate
);
20528 IRTemp oldRn
= newTemp(Ity_I32
);
20529 IRTemp base
= newTemp(Ity_I32
);
20530 assign(oldRn
, getIRegT(rN
));
20531 assign(base
, binop(Iop_And32
, mkexpr(oldRn
), mkU32(~3U)));
20532 for (i
= 0; i
< 8; i
++) {
20533 if (0 == (list
& (1 << i
)))
20538 binop(Iop_Add32
, mkexpr(base
),
20539 mkU32(nRegs
* 4 - 4))),
20543 /* Only do the writeback for rN if it isn't in the list of
20544 registers to be transferred. */
20545 if (0 == (list
& (1 << rN
))) {
20547 binop(Iop_Add32
, mkexpr(oldRn
),
20553 /* Reinstate the ITSTATE update. */
20554 put_ITSTATE(new_itstate
);
20556 DIP("ldmia r%u!, {0x%04x}\n", rN
, list
);
20557 goto decode_success
;
20562 case BITS5(1,1,0,0,0): {
20563 /* ------------- STMIA Rn!, {reglist} ------------- */
20565 UInt rN
= INSN0(10,8);
20566 UInt list
= INSN0(7,0);
20567 /* Empty lists aren't allowed. Also, if rN is in the list then
20568 it must be the lowest numbered register in the list. */
20569 Bool valid
= list
!= 0;
20570 if (valid
&& 0 != (list
& (1 << rN
))) {
20571 for (i
= 0; i
< rN
; i
++) {
20572 if (0 != (list
& (1 << i
)))
20577 mk_skip_over_T16_if_cond_is_false(condT
);
20578 condT
= IRTemp_INVALID
;
20579 put_ITSTATE(old_itstate
);
20582 IRTemp oldRn
= newTemp(Ity_I32
);
20583 IRTemp base
= newTemp(Ity_I32
);
20584 assign(oldRn
, getIRegT(rN
));
20585 assign(base
, binop(Iop_And32
, mkexpr(oldRn
), mkU32(~3U)));
20586 for (i
= 0; i
< 8; i
++) {
20587 if (0 == (list
& (1 << i
)))
20590 storeLE( binop(Iop_Add32
, mkexpr(base
), mkU32(nRegs
* 4 - 4)),
20593 /* Always do the writeback. */
20595 binop(Iop_Add32
, mkexpr(oldRn
),
20599 /* Reinstate the ITSTATE update. */
20600 put_ITSTATE(new_itstate
);
20602 DIP("stmia r%u!, {0x%04x}\n", rN
, list
);
20603 goto decode_success
;
20608 case BITS5(0,0,0,0,0): /* LSLS */
20609 case BITS5(0,0,0,0,1): /* LSRS */
20610 case BITS5(0,0,0,1,0): { /* ASRS */
20611 /* ---------------- LSLS Rd, Rm, #imm5 ---------------- */
20612 /* ---------------- LSRS Rd, Rm, #imm5 ---------------- */
20613 /* ---------------- ASRS Rd, Rm, #imm5 ---------------- */
20614 UInt rD
= INSN0(2,0);
20615 UInt rM
= INSN0(5,3);
20616 UInt imm5
= INSN0(10,6);
20617 IRTemp res
= newTemp(Ity_I32
);
20618 IRTemp resC
= newTemp(Ity_I32
);
20619 IRTemp rMt
= newTemp(Ity_I32
);
20620 IRTemp oldV
= newTemp(Ity_I32
);
20621 const HChar
* wot
= "???";
20622 assign(rMt
, getIRegT(rM
));
20623 assign(oldV
, mk_armg_calculate_flag_v());
20624 /* Looks like INSN0(12,11) are the standard 'how' encoding.
20625 Could compactify if the ROR case later appears. */
20626 switch (INSN0(15,11)) {
20627 case BITS5(0,0,0,0,0):
20628 compute_result_and_C_after_LSL_by_imm5(
20629 dis_buf
, &res
, &resC
, rMt
, imm5
, rM
20633 case BITS5(0,0,0,0,1):
20634 compute_result_and_C_after_LSR_by_imm5(
20635 dis_buf
, &res
, &resC
, rMt
, imm5
, rM
20639 case BITS5(0,0,0,1,0):
20640 compute_result_and_C_after_ASR_by_imm5(
20641 dis_buf
, &res
, &resC
, rMt
, imm5
, rM
20646 /*NOTREACHED*/vassert(0);
20648 // not safe to read guest state after this point
20649 putIRegT(rD
, mkexpr(res
), condT
);
20650 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, resC
, oldV
,
20651 cond_AND_notInIT_T
);
20652 /* ignore buf and roll our own output */
20653 DIP("%ss r%u, r%u, #%u\n", wot
, rD
, rM
, imm5
);
20654 goto decode_success
;
20657 case BITS5(1,1,1,0,0): {
20658 /* ---------------- B #simm11 ---------------- */
20659 UInt uimm11
= INSN0(10,0); uimm11
<<= 21;
20660 Int simm11
= (Int
)uimm11
; simm11
>>= 20;
20661 UInt dst
= simm11
+ guest_R15_curr_instr_notENC
+ 4;
20662 /* Only allowed outside or last-in IT block; SIGILL if not so. */
20663 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
20664 // and skip this insn if not selected; being cleverer is too
20666 mk_skip_over_T16_if_cond_is_false(condT
);
20667 condT
= IRTemp_INVALID
;
20669 llPutIReg(15, mkU32( dst
| 1 /*CPSR.T*/ ));
20670 dres
.jk_StopHere
= Ijk_Boring
;
20671 dres
.whatNext
= Dis_StopHere
;
20672 DIP("b 0x%x\n", dst
);
20673 goto decode_success
;
20677 break; /* examine the next shortest prefix */
20682 /* ================ 16-bit 15:12 cases ================ */
20684 switch (INSN0(15,12)) {
20686 case BITS4(1,1,0,1): {
20687 /* ---------------- Bcond #simm8 ---------------- */
20688 UInt cond
= INSN0(11,8);
20689 UInt uimm8
= INSN0(7,0); uimm8
<<= 24;
20690 Int simm8
= (Int
)uimm8
; simm8
>>= 23;
20691 UInt dst
= simm8
+ guest_R15_curr_instr_notENC
+ 4;
20692 if (cond
!= ARMCondAL
&& cond
!= ARMCondNV
) {
20693 /* Not allowed in an IT block; SIGILL if so. */
20694 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
20696 IRTemp kondT
= newTemp(Ity_I32
);
20697 assign( kondT
, mk_armg_calculate_condition(cond
) );
20698 stmt( IRStmt_Exit( unop(Iop_32to1
, mkexpr(kondT
)),
20700 IRConst_U32(dst
| 1/*CPSR.T*/),
20702 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC
+ 2)
20704 dres
.jk_StopHere
= Ijk_Boring
;
20705 dres
.whatNext
= Dis_StopHere
;
20706 DIP("b%s 0x%x\n", nCC(cond
), dst
);
20707 goto decode_success
;
20713 break; /* hmm, nothing matched */
20717 /* ================ 16-bit misc cases ================ */
20719 switch (INSN0(15,0)) {
20721 /* ------ NOP ------ */
20723 goto decode_success
;
20724 case 0xBF10: // YIELD
20725 case 0xBF20: // WFE
20726 /* ------ WFE, YIELD ------ */
20727 /* Both appear to get used as a spin-loop hints. Do the usual thing,
20728 which is to continue after yielding. */
20729 stmt( IRStmt_Exit( unop(Iop_32to1
, mkexpr(condT
)),
20731 IRConst_U32((guest_R15_curr_instr_notENC
+ 2)
20734 Bool isWFE
= INSN0(15,0) == 0xBF20;
20735 DIP(isWFE
? "wfe\n" : "yield\n");
20736 goto decode_success
;
20738 /* ------ SEV ------ */
20739 /* Treat this as a no-op. Any matching WFEs won't really
20740 cause the host CPU to snooze; they just cause V to try to
20741 run some other thread for a while. So there's no point in
20742 really doing anything for SEV. */
20744 goto decode_success
;
20746 break; /* fall through */
20749 /* ----------------------------------------------------------- */
20751 /* -- Thumb 32-bit integer instructions -- */
20753 /* ----------------------------------------------------------- */
20755 # define INSN1(_bMax,_bMin) SLICE_UInt(((UInt)insn1), (_bMax), (_bMin))
20757 /* second 16 bits of the instruction, if any */
20758 vassert(insn1
== 0);
20759 insn1
= getUShortLittleEndianly( guest_instr
+2 );
20761 anOp
= Iop_INVALID
; /* paranoia */
20762 anOpNm
= NULL
; /* paranoia */
20764 /* Change result defaults to suit 32-bit insns. */
20765 vassert(dres
.whatNext
== Dis_Continue
);
20766 vassert(dres
.len
== 2);
20767 vassert(dres
.continueAt
== 0);
20770 /* ---------------- BL/BLX simm26 ---------------- */
20771 if (BITS5(1,1,1,1,0) == INSN0(15,11) && BITS2(1,1) == INSN1(15,14)) {
20772 UInt isBL
= INSN1(12,12);
20773 UInt bS
= INSN0(10,10);
20774 UInt bJ1
= INSN1(13,13);
20775 UInt bJ2
= INSN1(11,11);
20776 UInt bI1
= 1 ^ (bJ1
^ bS
);
20777 UInt bI2
= 1 ^ (bJ2
^ bS
);
20779 = (bS
<< (1 + 1 + 10 + 11 + 1))
20780 | (bI1
<< (1 + 10 + 11 + 1))
20781 | (bI2
<< (10 + 11 + 1))
20782 | (INSN0(9,0) << (11 + 1))
20783 | (INSN1(10,0) << 1);
20785 Int simm25
= (Int
)uimm25
;
20788 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
20789 UInt dst
= simm25
+ guest_R15_curr_instr_notENC
+ 4;
20791 /* One further validity case to check: in the case of BLX
20792 (not-BL), that insn1[0] must be zero. */
20794 if (isBL
== 0 && INSN1(0,0) == 1) valid
= False
;
20796 /* Only allowed outside or last-in IT block; SIGILL if not so. */
20797 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
20798 // and skip this insn if not selected; being cleverer is too
20800 mk_skip_over_T32_if_cond_is_false(condT
);
20801 condT
= IRTemp_INVALID
;
20804 /* We're returning to Thumb code, hence "| 1" */
20805 putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC
+ 4) | 1 ),
20808 /* BL: unconditional T -> T call */
20809 /* we're calling Thumb code, hence "| 1" */
20810 llPutIReg(15, mkU32( dst
| 1 ));
20811 DIP("bl 0x%x (stay in Thumb mode)\n", dst
);
20813 /* BLX: unconditional T -> A call */
20814 /* we're calling ARM code, hence "& 3" to align to a
20815 valid ARM insn address */
20816 llPutIReg(15, mkU32( dst
& ~3 ));
20817 DIP("blx 0x%x (switch to ARM mode)\n", dst
& ~3);
20819 dres
.whatNext
= Dis_StopHere
;
20820 dres
.jk_StopHere
= Ijk_Call
;
20821 goto decode_success
;
20825 /* ---------------- {LD,ST}M{IA,DB} ---------------- */
20826 if (0x3a2 == INSN0(15,6) // {LD,ST}MIA
20827 || 0x3a4 == INSN0(15,6)) { // {LD,ST}MDB
20828 UInt bW
= INSN0(5,5); /* writeback Rn ? */
20829 UInt bL
= INSN0(4,4);
20830 UInt rN
= INSN0(3,0);
20831 UInt bP
= INSN1(15,15); /* reglist entry for r15 */
20832 UInt bM
= INSN1(14,14); /* reglist entry for r14 */
20833 UInt rLmost
= INSN1(12,0); /* reglist entry for r0 .. 12 */
20834 UInt rL13
= INSN1(13,13); /* must be zero */
20840 if (INSN0(15,6) == 0x3a4) {
20845 /* detect statically invalid cases, and construct the final
20851 regList
= (bP
<< 15) | (bM
<< 14) | rLmost
;
20852 if (rN
== 15) valid
= False
;
20853 if (popcount32(regList
) < 2) valid
= False
;
20854 if (bP
== 1 && bM
== 1) valid
= False
;
20855 if (bW
== 1 && (regList
& (1<<rN
))) valid
= False
;
20857 regList
= (bM
<< 14) | rLmost
;
20858 if (bP
== 1) valid
= False
;
20859 if (rN
== 15) valid
= False
;
20860 if (popcount32(regList
) < 2) valid
= False
;
20861 if (bW
== 1 && (regList
& (1<<rN
))) valid
= False
;
20865 if (bL
== 1 && bP
== 1) {
20866 // We'll be writing the PC. Hence:
20867 /* Only allowed outside or last-in IT block; SIGILL if not so. */
20868 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
20872 mk_skip_over_T32_if_cond_is_false(condT
);
20873 condT
= IRTemp_INVALID
;
20876 /* Generate the IR. This might generate a write to R15. */
20877 mk_ldm_stm(False
/*!arm*/, rN
, bINC
, bBEFORE
, bW
, bL
, regList
);
20879 if (bL
== 1 && (regList
& (1<<15))) {
20880 // If we wrote to R15, we have an interworking return to
20882 llPutIReg(15, llGetIReg(15));
20883 dres
.jk_StopHere
= Ijk_Ret
;
20884 dres
.whatNext
= Dis_StopHere
;
20887 DIP("%sm%c%c r%u%s, {0x%04x}\n",
20888 bL
== 1 ? "ld" : "st", bINC
? 'i' : 'd', bBEFORE
? 'b' : 'a',
20889 rN
, bW
? "!" : "", regList
);
20891 goto decode_success
;
20895 /* -------------- (T3) ADD{S}.W Rd, Rn, #constT -------------- */
20896 if (INSN0(15,11) == BITS5(1,1,1,1,0)
20897 && INSN0(9,5) == BITS5(0,1,0,0,0)
20898 && INSN1(15,15) == 0) {
20899 UInt bS
= INSN0(4,4);
20900 UInt rN
= INSN0(3,0);
20901 UInt rD
= INSN1(11,8);
20902 Bool valid
= !isBadRegT(rN
) && !isBadRegT(rD
);
20903 /* but allow "add.w reg, sp, #constT" for reg != PC */
20904 if (!valid
&& rD
<= 14 && rN
== 13)
20907 IRTemp argL
= newTemp(Ity_I32
);
20908 IRTemp argR
= newTemp(Ity_I32
);
20909 IRTemp res
= newTemp(Ity_I32
);
20910 UInt imm32
= thumbExpandImm_from_I0_I1(NULL
, insn0
, insn1
);
20911 assign(argL
, getIRegT(rN
));
20912 assign(argR
, mkU32(imm32
));
20913 assign(res
, binop(Iop_Add32
, mkexpr(argL
), mkexpr(argR
)));
20914 putIRegT(rD
, mkexpr(res
), condT
);
20916 setFlags_D1_D2( ARMG_CC_OP_ADD
, argL
, argR
, condT
);
20917 DIP("add%s.w r%u, r%u, #%u\n",
20918 bS
== 1 ? "s" : "", rD
, rN
, imm32
);
20919 goto decode_success
;
20923 /* ---------------- (T4) ADDW Rd, Rn, #uimm12 -------------- */
20924 if (INSN0(15,11) == BITS5(1,1,1,1,0)
20925 && INSN0(9,4) == BITS6(1,0,0,0,0,0)
20926 && INSN1(15,15) == 0) {
20927 UInt rN
= INSN0(3,0);
20928 UInt rD
= INSN1(11,8);
20929 Bool valid
= !isBadRegT(rN
) && !isBadRegT(rD
);
20930 /* but allow "addw reg, sp, #uimm12" for reg != PC */
20931 if (!valid
&& rD
<= 14 && rN
== 13)
20934 IRTemp argL
= newTemp(Ity_I32
);
20935 IRTemp argR
= newTemp(Ity_I32
);
20936 IRTemp res
= newTemp(Ity_I32
);
20937 UInt imm12
= (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
20938 assign(argL
, getIRegT(rN
));
20939 assign(argR
, mkU32(imm12
));
20940 assign(res
, binop(Iop_Add32
, mkexpr(argL
), mkexpr(argR
)));
20941 putIRegT(rD
, mkexpr(res
), condT
);
20942 DIP("addw r%u, r%u, #%u\n", rD
, rN
, imm12
);
20943 goto decode_success
;
20947 /* ---------------- (T2) CMP.W Rn, #constT ---------------- */
20948 /* ---------------- (T2) CMN.W Rn, #constT ---------------- */
20949 if (INSN0(15,11) == BITS5(1,1,1,1,0)
20950 && ( INSN0(9,4) == BITS6(0,1,1,0,1,1) // CMP
20951 || INSN0(9,4) == BITS6(0,1,0,0,0,1)) // CMN
20952 && INSN1(15,15) == 0
20953 && INSN1(11,8) == BITS4(1,1,1,1)) {
20954 UInt rN
= INSN0(3,0);
20956 IRTemp argL
= newTemp(Ity_I32
);
20957 IRTemp argR
= newTemp(Ity_I32
);
20958 Bool isCMN
= INSN0(9,4) == BITS6(0,1,0,0,0,1);
20959 UInt imm32
= thumbExpandImm_from_I0_I1(NULL
, insn0
, insn1
);
20960 assign(argL
, getIRegT(rN
));
20961 assign(argR
, mkU32(imm32
));
20962 setFlags_D1_D2( isCMN
? ARMG_CC_OP_ADD
: ARMG_CC_OP_SUB
,
20963 argL
, argR
, condT
);
20964 DIP("%s.w r%u, #%u\n", isCMN
? "cmn" : "cmp", rN
, imm32
);
20965 goto decode_success
;
20969 /* -------------- (T1) TST.W Rn, #constT -------------- */
20970 /* -------------- (T1) TEQ.W Rn, #constT -------------- */
20971 if (INSN0(15,11) == BITS5(1,1,1,1,0)
20972 && ( INSN0(9,4) == BITS6(0,0,0,0,0,1) // TST
20973 || INSN0(9,4) == BITS6(0,0,1,0,0,1)) // TEQ
20974 && INSN1(15,15) == 0
20975 && INSN1(11,8) == BITS4(1,1,1,1)) {
20976 UInt rN
= INSN0(3,0);
20977 if (!isBadRegT(rN
)) { // yes, really, it's inconsistent with CMP.W
20978 Bool isTST
= INSN0(9,4) == BITS6(0,0,0,0,0,1);
20979 IRTemp argL
= newTemp(Ity_I32
);
20980 IRTemp argR
= newTemp(Ity_I32
);
20981 IRTemp res
= newTemp(Ity_I32
);
20982 IRTemp oldV
= newTemp(Ity_I32
);
20983 IRTemp oldC
= newTemp(Ity_I32
);
20985 UInt imm32
= thumbExpandImm_from_I0_I1(&updC
, insn0
, insn1
);
20986 assign(argL
, getIRegT(rN
));
20987 assign(argR
, mkU32(imm32
));
20988 assign(res
, binop(isTST
? Iop_And32
: Iop_Xor32
,
20989 mkexpr(argL
), mkexpr(argR
)));
20990 assign( oldV
, mk_armg_calculate_flag_v() );
20992 ? mkU32((imm32
>> 31) & 1)
20993 : mk_armg_calculate_flag_c() );
20994 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
, condT
);
20995 DIP("%s.w r%u, #%u\n", isTST
? "tst" : "teq", rN
, imm32
);
20996 goto decode_success
;
21000 /* -------------- (T3) SUB{S}.W Rd, Rn, #constT -------------- */
21001 /* -------------- (T3) RSB{S}.W Rd, Rn, #constT -------------- */
21002 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21003 && (INSN0(9,5) == BITS5(0,1,1,0,1) // SUB
21004 || INSN0(9,5) == BITS5(0,1,1,1,0)) // RSB
21005 && INSN1(15,15) == 0) {
21006 Bool isRSB
= INSN0(9,5) == BITS5(0,1,1,1,0);
21007 UInt bS
= INSN0(4,4);
21008 UInt rN
= INSN0(3,0);
21009 UInt rD
= INSN1(11,8);
21010 Bool valid
= !isBadRegT(rN
) && !isBadRegT(rD
);
21011 /* but allow "sub{s}.w reg, sp, #constT
21012 this is (T2) of "SUB (SP minus immediate)" */
21013 if (!valid
&& !isRSB
&& rN
== 13 && rD
!= 15)
21016 IRTemp argL
= newTemp(Ity_I32
);
21017 IRTemp argR
= newTemp(Ity_I32
);
21018 IRTemp res
= newTemp(Ity_I32
);
21019 UInt imm32
= thumbExpandImm_from_I0_I1(NULL
, insn0
, insn1
);
21020 assign(argL
, getIRegT(rN
));
21021 assign(argR
, mkU32(imm32
));
21023 ? binop(Iop_Sub32
, mkexpr(argR
), mkexpr(argL
))
21024 : binop(Iop_Sub32
, mkexpr(argL
), mkexpr(argR
)));
21025 putIRegT(rD
, mkexpr(res
), condT
);
21028 setFlags_D1_D2( ARMG_CC_OP_SUB
, argR
, argL
, condT
);
21030 setFlags_D1_D2( ARMG_CC_OP_SUB
, argL
, argR
, condT
);
21032 DIP("%s%s.w r%u, r%u, #%u\n",
21033 isRSB
? "rsb" : "sub", bS
== 1 ? "s" : "", rD
, rN
, imm32
);
21034 goto decode_success
;
21038 /* -------------- (T4) SUBW Rd, Rn, #uimm12 ------------------- */
21039 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21040 && INSN0(9,4) == BITS6(1,0,1,0,1,0)
21041 && INSN1(15,15) == 0) {
21042 UInt rN
= INSN0(3,0);
21043 UInt rD
= INSN1(11,8);
21044 Bool valid
= !isBadRegT(rN
) && !isBadRegT(rD
);
21045 /* but allow "subw sp, sp, #uimm12" */
21046 if (!valid
&& rD
== 13 && rN
== 13)
21049 IRTemp argL
= newTemp(Ity_I32
);
21050 IRTemp argR
= newTemp(Ity_I32
);
21051 IRTemp res
= newTemp(Ity_I32
);
21052 UInt imm12
= (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
21053 assign(argL
, getIRegT(rN
));
21054 assign(argR
, mkU32(imm12
));
21055 assign(res
, binop(Iop_Sub32
, mkexpr(argL
), mkexpr(argR
)));
21056 putIRegT(rD
, mkexpr(res
), condT
);
21057 DIP("subw r%u, r%u, #%u\n", rD
, rN
, imm12
);
21058 goto decode_success
;
21062 /* -------------- (T1) ADC{S}.W Rd, Rn, #constT -------------- */
21063 /* -------------- (T1) SBC{S}.W Rd, Rn, #constT -------------- */
21064 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21065 && ( INSN0(9,5) == BITS5(0,1,0,1,0) // ADC
21066 || INSN0(9,5) == BITS5(0,1,0,1,1)) // SBC
21067 && INSN1(15,15) == 0) {
21068 /* ADC: Rd = Rn + constT + oldC */
21069 /* SBC: Rd = Rn - constT - (oldC ^ 1) */
21070 UInt bS
= INSN0(4,4);
21071 UInt rN
= INSN0(3,0);
21072 UInt rD
= INSN1(11,8);
21073 if (!isBadRegT(rN
) && !isBadRegT(rD
)) {
21074 IRTemp argL
= newTemp(Ity_I32
);
21075 IRTemp argR
= newTemp(Ity_I32
);
21076 IRTemp res
= newTemp(Ity_I32
);
21077 IRTemp oldC
= newTemp(Ity_I32
);
21078 UInt imm32
= thumbExpandImm_from_I0_I1(NULL
, insn0
, insn1
);
21079 assign(argL
, getIRegT(rN
));
21080 assign(argR
, mkU32(imm32
));
21081 assign(oldC
, mk_armg_calculate_flag_c() );
21082 const HChar
* nm
= "???";
21083 switch (INSN0(9,5)) {
21084 case BITS5(0,1,0,1,0): // ADC
21088 binop(Iop_Add32
, mkexpr(argL
), mkexpr(argR
)),
21090 putIRegT(rD
, mkexpr(res
), condT
);
21092 setFlags_D1_D2_ND( ARMG_CC_OP_ADC
,
21093 argL
, argR
, oldC
, condT
);
21095 case BITS5(0,1,0,1,1): // SBC
21099 binop(Iop_Sub32
, mkexpr(argL
), mkexpr(argR
)),
21100 binop(Iop_Xor32
, mkexpr(oldC
), mkU32(1)) ));
21101 putIRegT(rD
, mkexpr(res
), condT
);
21103 setFlags_D1_D2_ND( ARMG_CC_OP_SBB
,
21104 argL
, argR
, oldC
, condT
);
21109 DIP("%s%s.w r%u, r%u, #%u\n",
21110 nm
, bS
== 1 ? "s" : "", rD
, rN
, imm32
);
21111 goto decode_success
;
21115 /* -------------- (T1) ORR{S}.W Rd, Rn, #constT -------------- */
21116 /* -------------- (T1) AND{S}.W Rd, Rn, #constT -------------- */
21117 /* -------------- (T1) BIC{S}.W Rd, Rn, #constT -------------- */
21118 /* -------------- (T1) EOR{S}.W Rd, Rn, #constT -------------- */
21119 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21120 && ( INSN0(9,5) == BITS5(0,0,0,1,0) // ORR
21121 || INSN0(9,5) == BITS5(0,0,0,0,0) // AND
21122 || INSN0(9,5) == BITS5(0,0,0,0,1) // BIC
21123 || INSN0(9,5) == BITS5(0,0,1,0,0) // EOR
21124 || INSN0(9,5) == BITS5(0,0,0,1,1)) // ORN
21125 && INSN1(15,15) == 0) {
21126 UInt bS
= INSN0(4,4);
21127 UInt rN
= INSN0(3,0);
21128 UInt rD
= INSN1(11,8);
21129 if (!isBadRegT(rN
) && !isBadRegT(rD
)) {
21130 Bool notArgR
= False
;
21131 IROp op
= Iop_INVALID
;
21132 const HChar
* nm
= "???";
21133 switch (INSN0(9,5)) {
21134 case BITS5(0,0,0,1,0): op
= Iop_Or32
; nm
= "orr"; break;
21135 case BITS5(0,0,0,0,0): op
= Iop_And32
; nm
= "and"; break;
21136 case BITS5(0,0,0,0,1): op
= Iop_And32
; nm
= "bic";
21137 notArgR
= True
; break;
21138 case BITS5(0,0,1,0,0): op
= Iop_Xor32
; nm
= "eor"; break;
21139 case BITS5(0,0,0,1,1): op
= Iop_Or32
; nm
= "orn";
21140 notArgR
= True
; break;
21141 default: vassert(0);
21143 IRTemp argL
= newTemp(Ity_I32
);
21144 IRTemp argR
= newTemp(Ity_I32
);
21145 IRTemp res
= newTemp(Ity_I32
);
21147 UInt imm32
= thumbExpandImm_from_I0_I1(&updC
, insn0
, insn1
);
21148 assign(argL
, getIRegT(rN
));
21149 assign(argR
, mkU32(notArgR
? ~imm32
: imm32
));
21150 assign(res
, binop(op
, mkexpr(argL
), mkexpr(argR
)));
21151 putIRegT(rD
, mkexpr(res
), condT
);
21153 IRTemp oldV
= newTemp(Ity_I32
);
21154 IRTemp oldC
= newTemp(Ity_I32
);
21155 assign( oldV
, mk_armg_calculate_flag_v() );
21157 ? mkU32((imm32
>> 31) & 1)
21158 : mk_armg_calculate_flag_c() );
21159 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
21162 DIP("%s%s.w r%u, r%u, #%u\n",
21163 nm
, bS
== 1 ? "s" : "", rD
, rN
, imm32
);
21164 goto decode_success
;
21168 /* ---------- (T3) ADD{S}.W Rd, Rn, Rm, {shift} ---------- */
21169 /* ---------- (T3) SUB{S}.W Rd, Rn, Rm, {shift} ---------- */
21170 /* ---------- (T3) RSB{S}.W Rd, Rn, Rm, {shift} ---------- */
21171 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
21172 && ( INSN0(8,5) == BITS4(1,0,0,0) // add subopc
21173 || INSN0(8,5) == BITS4(1,1,0,1) // sub subopc
21174 || INSN0(8,5) == BITS4(1,1,1,0)) // rsb subopc
21175 && INSN1(15,15) == 0) {
21176 UInt rN
= INSN0(3,0);
21177 UInt rD
= INSN1(11,8);
21178 UInt rM
= INSN1(3,0);
21179 UInt bS
= INSN0(4,4);
21180 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21181 UInt how
= INSN1(5,4);
21183 Bool valid
= !isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
);
21184 /* but allow "add.w reg, sp, reg, lsl #N for N=0..31
21185 (T3) "ADD (SP plus register) */
21186 if (!valid
&& INSN0(8,5) == BITS4(1,0,0,0) // add
21187 && rD
!= 15 && rN
== 13 && imm5
<= 31 && how
== 0) {
21190 /* also allow "sub.w reg, sp, reg lsl #N for N=0 .. 5
21191 (T1) "SUB (SP minus register) */
21192 if (!valid
&& INSN0(8,5) == BITS4(1,1,0,1) // sub
21193 && rD
!= 15 && rN
== 13 && imm5
<= 5 && how
== 0) {
21198 IROp op
= Iop_INVALID
;
21199 const HChar
* nm
= "???";
21200 switch (INSN0(8,5)) {
21201 case BITS4(1,0,0,0): op
= Iop_Add32
; nm
= "add"; break;
21202 case BITS4(1,1,0,1): op
= Iop_Sub32
; nm
= "sub"; break;
21203 case BITS4(1,1,1,0): op
= Iop_Sub32
; nm
= "rsb";
21204 swap
= True
; break;
21205 default: vassert(0);
21208 IRTemp argL
= newTemp(Ity_I32
);
21209 assign(argL
, getIRegT(rN
));
21211 IRTemp rMt
= newTemp(Ity_I32
);
21212 assign(rMt
, getIRegT(rM
));
21214 IRTemp argR
= newTemp(Ity_I32
);
21215 compute_result_and_C_after_shift_by_imm5(
21216 dis_buf
, &argR
, NULL
, rMt
, how
, imm5
, rM
21219 IRTemp res
= newTemp(Ity_I32
);
21221 ? binop(op
, mkexpr(argR
), mkexpr(argL
))
21222 : binop(op
, mkexpr(argL
), mkexpr(argR
)));
21224 putIRegT(rD
, mkexpr(res
), condT
);
21228 setFlags_D1_D2( ARMG_CC_OP_ADD
, argL
, argR
, condT
);
21232 setFlags_D1_D2( ARMG_CC_OP_SUB
, argR
, argL
, condT
);
21234 setFlags_D1_D2( ARMG_CC_OP_SUB
, argL
, argR
, condT
);
21241 DIP("%s%s.w r%u, r%u, %s\n",
21242 nm
, bS
? "s" : "", rD
, rN
, dis_buf
);
21243 goto decode_success
;
21247 /* ---------- (T3) ADC{S}.W Rd, Rn, Rm, {shift} ---------- */
21248 /* ---------- (T2) SBC{S}.W Rd, Rn, Rm, {shift} ---------- */
21249 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
21250 && ( INSN0(8,5) == BITS4(1,0,1,0) // adc subopc
21251 || INSN0(8,5) == BITS4(1,0,1,1)) // sbc subopc
21252 && INSN1(15,15) == 0) {
21253 /* ADC: Rd = Rn + shifter_operand + oldC */
21254 /* SBC: Rd = Rn - shifter_operand - (oldC ^ 1) */
21255 UInt rN
= INSN0(3,0);
21256 UInt rD
= INSN1(11,8);
21257 UInt rM
= INSN1(3,0);
21258 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
21259 UInt bS
= INSN0(4,4);
21260 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21261 UInt how
= INSN1(5,4);
21263 IRTemp argL
= newTemp(Ity_I32
);
21264 assign(argL
, getIRegT(rN
));
21266 IRTemp rMt
= newTemp(Ity_I32
);
21267 assign(rMt
, getIRegT(rM
));
21269 IRTemp oldC
= newTemp(Ity_I32
);
21270 assign(oldC
, mk_armg_calculate_flag_c());
21272 IRTemp argR
= newTemp(Ity_I32
);
21273 compute_result_and_C_after_shift_by_imm5(
21274 dis_buf
, &argR
, NULL
, rMt
, how
, imm5
, rM
21277 const HChar
* nm
= "???";
21278 IRTemp res
= newTemp(Ity_I32
);
21279 switch (INSN0(8,5)) {
21280 case BITS4(1,0,1,0): // ADC
21284 binop(Iop_Add32
, mkexpr(argL
), mkexpr(argR
)),
21286 putIRegT(rD
, mkexpr(res
), condT
);
21288 setFlags_D1_D2_ND( ARMG_CC_OP_ADC
,
21289 argL
, argR
, oldC
, condT
);
21291 case BITS4(1,0,1,1): // SBC
21295 binop(Iop_Sub32
, mkexpr(argL
), mkexpr(argR
)),
21296 binop(Iop_Xor32
, mkexpr(oldC
), mkU32(1)) ));
21297 putIRegT(rD
, mkexpr(res
), condT
);
21299 setFlags_D1_D2_ND( ARMG_CC_OP_SBB
,
21300 argL
, argR
, oldC
, condT
);
21306 DIP("%s%s.w r%u, r%u, %s\n",
21307 nm
, bS
? "s" : "", rD
, rN
, dis_buf
);
21308 goto decode_success
;
21312 /* ---------- (T3) AND{S}.W Rd, Rn, Rm, {shift} ---------- */
21313 /* ---------- (T3) ORR{S}.W Rd, Rn, Rm, {shift} ---------- */
21314 /* ---------- (T3) EOR{S}.W Rd, Rn, Rm, {shift} ---------- */
21315 /* ---------- (T3) BIC{S}.W Rd, Rn, Rm, {shift} ---------- */
21316 /* ---------- (T1) ORN{S}.W Rd, Rn, Rm, {shift} ---------- */
21317 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
21318 && ( INSN0(8,5) == BITS4(0,0,0,0) // and subopc
21319 || INSN0(8,5) == BITS4(0,0,1,0) // orr subopc
21320 || INSN0(8,5) == BITS4(0,1,0,0) // eor subopc
21321 || INSN0(8,5) == BITS4(0,0,0,1) // bic subopc
21322 || INSN0(8,5) == BITS4(0,0,1,1)) // orn subopc
21323 && INSN1(15,15) == 0) {
21324 UInt rN
= INSN0(3,0);
21325 UInt rD
= INSN1(11,8);
21326 UInt rM
= INSN1(3,0);
21327 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
21328 Bool notArgR
= False
;
21329 IROp op
= Iop_INVALID
;
21330 const HChar
* nm
= "???";
21331 switch (INSN0(8,5)) {
21332 case BITS4(0,0,0,0): op
= Iop_And32
; nm
= "and"; break;
21333 case BITS4(0,0,1,0): op
= Iop_Or32
; nm
= "orr"; break;
21334 case BITS4(0,1,0,0): op
= Iop_Xor32
; nm
= "eor"; break;
21335 case BITS4(0,0,0,1): op
= Iop_And32
; nm
= "bic";
21336 notArgR
= True
; break;
21337 case BITS4(0,0,1,1): op
= Iop_Or32
; nm
= "orn";
21338 notArgR
= True
; break;
21339 default: vassert(0);
21341 UInt bS
= INSN0(4,4);
21342 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21343 UInt how
= INSN1(5,4);
21345 IRTemp rNt
= newTemp(Ity_I32
);
21346 assign(rNt
, getIRegT(rN
));
21348 IRTemp rMt
= newTemp(Ity_I32
);
21349 assign(rMt
, getIRegT(rM
));
21351 IRTemp argR
= newTemp(Ity_I32
);
21352 IRTemp oldC
= bS
? newTemp(Ity_I32
) : IRTemp_INVALID
;
21354 compute_result_and_C_after_shift_by_imm5(
21355 dis_buf
, &argR
, bS
? &oldC
: NULL
, rMt
, how
, imm5
, rM
21358 IRTemp res
= newTemp(Ity_I32
);
21360 vassert(op
== Iop_And32
|| op
== Iop_Or32
);
21361 assign(res
, binop(op
, mkexpr(rNt
),
21362 unop(Iop_Not32
, mkexpr(argR
))));
21364 assign(res
, binop(op
, mkexpr(rNt
), mkexpr(argR
)));
21367 putIRegT(rD
, mkexpr(res
), condT
);
21369 IRTemp oldV
= newTemp(Ity_I32
);
21370 assign( oldV
, mk_armg_calculate_flag_v() );
21371 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
21375 DIP("%s%s.w r%u, r%u, %s\n",
21376 nm
, bS
? "s" : "", rD
, rN
, dis_buf
);
21377 goto decode_success
;
21381 /* -------------- (T?) LSL{S}.W Rd, Rn, Rm -------------- */
21382 /* -------------- (T?) LSR{S}.W Rd, Rn, Rm -------------- */
21383 /* -------------- (T?) ASR{S}.W Rd, Rn, Rm -------------- */
21384 /* -------------- (T?) ROR{S}.W Rd, Rn, Rm -------------- */
21385 if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,0,0)
21386 && INSN1(15,12) == BITS4(1,1,1,1)
21387 && INSN1(7,4) == BITS4(0,0,0,0)) {
21388 UInt how
= INSN0(6,5); // standard encoding
21389 UInt rN
= INSN0(3,0);
21390 UInt rD
= INSN1(11,8);
21391 UInt rM
= INSN1(3,0);
21392 UInt bS
= INSN0(4,4);
21393 Bool valid
= !isBadRegT(rN
) && !isBadRegT(rM
) && !isBadRegT(rD
);
21395 IRTemp rNt
= newTemp(Ity_I32
);
21396 IRTemp rMt
= newTemp(Ity_I32
);
21397 IRTemp res
= newTemp(Ity_I32
);
21398 IRTemp oldC
= bS
? newTemp(Ity_I32
) : IRTemp_INVALID
;
21399 IRTemp oldV
= bS
? newTemp(Ity_I32
) : IRTemp_INVALID
;
21400 const HChar
* nms
[4] = { "lsl", "lsr", "asr", "ror" };
21401 const HChar
* nm
= nms
[how
];
21402 assign(rNt
, getIRegT(rN
));
21403 assign(rMt
, getIRegT(rM
));
21404 compute_result_and_C_after_shift_by_reg(
21405 dis_buf
, &res
, bS
? &oldC
: NULL
,
21406 rNt
, how
, rMt
, rN
, rM
21409 assign(oldV
, mk_armg_calculate_flag_v());
21410 putIRegT(rD
, mkexpr(res
), condT
);
21412 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
21415 DIP("%s%s.w r%u, r%u, r%u\n",
21416 nm
, bS
? "s" : "", rD
, rN
, rM
);
21417 goto decode_success
;
21421 /* ------------ (T?) MOV{S}.W Rd, Rn, {shift} ------------ */
21422 /* ------------ (T?) MVN{S}.W Rd, Rn, {shift} ------------ */
21423 if ((INSN0(15,0) & 0xFFCF) == 0xEA4F
21424 && INSN1(15,15) == 0) {
21425 UInt rD
= INSN1(11,8);
21426 UInt rN
= INSN1(3,0);
21427 UInt bS
= INSN0(4,4);
21428 UInt isMVN
= INSN0(5,5);
21429 Bool regsOK
= (bS
|| isMVN
)
21430 ? (!isBadRegT(rD
) && !isBadRegT(rN
))
21431 : (rD
!= 15 && rN
!= 15 && (rD
!= 13 || rN
!= 13));
21433 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21434 UInt how
= INSN1(5,4);
21436 IRTemp rNt
= newTemp(Ity_I32
);
21437 assign(rNt
, getIRegT(rN
));
21439 IRTemp oldRn
= newTemp(Ity_I32
);
21440 IRTemp oldC
= bS
? newTemp(Ity_I32
) : IRTemp_INVALID
;
21441 compute_result_and_C_after_shift_by_imm5(
21442 dis_buf
, &oldRn
, bS
? &oldC
: NULL
, rNt
, how
, imm5
, rN
21445 IRTemp res
= newTemp(Ity_I32
);
21446 assign(res
, isMVN
? unop(Iop_Not32
, mkexpr(oldRn
))
21449 putIRegT(rD
, mkexpr(res
), condT
);
21451 IRTemp oldV
= newTemp(Ity_I32
);
21452 assign( oldV
, mk_armg_calculate_flag_v() );
21453 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
, condT
);
21455 DIP("%s%s.w r%u, %s\n",
21456 isMVN
? "mvn" : "mov", bS
? "s" : "", rD
, dis_buf
);
21457 goto decode_success
;
21461 /* -------------- (T?) TST.W Rn, Rm, {shift} -------------- */
21462 /* -------------- (T?) TEQ.W Rn, Rm, {shift} -------------- */
21463 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
21464 && ( INSN0(8,4) == BITS5(0,0,0,0,1) // TST
21465 || INSN0(8,4) == BITS5(0,1,0,0,1)) // TEQ
21466 && INSN1(15,15) == 0
21467 && INSN1(11,8) == BITS4(1,1,1,1)) {
21468 UInt rN
= INSN0(3,0);
21469 UInt rM
= INSN1(3,0);
21470 if (!isBadRegT(rN
) && !isBadRegT(rM
)) {
21471 Bool isTST
= INSN0(8,4) == BITS5(0,0,0,0,1);
21473 UInt how
= INSN1(5,4);
21474 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21476 IRTemp argL
= newTemp(Ity_I32
);
21477 assign(argL
, getIRegT(rN
));
21479 IRTemp rMt
= newTemp(Ity_I32
);
21480 assign(rMt
, getIRegT(rM
));
21482 IRTemp argR
= newTemp(Ity_I32
);
21483 IRTemp oldC
= newTemp(Ity_I32
);
21484 compute_result_and_C_after_shift_by_imm5(
21485 dis_buf
, &argR
, &oldC
, rMt
, how
, imm5
, rM
21488 IRTemp oldV
= newTemp(Ity_I32
);
21489 assign( oldV
, mk_armg_calculate_flag_v() );
21491 IRTemp res
= newTemp(Ity_I32
);
21492 assign(res
, binop(isTST
? Iop_And32
: Iop_Xor32
,
21493 mkexpr(argL
), mkexpr(argR
)));
21495 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
21497 DIP("%s.w r%u, %s\n", isTST
? "tst" : "teq", rN
, dis_buf
);
21498 goto decode_success
;
21502 /* -------------- (T3) CMP.W Rn, Rm, {shift} -------------- */
21503 /* -------------- (T2) CMN.W Rn, Rm, {shift} -------------- */
21504 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
21505 && ( INSN0(8,4) == BITS5(1,1,0,1,1) // CMP
21506 || INSN0(8,4) == BITS5(1,0,0,0,1)) // CMN
21507 && INSN1(15,15) == 0
21508 && INSN1(11,8) == BITS4(1,1,1,1)) {
21509 UInt rN
= INSN0(3,0);
21510 UInt rM
= INSN1(3,0);
21511 if (!isBadRegT(rN
) && !isBadRegT(rM
)) {
21512 Bool isCMN
= INSN0(8,4) == BITS5(1,0,0,0,1);
21513 UInt how
= INSN1(5,4);
21514 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21516 IRTemp argL
= newTemp(Ity_I32
);
21517 assign(argL
, getIRegT(rN
));
21519 IRTemp rMt
= newTemp(Ity_I32
);
21520 assign(rMt
, getIRegT(rM
));
21522 IRTemp argR
= newTemp(Ity_I32
);
21523 compute_result_and_C_after_shift_by_imm5(
21524 dis_buf
, &argR
, NULL
, rMt
, how
, imm5
, rM
21527 setFlags_D1_D2( isCMN
? ARMG_CC_OP_ADD
: ARMG_CC_OP_SUB
,
21528 argL
, argR
, condT
);
21530 DIP("%s.w r%u, %s\n", isCMN
? "cmn" : "cmp", rN
, dis_buf
);
21531 goto decode_success
;
21535 /* -------------- (T2) MOV{S}.W Rd, #constT -------------- */
21536 /* -------------- (T2) MVN{S}.W Rd, #constT -------------- */
21537 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21538 && ( INSN0(9,5) == BITS5(0,0,0,1,0) // MOV
21539 || INSN0(9,5) == BITS5(0,0,0,1,1)) // MVN
21540 && INSN0(3,0) == BITS4(1,1,1,1)
21541 && INSN1(15,15) == 0) {
21542 UInt rD
= INSN1(11,8);
21543 if (!isBadRegT(rD
)) {
21545 UInt bS
= INSN0(4,4);
21546 Bool isMVN
= INSN0(5,5) == 1;
21547 UInt imm32
= thumbExpandImm_from_I0_I1(&updC
, insn0
, insn1
);
21548 IRTemp res
= newTemp(Ity_I32
);
21549 assign(res
, mkU32(isMVN
? ~imm32
: imm32
));
21550 putIRegT(rD
, mkexpr(res
), condT
);
21552 IRTemp oldV
= newTemp(Ity_I32
);
21553 IRTemp oldC
= newTemp(Ity_I32
);
21554 assign( oldV
, mk_armg_calculate_flag_v() );
21556 ? mkU32((imm32
>> 31) & 1)
21557 : mk_armg_calculate_flag_c() );
21558 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
21561 DIP("%s%s.w r%u, #%u\n",
21562 isMVN
? "mvn" : "mov", bS
? "s" : "", rD
, imm32
);
21563 goto decode_success
;
21567 /* -------------- (T3) MOVW Rd, #imm16 -------------- */
21568 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21569 && INSN0(9,4) == BITS6(1,0,0,1,0,0)
21570 && INSN1(15,15) == 0) {
21571 UInt rD
= INSN1(11,8);
21572 if (!isBadRegT(rD
)) {
21573 UInt imm16
= (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
21574 | (INSN1(14,12) << 8) | INSN1(7,0);
21575 putIRegT(rD
, mkU32(imm16
), condT
);
21576 DIP("movw r%u, #%u\n", rD
, imm16
);
21577 goto decode_success
;
21581 /* ---------------- MOVT Rd, #imm16 ---------------- */
21582 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21583 && INSN0(9,4) == BITS6(1,0,1,1,0,0)
21584 && INSN1(15,15) == 0) {
21585 UInt rD
= INSN1(11,8);
21586 if (!isBadRegT(rD
)) {
21587 UInt imm16
= (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
21588 | (INSN1(14,12) << 8) | INSN1(7,0);
21589 IRTemp res
= newTemp(Ity_I32
);
21592 binop(Iop_And32
, getIRegT(rD
), mkU32(0xFFFF)),
21593 mkU32(imm16
<< 16)));
21594 putIRegT(rD
, mkexpr(res
), condT
);
21595 DIP("movt r%u, #%u\n", rD
, imm16
);
21596 goto decode_success
;
21600 /* ---------------- LD/ST reg+/-#imm8 ---------------- */
21601 /* Loads and stores of the form:
21602 op Rt, [Rn, #-imm8] or
21603 op Rt, [Rn], #+/-imm8 or
21604 op Rt, [Rn, #+/-imm8]!
21606 ldrb ldrh ldr ldrsb ldrsh
21609 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) && INSN1(11,11) == 1) {
21611 Bool syned
= False
;
21613 IRType ty
= Ity_I8
;
21614 const HChar
* nm
= "???";
21616 switch (INSN0(8,4)) {
21617 case BITS5(0,0,0,0,0): // strb
21618 nm
= "strb"; isST
= True
; break;
21619 case BITS5(0,0,0,0,1): // ldrb
21620 nm
= "ldrb"; break;
21621 case BITS5(1,0,0,0,1): // ldrsb
21622 nm
= "ldrsb"; syned
= True
; break;
21623 case BITS5(0,0,0,1,0): // strh
21624 nm
= "strh"; ty
= Ity_I16
; isST
= True
; break;
21625 case BITS5(0,0,0,1,1): // ldrh
21626 nm
= "ldrh"; ty
= Ity_I16
; break;
21627 case BITS5(1,0,0,1,1): // ldrsh
21628 nm
= "ldrsh"; ty
= Ity_I16
; syned
= True
; break;
21629 case BITS5(0,0,1,0,0): // str
21630 nm
= "str"; ty
= Ity_I32
; isST
= True
; break;
21631 case BITS5(0,0,1,0,1):
21632 nm
= "ldr"; ty
= Ity_I32
; break; // ldr
21634 valid
= False
; break;
21637 UInt rN
= INSN0(3,0);
21638 UInt rT
= INSN1(15,12);
21639 UInt bP
= INSN1(10,10);
21640 UInt bU
= INSN1(9,9);
21641 UInt bW
= INSN1(8,8);
21642 UInt imm8
= INSN1(7,0);
21643 Bool loadsPC
= False
;
21646 if (bP
== 1 && bU
== 1 && bW
== 0)
21648 if (bP
== 0 && bW
== 0)
21652 if (bW
== 1 && rN
== rT
)
21654 if (ty
== Ity_I8
|| ty
== Ity_I16
) {
21658 /* ty == Ity_I32 */
21659 if (isST
&& rT
== 15)
21661 if (!isST
&& rT
== 15)
21667 // if it's a branch, it can't happen in the middle of an IT block
21668 // Also, if it is a branch, make it unconditional at this point.
21669 // Doing conditional branches in-line is too complex (for now)
21671 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
21673 mk_skip_over_T32_if_cond_is_false(condT
);
21674 condT
= IRTemp_INVALID
;
21678 IRTemp preAddr
= newTemp(Ity_I32
);
21679 assign(preAddr
, getIRegT(rN
));
21681 IRTemp postAddr
= newTemp(Ity_I32
);
21682 assign(postAddr
, binop(bU
== 1 ? Iop_Add32
: Iop_Sub32
,
21683 mkexpr(preAddr
), mkU32(imm8
)));
21685 IRTemp transAddr
= bP
== 1 ? postAddr
: preAddr
;
21689 /* Store. If necessary, update the base register before
21690 the store itself, so that the common idiom of "str rX,
21691 [sp, #-4]!" (store rX at sp-4, then do new sp = sp-4,
21692 a.k.a "push rX") doesn't cause Memcheck to complain
21693 that the access is below the stack pointer. Also, not
21694 updating sp before the store confuses Valgrind's
21695 dynamic stack-extending logic. So do it before the
21696 store. Hence we need to snarf the store data before
21697 doing the basereg update. */
21699 /* get hold of the data to be stored */
21700 IRTemp oldRt
= newTemp(Ity_I32
);
21701 assign(oldRt
, getIRegT(rT
));
21703 /* Update Rn if necessary. */
21705 vassert(rN
!= rT
); // assured by validity check above
21706 putIRegT(rN
, mkexpr(postAddr
), condT
);
21709 /* generate the transfer */
21710 IRExpr
* data
= NULL
;
21713 data
= unop(Iop_32to8
, mkexpr(oldRt
));
21716 data
= unop(Iop_32to16
, mkexpr(oldRt
));
21719 data
= mkexpr(oldRt
);
21724 storeGuardedLE(mkexpr(transAddr
), data
, condT
);
21729 IRTemp llOldRt
= newTemp(Ity_I32
);
21730 assign(llOldRt
, llGetIReg(rT
));
21732 /* generate the transfer */
21733 IRTemp newRt
= newTemp(Ity_I32
);
21734 IRLoadGOp widen
= ILGop_INVALID
;
21737 widen
= syned
? ILGop_8Sto32
: ILGop_8Uto32
; break;
21739 widen
= syned
? ILGop_16Sto32
: ILGop_16Uto32
; break;
21741 widen
= ILGop_Ident32
; break;
21745 loadGuardedLE(newRt
, widen
,
21746 mkexpr(transAddr
), mkexpr(llOldRt
), condT
);
21749 /* We'll do the write to the PC just below */
21752 /* IRTemp_INVALID is OK here because in the case where
21753 condT is false at run time, we're just putting the
21754 old rT value back. */
21755 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
21758 /* Update Rn if necessary. */
21760 vassert(rN
!= rT
); // assured by validity check above
21761 putIRegT(rN
, mkexpr(postAddr
), condT
);
21765 /* Presumably this is an interworking branch. */
21766 vassert(rN
!= 15); // assured by validity check above
21768 vassert(condT
== IRTemp_INVALID
); /* due to check above */
21769 llPutIReg(15, mkexpr(newRt
));
21770 dres
.jk_StopHere
= Ijk_Boring
; /* or _Ret ? */
21771 dres
.whatNext
= Dis_StopHere
;
21775 if (bP
== 1 && bW
== 0) {
21776 DIP("%s.w r%u, [r%u, #%c%u]\n",
21777 nm
, rT
, rN
, bU
? '+' : '-', imm8
);
21779 else if (bP
== 1 && bW
== 1) {
21780 DIP("%s.w r%u, [r%u, #%c%u]!\n",
21781 nm
, rT
, rN
, bU
? '+' : '-', imm8
);
21784 vassert(bP
== 0 && bW
== 1);
21785 DIP("%s.w r%u, [r%u], #%c%u\n",
21786 nm
, rT
, rN
, bU
? '+' : '-', imm8
);
21789 goto decode_success
;
21793 /* ------------- LD/ST reg+(reg<<imm2) ------------- */
21794 /* Loads and stores of the form:
21795 op Rt, [Rn, Rm, LSL #imm8]
21797 ldrb ldrh ldr ldrsb ldrsh
21800 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)
21801 && INSN1(11,6) == BITS6(0,0,0,0,0,0)) {
21803 Bool syned
= False
;
21805 IRType ty
= Ity_I8
;
21806 const HChar
* nm
= "???";
21808 switch (INSN0(8,4)) {
21809 case BITS5(0,0,0,0,0): // strb
21810 nm
= "strb"; isST
= True
; break;
21811 case BITS5(0,0,0,0,1): // ldrb
21812 nm
= "ldrb"; break;
21813 case BITS5(1,0,0,0,1): // ldrsb
21814 nm
= "ldrsb"; syned
= True
; break;
21815 case BITS5(0,0,0,1,0): // strh
21816 nm
= "strh"; ty
= Ity_I16
; isST
= True
; break;
21817 case BITS5(0,0,0,1,1): // ldrh
21818 nm
= "ldrh"; ty
= Ity_I16
; break;
21819 case BITS5(1,0,0,1,1): // ldrsh
21820 nm
= "ldrsh"; ty
= Ity_I16
; syned
= True
; break;
21821 case BITS5(0,0,1,0,0): // str
21822 nm
= "str"; ty
= Ity_I32
; isST
= True
; break;
21823 case BITS5(0,0,1,0,1):
21824 nm
= "ldr"; ty
= Ity_I32
; break; // ldr
21826 valid
= False
; break;
21829 UInt rN
= INSN0(3,0);
21830 UInt rM
= INSN1(3,0);
21831 UInt rT
= INSN1(15,12);
21832 UInt imm2
= INSN1(5,4);
21833 Bool loadsPC
= False
;
21835 if (ty
== Ity_I8
|| ty
== Ity_I16
) {
21836 /* all 8- and 16-bit load and store cases have the
21837 same exclusion set. */
21838 if (rN
== 15 || isBadRegT(rT
) || isBadRegT(rM
))
21841 vassert(ty
== Ity_I32
);
21842 if (rN
== 15 || isBadRegT(rM
))
21844 if (isST
&& rT
== 15)
21846 /* If it is a load and rT is 15, that's only allowable if we
21847 not in an IT block, or are the last in it. Need to insert
21848 a dynamic check for that. */
21849 if (!isST
&& rT
== 15)
21854 // if it's a branch, it can't happen in the middle of an IT block
21855 // Also, if it is a branch, make it unconditional at this point.
21856 // Doing conditional branches in-line is too complex (for now)
21858 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
21860 mk_skip_over_T32_if_cond_is_false(condT
);
21861 condT
= IRTemp_INVALID
;
21865 IRTemp transAddr
= newTemp(Ity_I32
);
21869 binop(Iop_Shl32
, getIRegT(rM
), mkU8(imm2
)) ));
21873 /* get hold of the data to be stored */
21874 IRTemp oldRt
= newTemp(Ity_I32
);
21875 assign(oldRt
, getIRegT(rT
));
21877 /* generate the transfer */
21878 IRExpr
* data
= NULL
;
21881 data
= unop(Iop_32to8
, mkexpr(oldRt
));
21884 data
= unop(Iop_32to16
, mkexpr(oldRt
));
21887 data
= mkexpr(oldRt
);
21892 storeGuardedLE(mkexpr(transAddr
), data
, condT
);
21897 IRTemp llOldRt
= newTemp(Ity_I32
);
21898 assign(llOldRt
, llGetIReg(rT
));
21900 /* generate the transfer */
21901 IRTemp newRt
= newTemp(Ity_I32
);
21902 IRLoadGOp widen
= ILGop_INVALID
;
21905 widen
= syned
? ILGop_8Sto32
: ILGop_8Uto32
; break;
21907 widen
= syned
? ILGop_16Sto32
: ILGop_16Uto32
; break;
21909 widen
= ILGop_Ident32
; break;
21913 loadGuardedLE(newRt
, widen
,
21914 mkexpr(transAddr
), mkexpr(llOldRt
), condT
);
21918 /* We'll do the write to the PC just below */
21921 /* IRTemp_INVALID is OK here because in the case where
21922 condT is false at run time, we're just putting the
21923 old rT value back. */
21924 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
21928 /* Presumably this is an interworking branch. */
21929 vassert(rN
!= 15); // assured by validity check above
21931 vassert(condT
== IRTemp_INVALID
); /* due to check above */
21932 llPutIReg(15, mkexpr(newRt
));
21933 dres
.jk_StopHere
= Ijk_Boring
; /* or _Ret ? */
21934 dres
.whatNext
= Dis_StopHere
;
21938 DIP("%s.w r%u, [r%u, r%u, LSL #%u]\n",
21939 nm
, rT
, rN
, rM
, imm2
);
21941 goto decode_success
;
21945 /* --------------- LD/ST reg+imm12 --------------- */
21946 /* Loads and stores of the form:
21947 op Rt, [Rn, #+-imm12]
21949 ldrb ldrh ldr ldrsb ldrsh
21952 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)) {
21954 Bool syned
= INSN0(8,8) == 1;
21956 IRType ty
= Ity_I8
;
21957 UInt bU
= INSN0(7,7); // 1: +imm 0: -imm
21958 // -imm is only supported by literal versions
21959 const HChar
* nm
= "???";
21961 switch (INSN0(6,4)) {
21962 case BITS3(0,0,0): // strb
21963 nm
= "strb"; isST
= True
; break;
21964 case BITS3(0,0,1): // ldrb
21965 nm
= syned
? "ldrsb" : "ldrb"; break;
21966 case BITS3(0,1,0): // strh
21967 nm
= "strh"; ty
= Ity_I16
; isST
= True
; break;
21968 case BITS3(0,1,1): // ldrh
21969 nm
= syned
? "ldrsh" : "ldrh"; ty
= Ity_I16
; break;
21970 case BITS3(1,0,0): // str
21971 nm
= "str"; ty
= Ity_I32
; isST
= True
; break;
21973 nm
= "ldr"; ty
= Ity_I32
; break; // ldr
21975 valid
= False
; break;
21978 UInt rN
= INSN0(3,0);
21979 UInt rT
= INSN1(15,12);
21980 UInt imm12
= INSN1(11,0);
21981 Bool loadsPC
= False
;
21983 if (rN
!= 15 && bU
== 0) {
21984 // only pc supports #-imm12
21989 if (syned
) valid
= False
;
21990 if (rN
== 15 || rT
== 15)
21993 /* For a 32-bit load, rT == 15 is only allowable if we are not
21994 in an IT block, or are the last in it. Need to insert
21995 a dynamic check for that. Also, in this particular
21996 case, rN == 15 is allowable. In this case however, the
21997 value obtained for rN is (apparently)
21998 "word-align(address of current insn + 4)". */
22002 else // Can't do it for B/H loads
22008 // if it's a branch, it can't happen in the middle of an IT block
22009 // Also, if it is a branch, make it unconditional at this point.
22010 // Doing conditional branches in-line is too complex (for now)
22012 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
22014 mk_skip_over_T32_if_cond_is_false(condT
);
22015 condT
= IRTemp_INVALID
;
22019 IRTemp rNt
= newTemp(Ity_I32
);
22022 assign(rNt
, binop(Iop_And32
, getIRegT(15), mkU32(~3)));
22024 assign(rNt
, getIRegT(rN
));
22027 IRTemp transAddr
= newTemp(Ity_I32
);
22029 binop(bU
== 1 ? Iop_Add32
: Iop_Sub32
,
22030 mkexpr(rNt
), mkU32(imm12
)));
22032 IRTemp oldRt
= newTemp(Ity_I32
);
22033 assign(oldRt
, getIRegT(rT
));
22035 IRTemp llOldRt
= newTemp(Ity_I32
);
22036 assign(llOldRt
, llGetIReg(rT
));
22039 IRExpr
* data
= NULL
;
22042 data
= unop(Iop_32to8
, mkexpr(oldRt
));
22045 data
= unop(Iop_32to16
, mkexpr(oldRt
));
22048 data
= mkexpr(oldRt
);
22053 storeGuardedLE(mkexpr(transAddr
), data
, condT
);
22055 IRTemp newRt
= newTemp(Ity_I32
);
22056 IRLoadGOp widen
= ILGop_INVALID
;
22059 widen
= syned
? ILGop_8Sto32
: ILGop_8Uto32
; break;
22061 widen
= syned
? ILGop_16Sto32
: ILGop_16Uto32
; break;
22063 widen
= ILGop_Ident32
; break;
22067 loadGuardedLE(newRt
, widen
,
22068 mkexpr(transAddr
), mkexpr(llOldRt
), condT
);
22071 /* We'll do the write to the PC just below */
22074 /* IRTemp_INVALID is OK here because in the case where
22075 condT is false at run time, we're just putting the
22076 old rT value back. */
22077 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
22081 /* Presumably this is an interworking branch. */
22083 vassert(condT
== IRTemp_INVALID
); /* due to check above */
22084 llPutIReg(15, mkexpr(newRt
));
22085 dres
.jk_StopHere
= Ijk_Boring
;
22086 dres
.whatNext
= Dis_StopHere
;
22090 DIP("%s.w r%u, [r%u, +#%u]\n", nm
, rT
, rN
, imm12
);
22092 goto decode_success
;
22096 /* -------------- LDRD/STRD reg+/-#imm8 -------------- */
22097 /* Doubleword loads and stores of the form:
22098 ldrd/strd Rt, Rt2, [Rn, #+/-imm8] or
22099 ldrd/strd Rt, Rt2, [Rn], #+/-imm8 or
22100 ldrd/strd Rt, Rt2, [Rn, #+/-imm8]!
22102 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,0) && INSN0(6,6) == 1) {
22103 UInt bP
= INSN0(8,8);
22104 UInt bU
= INSN0(7,7);
22105 UInt bW
= INSN0(5,5);
22106 UInt bL
= INSN0(4,4); // 1: load 0: store
22107 UInt rN
= INSN0(3,0);
22108 UInt rT
= INSN1(15,12);
22109 UInt rT2
= INSN1(11,8);
22110 UInt imm8
= INSN1(7,0);
22113 if (bP
== 0 && bW
== 0) valid
= False
;
22114 if (bW
== 1 && (rN
== rT
|| rN
== rT2
)) valid
= False
;
22115 if (isBadRegT(rT
) || isBadRegT(rT2
)) valid
= False
;
22116 if (bL
== 1 && rT
== rT2
) valid
= False
;
22117 /* It's OK to use PC as the base register only in the
22118 following case: ldrd Rt, Rt2, [PC, #+/-imm8] */
22119 if (rN
== 15 && (bL
== 0/*store*/
22120 || bW
== 1/*wb*/)) valid
= False
;
22123 IRTemp preAddr
= newTemp(Ity_I32
);
22124 assign(preAddr
, 15 == rN
22125 ? binop(Iop_And32
, getIRegT(15), mkU32(~3U))
22128 IRTemp postAddr
= newTemp(Ity_I32
);
22129 assign(postAddr
, binop(bU
== 1 ? Iop_Add32
: Iop_Sub32
,
22130 mkexpr(preAddr
), mkU32(imm8
<< 2)));
22132 IRTemp transAddr
= bP
== 1 ? postAddr
: preAddr
;
22134 /* For almost all cases, we do the writeback after the transfers.
22135 However, that leaves the stack "uncovered" in cases like:
22137 strd rD, [sp, #-16]
22138 In which case, do the writeback to SP now, instead of later.
22139 This is bad in that it makes the insn non-restartable if the
22140 accesses fault, but at least keeps Memcheck happy. */
22141 Bool writeback_already_done
= False
;
22142 if (bL
== 0/*store*/ && bW
== 1/*wb*/
22143 && rN
== 13 && rN
!= rT
&& rN
!= rT2
22144 && bU
== 0/*minus*/
22145 && ((imm8
<< 2) == 8 || (imm8
<< 2) == 16)) {
22146 putIRegT(rN
, mkexpr(postAddr
), condT
);
22147 writeback_already_done
= True
;
22151 IRTemp oldRt
= newTemp(Ity_I32
);
22152 IRTemp oldRt2
= newTemp(Ity_I32
);
22153 assign(oldRt
, getIRegT(rT
));
22154 assign(oldRt2
, getIRegT(rT2
));
22155 storeGuardedLE( mkexpr(transAddr
),
22156 mkexpr(oldRt
), condT
);
22157 storeGuardedLE( binop(Iop_Add32
, mkexpr(transAddr
), mkU32(4)),
22158 mkexpr(oldRt2
), condT
);
22160 IRTemp oldRt
= newTemp(Ity_I32
);
22161 IRTemp oldRt2
= newTemp(Ity_I32
);
22162 IRTemp newRt
= newTemp(Ity_I32
);
22163 IRTemp newRt2
= newTemp(Ity_I32
);
22164 assign(oldRt
, llGetIReg(rT
));
22165 assign(oldRt2
, llGetIReg(rT2
));
22166 loadGuardedLE( newRt
, ILGop_Ident32
,
22168 mkexpr(oldRt
), condT
);
22169 loadGuardedLE( newRt2
, ILGop_Ident32
,
22170 binop(Iop_Add32
, mkexpr(transAddr
), mkU32(4)),
22171 mkexpr(oldRt2
), condT
);
22172 /* Put unconditionally, since we already switched on the condT
22173 in the guarded loads. */
22174 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
22175 putIRegT(rT2
, mkexpr(newRt2
), IRTemp_INVALID
);
22178 if (bW
== 1 && !writeback_already_done
) {
22179 putIRegT(rN
, mkexpr(postAddr
), condT
);
22182 const HChar
* nm
= bL
? "ldrd" : "strd";
22184 if (bP
== 1 && bW
== 0) {
22185 DIP("%s.w r%u, r%u, [r%u, #%c%u]\n",
22186 nm
, rT
, rT2
, rN
, bU
? '+' : '-', imm8
<< 2);
22188 else if (bP
== 1 && bW
== 1) {
22189 DIP("%s.w r%u, r%u, [r%u, #%c%u]!\n",
22190 nm
, rT
, rT2
, rN
, bU
? '+' : '-', imm8
<< 2);
22193 vassert(bP
== 0 && bW
== 1);
22194 DIP("%s.w r%u, r%u, [r%u], #%c%u\n",
22195 nm
, rT
, rT2
, rN
, bU
? '+' : '-', imm8
<< 2);
22198 goto decode_success
;
22202 /* -------------- (T3) Bcond.W label -------------- */
22203 /* This variant carries its own condition, so can't be part of an
22205 if (INSN0(15,11) == BITS5(1,1,1,1,0)
22206 && INSN1(15,14) == BITS2(1,0)
22207 && INSN1(12,12) == 0) {
22208 UInt cond
= INSN0(9,6);
22209 if (cond
!= ARMCondAL
&& cond
!= ARMCondNV
) {
22211 = (INSN0(10,10) << (1 + 1 + 6 + 11 + 1))
22212 | (INSN1(11,11) << (1 + 6 + 11 + 1))
22213 | (INSN1(13,13) << (6 + 11 + 1))
22214 | (INSN0(5,0) << (11 + 1))
22215 | (INSN1(10,0) << 1);
22217 Int simm21
= (Int
)uimm21
;
22220 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
22221 UInt dst
= simm21
+ guest_R15_curr_instr_notENC
+ 4;
22223 /* Not allowed in an IT block; SIGILL if so. */
22224 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
22226 IRTemp kondT
= newTemp(Ity_I32
);
22227 assign( kondT
, mk_armg_calculate_condition(cond
) );
22228 stmt( IRStmt_Exit( unop(Iop_32to1
, mkexpr(kondT
)),
22230 IRConst_U32(dst
| 1/*CPSR.T*/),
22232 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC
+ 4)
22234 dres
.jk_StopHere
= Ijk_Boring
;
22235 dres
.whatNext
= Dis_StopHere
;
22236 DIP("b%s.w 0x%x\n", nCC(cond
), dst
);
22237 goto decode_success
;
22241 /* ---------------- (T4) B.W label ---------------- */
22242 /* ... whereas this variant doesn't carry its own condition, so it
22243 has to be either unconditional or the conditional by virtue of
22244 being the last in an IT block. The upside is that there's 4
22245 more bits available for the jump offset, so it has a 16-times
22246 greater branch range than the T3 variant. */
22247 if (INSN0(15,11) == BITS5(1,1,1,1,0)
22248 && INSN1(15,14) == BITS2(1,0)
22249 && INSN1(12,12) == 1) {
22251 UInt bS
= INSN0(10,10);
22252 UInt bJ1
= INSN1(13,13);
22253 UInt bJ2
= INSN1(11,11);
22254 UInt bI1
= 1 ^ (bJ1
^ bS
);
22255 UInt bI2
= 1 ^ (bJ2
^ bS
);
22257 = (bS
<< (1 + 1 + 10 + 11 + 1))
22258 | (bI1
<< (1 + 10 + 11 + 1))
22259 | (bI2
<< (10 + 11 + 1))
22260 | (INSN0(9,0) << (11 + 1))
22261 | (INSN1(10,0) << 1);
22263 Int simm25
= (Int
)uimm25
;
22266 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
22267 UInt dst
= simm25
+ guest_R15_curr_instr_notENC
+ 4;
22269 /* If in an IT block, must be the last insn. */
22270 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
22273 mk_skip_over_T32_if_cond_is_false(condT
);
22274 condT
= IRTemp_INVALID
;
22278 llPutIReg(15, mkU32( dst
| 1 /*CPSR.T*/ ));
22279 dres
.jk_StopHere
= Ijk_Boring
;
22280 dres
.whatNext
= Dis_StopHere
;
22281 DIP("b.w 0x%x\n", dst
);
22282 goto decode_success
;
22286 /* ------------------ TBB, TBH ------------------ */
22287 if (INSN0(15,4) == 0xE8D && INSN1(15,5) == 0x780) {
22288 UInt rN
= INSN0(3,0);
22289 UInt rM
= INSN1(3,0);
22290 UInt bH
= INSN1(4,4);
22291 if (bH
/*ATC*/ || (rN
!= 13 && !isBadRegT(rM
))) {
22292 /* Must be last or not-in IT block */
22293 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
22295 mk_skip_over_T32_if_cond_is_false(condT
);
22296 condT
= IRTemp_INVALID
;
22301 bH
? binop(Iop_Shl32
, getIRegT(rM
), mkU8(1))
22304 IRTemp delta
= newTemp(Ity_I32
);
22306 assign(delta
, unop(Iop_16Uto32
, loadLE(Ity_I16
, ea
)));
22308 assign(delta
, unop(Iop_8Uto32
, loadLE(Ity_I8
, ea
)));
22316 binop(Iop_Shl32
, mkexpr(delta
), mkU8(1))
22320 dres
.jk_StopHere
= Ijk_Boring
;
22321 dres
.whatNext
= Dis_StopHere
;
22322 DIP("tb%c [r%u, r%u%s]\n",
22323 bH
? 'h' : 'b', rN
, rM
, bH
? ", LSL #1" : "");
22324 goto decode_success
;
22328 /* ------------------ UBFX ------------------ */
22329 /* ------------------ SBFX ------------------ */
22330 /* There's also ARM versions of same, but it doesn't seem worth the
22331 hassle to common up the handling (it's only a couple of C
22333 if ((INSN0(15,4) == 0xF3C // UBFX
22334 || INSN0(15,4) == 0xF34) // SBFX
22335 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
22336 UInt rN
= INSN0(3,0);
22337 UInt rD
= INSN1(11,8);
22338 UInt lsb
= (INSN1(14,12) << 2) | INSN1(7,6);
22339 UInt wm1
= INSN1(4,0);
22340 UInt msb
= lsb
+ wm1
;
22341 if (!isBadRegT(rD
) && !isBadRegT(rN
) && msb
<= 31) {
22342 Bool isU
= INSN0(15,4) == 0xF3C;
22343 IRTemp src
= newTemp(Ity_I32
);
22344 IRTemp tmp
= newTemp(Ity_I32
);
22345 IRTemp res
= newTemp(Ity_I32
);
22346 UInt mask
= ((1 << wm1
) - 1) + (1 << wm1
);
22347 vassert(msb
>= 0 && msb
<= 31);
22348 vassert(mask
!= 0); // guaranteed by msb being in 0 .. 31 inclusive
22350 assign(src
, getIRegT(rN
));
22351 assign(tmp
, binop(Iop_And32
,
22352 binop(Iop_Shr32
, mkexpr(src
), mkU8(lsb
)),
22354 assign(res
, binop(isU
? Iop_Shr32
: Iop_Sar32
,
22355 binop(Iop_Shl32
, mkexpr(tmp
), mkU8(31-wm1
)),
22358 putIRegT(rD
, mkexpr(res
), condT
);
22360 DIP("%s r%u, r%u, #%u, #%u\n",
22361 isU
? "ubfx" : "sbfx", rD
, rN
, lsb
, wm1
+ 1);
22362 goto decode_success
;
22366 /* ------------------ UXTB ------------------ */
22367 /* ------------------ UXTH ------------------ */
22368 /* ------------------ SXTB ------------------ */
22369 /* ------------------ SXTH ------------------ */
22370 /* ----------------- UXTB16 ----------------- */
22371 /* ----------------- SXTB16 ----------------- */
22372 /* FIXME: this is an exact duplicate of the ARM version. They
22373 should be commoned up. */
22374 if ((INSN0(15,0) == 0xFA5F // UXTB
22375 || INSN0(15,0) == 0xFA1F // UXTH
22376 || INSN0(15,0) == 0xFA4F // SXTB
22377 || INSN0(15,0) == 0xFA0F // SXTH
22378 || INSN0(15,0) == 0xFA3F // UXTB16
22379 || INSN0(15,0) == 0xFA2F) // SXTB16
22380 && INSN1(15,12) == BITS4(1,1,1,1)
22381 && INSN1(7,6) == BITS2(1,0)) {
22382 UInt rD
= INSN1(11,8);
22383 UInt rM
= INSN1(3,0);
22384 UInt rot
= INSN1(5,4);
22385 if (!isBadRegT(rD
) && !isBadRegT(rM
)) {
22386 const HChar
* nm
= "???";
22387 IRTemp srcT
= newTemp(Ity_I32
);
22388 IRTemp rotT
= newTemp(Ity_I32
);
22389 IRTemp dstT
= newTemp(Ity_I32
);
22390 assign(srcT
, getIRegT(rM
));
22391 assign(rotT
, genROR32(srcT
, 8 * rot
));
22392 switch (INSN0(15,0)) {
22393 case 0xFA5F: // UXTB
22395 assign(dstT
, unop(Iop_8Uto32
,
22396 unop(Iop_32to8
, mkexpr(rotT
))));
22398 case 0xFA1F: // UXTH
22400 assign(dstT
, unop(Iop_16Uto32
,
22401 unop(Iop_32to16
, mkexpr(rotT
))));
22403 case 0xFA4F: // SXTB
22405 assign(dstT
, unop(Iop_8Sto32
,
22406 unop(Iop_32to8
, mkexpr(rotT
))));
22408 case 0xFA0F: // SXTH
22410 assign(dstT
, unop(Iop_16Sto32
,
22411 unop(Iop_32to16
, mkexpr(rotT
))));
22413 case 0xFA3F: // UXTB16
22415 assign(dstT
, binop(Iop_And32
, mkexpr(rotT
),
22416 mkU32(0x00FF00FF)));
22418 case 0xFA2F: { // SXTB16
22420 IRTemp lo32
= newTemp(Ity_I32
);
22421 IRTemp hi32
= newTemp(Ity_I32
);
22422 assign(lo32
, binop(Iop_And32
, mkexpr(rotT
), mkU32(0xFF)));
22423 assign(hi32
, binop(Iop_Shr32
, mkexpr(rotT
), mkU8(16)));
22429 unop(Iop_32to8
, mkexpr(lo32
))),
22433 unop(Iop_32to8
, mkexpr(hi32
))),
22441 putIRegT(rD
, mkexpr(dstT
), condT
);
22442 DIP("%s r%u, r%u, ror #%u\n", nm
, rD
, rM
, 8 * rot
);
22443 goto decode_success
;
22447 /* -------------- MUL.W Rd, Rn, Rm -------------- */
22448 if (INSN0(15,4) == 0xFB0
22449 && (INSN1(15,0) & 0xF0F0) == 0xF000) {
22450 UInt rN
= INSN0(3,0);
22451 UInt rD
= INSN1(11,8);
22452 UInt rM
= INSN1(3,0);
22453 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22454 IRTemp res
= newTemp(Ity_I32
);
22455 assign(res
, binop(Iop_Mul32
, getIRegT(rN
), getIRegT(rM
)));
22456 putIRegT(rD
, mkexpr(res
), condT
);
22457 DIP("mul.w r%u, r%u, r%u\n", rD
, rN
, rM
);
22458 goto decode_success
;
22462 /* -------------- SDIV.W Rd, Rn, Rm -------------- */
22463 if (INSN0(15,4) == 0xFB9
22464 && (INSN1(15,0) & 0xF0F0) == 0xF0F0) {
22465 UInt rN
= INSN0(3,0);
22466 UInt rD
= INSN1(11,8);
22467 UInt rM
= INSN1(3,0);
22468 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22469 IRTemp res
= newTemp(Ity_I32
);
22470 IRTemp argL
= newTemp(Ity_I32
);
22471 IRTemp argR
= newTemp(Ity_I32
);
22472 assign(argL
, getIRegT(rN
));
22473 assign(argR
, getIRegT(rM
));
22474 assign(res
, binop(Iop_DivS32
, mkexpr(argL
), mkexpr(argR
)));
22475 putIRegT(rD
, mkexpr(res
), condT
);
22476 DIP("sdiv.w r%u, r%u, r%u\n", rD
, rN
, rM
);
22477 goto decode_success
;
22481 /* -------------- UDIV.W Rd, Rn, Rm -------------- */
22482 if (INSN0(15,4) == 0xFBB
22483 && (INSN1(15,0) & 0xF0F0) == 0xF0F0) {
22484 UInt rN
= INSN0(3,0);
22485 UInt rD
= INSN1(11,8);
22486 UInt rM
= INSN1(3,0);
22487 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22488 IRTemp res
= newTemp(Ity_I32
);
22489 IRTemp argL
= newTemp(Ity_I32
);
22490 IRTemp argR
= newTemp(Ity_I32
);
22491 assign(argL
, getIRegT(rN
));
22492 assign(argR
, getIRegT(rM
));
22493 assign(res
, binop(Iop_DivU32
, mkexpr(argL
), mkexpr(argR
)));
22494 putIRegT(rD
, mkexpr(res
), condT
);
22495 DIP("udiv.w r%u, r%u, r%u\n", rD
, rN
, rM
);
22496 goto decode_success
;
22500 /* ------------------ {U,S}MULL ------------------ */
22501 if ((INSN0(15,4) == 0xFB8 || INSN0(15,4) == 0xFBA)
22502 && INSN1(7,4) == BITS4(0,0,0,0)) {
22503 UInt isU
= INSN0(5,5);
22504 UInt rN
= INSN0(3,0);
22505 UInt rDlo
= INSN1(15,12);
22506 UInt rDhi
= INSN1(11,8);
22507 UInt rM
= INSN1(3,0);
22508 if (!isBadRegT(rDhi
) && !isBadRegT(rDlo
)
22509 && !isBadRegT(rN
) && !isBadRegT(rM
) && rDlo
!= rDhi
) {
22510 IRTemp res
= newTemp(Ity_I64
);
22511 assign(res
, binop(isU
? Iop_MullU32
: Iop_MullS32
,
22512 getIRegT(rN
), getIRegT(rM
)));
22513 putIRegT( rDhi
, unop(Iop_64HIto32
, mkexpr(res
)), condT
);
22514 putIRegT( rDlo
, unop(Iop_64to32
, mkexpr(res
)), condT
);
22515 DIP("%cmull r%u, r%u, r%u, r%u\n",
22516 isU
? 'u' : 's', rDlo
, rDhi
, rN
, rM
);
22517 goto decode_success
;
22521 /* ------------------ ML{A,S} ------------------ */
22522 if (INSN0(15,4) == 0xFB0
22523 && ( INSN1(7,4) == BITS4(0,0,0,0) // MLA
22524 || INSN1(7,4) == BITS4(0,0,0,1))) { // MLS
22525 UInt rN
= INSN0(3,0);
22526 UInt rA
= INSN1(15,12);
22527 UInt rD
= INSN1(11,8);
22528 UInt rM
= INSN1(3,0);
22529 if (!isBadRegT(rD
) && !isBadRegT(rN
)
22530 && !isBadRegT(rM
) && !isBadRegT(rA
)) {
22531 Bool isMLA
= INSN1(7,4) == BITS4(0,0,0,0);
22532 IRTemp res
= newTemp(Ity_I32
);
22534 binop(isMLA
? Iop_Add32
: Iop_Sub32
,
22536 binop(Iop_Mul32
, getIRegT(rN
), getIRegT(rM
))));
22537 putIRegT(rD
, mkexpr(res
), condT
);
22538 DIP("%s r%u, r%u, r%u, r%u\n",
22539 isMLA
? "mla" : "mls", rD
, rN
, rM
, rA
);
22540 goto decode_success
;
22544 /* ------------------ (T3) ADR ------------------ */
22545 if ((INSN0(15,0) == 0xF20F || INSN0(15,0) == 0xF60F)
22546 && INSN1(15,15) == 0) {
22547 /* rD = align4(PC) + imm32 */
22548 UInt rD
= INSN1(11,8);
22549 if (!isBadRegT(rD
)) {
22550 UInt imm32
= (INSN0(10,10) << 11)
22551 | (INSN1(14,12) << 8) | INSN1(7,0);
22552 putIRegT(rD
, binop(Iop_Add32
,
22553 binop(Iop_And32
, getIRegT(15), mkU32(~3U)),
22556 DIP("add r%u, pc, #%u\n", rD
, imm32
);
22557 goto decode_success
;
22561 /* ----------------- (T1) UMLAL ----------------- */
22562 /* ----------------- (T1) SMLAL ----------------- */
22563 if ((INSN0(15,4) == 0xFBE // UMLAL
22564 || INSN0(15,4) == 0xFBC) // SMLAL
22565 && INSN1(7,4) == BITS4(0,0,0,0)) {
22566 UInt rN
= INSN0(3,0);
22567 UInt rDlo
= INSN1(15,12);
22568 UInt rDhi
= INSN1(11,8);
22569 UInt rM
= INSN1(3,0);
22570 if (!isBadRegT(rDlo
) && !isBadRegT(rDhi
) && !isBadRegT(rN
)
22571 && !isBadRegT(rM
) && rDhi
!= rDlo
) {
22572 Bool isS
= INSN0(15,4) == 0xFBC;
22573 IRTemp argL
= newTemp(Ity_I32
);
22574 IRTemp argR
= newTemp(Ity_I32
);
22575 IRTemp old
= newTemp(Ity_I64
);
22576 IRTemp res
= newTemp(Ity_I64
);
22577 IRTemp resHi
= newTemp(Ity_I32
);
22578 IRTemp resLo
= newTemp(Ity_I32
);
22579 IROp mulOp
= isS
? Iop_MullS32
: Iop_MullU32
;
22580 assign( argL
, getIRegT(rM
));
22581 assign( argR
, getIRegT(rN
));
22582 assign( old
, binop(Iop_32HLto64
, getIRegT(rDhi
), getIRegT(rDlo
)) );
22583 assign( res
, binop(Iop_Add64
,
22585 binop(mulOp
, mkexpr(argL
), mkexpr(argR
))) );
22586 assign( resHi
, unop(Iop_64HIto32
, mkexpr(res
)) );
22587 assign( resLo
, unop(Iop_64to32
, mkexpr(res
)) );
22588 putIRegT( rDhi
, mkexpr(resHi
), condT
);
22589 putIRegT( rDlo
, mkexpr(resLo
), condT
);
22590 DIP("%cmlal r%u, r%u, r%u, r%u\n",
22591 isS
? 's' : 'u', rDlo
, rDhi
, rN
, rM
);
22592 goto decode_success
;
22596 /* ------------------ (T1) UMAAL ------------------ */
22597 if (INSN0(15,4) == 0xFBE && INSN1(7,4) == BITS4(0,1,1,0)) {
22598 UInt rN
= INSN0(3,0);
22599 UInt rDlo
= INSN1(15,12);
22600 UInt rDhi
= INSN1(11,8);
22601 UInt rM
= INSN1(3,0);
22602 if (!isBadRegT(rDlo
) && !isBadRegT(rDhi
) && !isBadRegT(rN
)
22603 && !isBadRegT(rM
) && rDhi
!= rDlo
) {
22604 IRTemp argN
= newTemp(Ity_I32
);
22605 IRTemp argM
= newTemp(Ity_I32
);
22606 IRTemp argDhi
= newTemp(Ity_I32
);
22607 IRTemp argDlo
= newTemp(Ity_I32
);
22608 IRTemp res
= newTemp(Ity_I64
);
22609 IRTemp resHi
= newTemp(Ity_I32
);
22610 IRTemp resLo
= newTemp(Ity_I32
);
22611 assign( argN
, getIRegT(rN
) );
22612 assign( argM
, getIRegT(rM
) );
22613 assign( argDhi
, getIRegT(rDhi
) );
22614 assign( argDlo
, getIRegT(rDlo
) );
22618 binop(Iop_MullU32
, mkexpr(argN
), mkexpr(argM
)),
22619 unop(Iop_32Uto64
, mkexpr(argDhi
))),
22620 unop(Iop_32Uto64
, mkexpr(argDlo
))) );
22621 assign( resHi
, unop(Iop_64HIto32
, mkexpr(res
)) );
22622 assign( resLo
, unop(Iop_64to32
, mkexpr(res
)) );
22623 putIRegT( rDhi
, mkexpr(resHi
), condT
);
22624 putIRegT( rDlo
, mkexpr(resLo
), condT
);
22625 DIP("umaal r%u, r%u, r%u, r%u\n", rDlo
, rDhi
, rN
, rM
);
22626 goto decode_success
;
22630 /* ------------------- (T1) SMMUL{R} ------------------ */
22631 if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
22632 && INSN0(6,4) == BITS3(1,0,1)
22633 && INSN1(15,12) == BITS4(1,1,1,1)
22634 && INSN1(7,5) == BITS3(0,0,0)) {
22635 UInt bitR
= INSN1(4,4);
22636 UInt rD
= INSN1(11,8);
22637 UInt rM
= INSN1(3,0);
22638 UInt rN
= INSN0(3,0);
22639 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22641 = unop(Iop_64HIto32
,
22643 binop(Iop_MullS32
, getIRegT(rN
), getIRegT(rM
)),
22644 mkU64(bitR
? 0x80000000ULL
: 0ULL)));
22645 putIRegT(rD
, res
, condT
);
22646 DIP("smmul%s r%u, r%u, r%u\n",
22647 bitR
? "r" : "", rD
, rN
, rM
);
22648 goto decode_success
;
22652 /* ------------------- (T1) SMMLA{R} ------------------ */
22653 if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
22654 && INSN0(6,4) == BITS3(1,0,1)
22655 && INSN1(7,5) == BITS3(0,0,0)) {
22656 UInt bitR
= INSN1(4,4);
22657 UInt rA
= INSN1(15,12);
22658 UInt rD
= INSN1(11,8);
22659 UInt rM
= INSN1(3,0);
22660 UInt rN
= INSN0(3,0);
22661 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
) && (rA
!= 13)) {
22663 = unop(Iop_64HIto32
,
22666 binop(Iop_32HLto64
, getIRegT(rA
), mkU32(0)),
22667 binop(Iop_MullS32
, getIRegT(rN
), getIRegT(rM
))),
22668 mkU64(bitR
? 0x80000000ULL
: 0ULL)));
22669 putIRegT(rD
, res
, condT
);
22670 DIP("smmla%s r%u, r%u, r%u, r%u\n",
22671 bitR
? "r" : "", rD
, rN
, rM
, rA
);
22672 goto decode_success
;
22676 /* ------------------ (T2) ADR ------------------ */
22677 if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF)
22678 && INSN1(15,15) == 0) {
22679 /* rD = align4(PC) - imm32 */
22680 UInt rD
= INSN1(11,8);
22681 if (!isBadRegT(rD
)) {
22682 UInt imm32
= (INSN0(10,10) << 11)
22683 | (INSN1(14,12) << 8) | INSN1(7,0);
22684 putIRegT(rD
, binop(Iop_Sub32
,
22685 binop(Iop_And32
, getIRegT(15), mkU32(~3U)),
22688 DIP("sub r%u, pc, #%u\n", rD
, imm32
);
22689 goto decode_success
;
22693 /* ------------------- (T1) BFI ------------------- */
22694 /* ------------------- (T1) BFC ------------------- */
22695 if (INSN0(15,4) == 0xF36 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
22696 UInt rD
= INSN1(11,8);
22697 UInt rN
= INSN0(3,0);
22698 UInt msb
= INSN1(4,0);
22699 UInt lsb
= (INSN1(14,12) << 2) | INSN1(7,6);
22700 if (isBadRegT(rD
) || rN
== 13 || msb
< lsb
) {
22701 /* undecodable; fall through */
22703 IRTemp src
= newTemp(Ity_I32
);
22704 IRTemp olddst
= newTemp(Ity_I32
);
22705 IRTemp newdst
= newTemp(Ity_I32
);
22706 UInt mask
= ((UInt
)1) << (msb
- lsb
);
22707 mask
= (mask
- 1) + mask
;
22708 vassert(mask
!= 0); // guaranteed by "msb < lsb" check above
22711 assign(src
, rN
== 15 ? mkU32(0) : getIRegT(rN
));
22712 assign(olddst
, getIRegT(rD
));
22716 binop(Iop_Shl32
, mkexpr(src
), mkU8(lsb
)),
22723 putIRegT(rD
, mkexpr(newdst
), condT
);
22726 DIP("bfc r%u, #%u, #%u\n",
22727 rD
, lsb
, msb
-lsb
+1);
22729 DIP("bfi r%u, r%u, #%u, #%u\n",
22730 rD
, rN
, lsb
, msb
-lsb
+1);
22732 goto decode_success
;
22736 /* ------------------- (T1) SXTAH ------------------- */
22737 /* ------------------- (T1) UXTAH ------------------- */
22738 if ((INSN0(15,4) == 0xFA1 // UXTAH
22739 || INSN0(15,4) == 0xFA0) // SXTAH
22740 && INSN1(15,12) == BITS4(1,1,1,1)
22741 && INSN1(7,6) == BITS2(1,0)) {
22742 Bool isU
= INSN0(15,4) == 0xFA1;
22743 UInt rN
= INSN0(3,0);
22744 UInt rD
= INSN1(11,8);
22745 UInt rM
= INSN1(3,0);
22746 UInt rot
= INSN1(5,4);
22747 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22748 IRTemp srcL
= newTemp(Ity_I32
);
22749 IRTemp srcR
= newTemp(Ity_I32
);
22750 IRTemp res
= newTemp(Ity_I32
);
22751 assign(srcR
, getIRegT(rM
));
22752 assign(srcL
, getIRegT(rN
));
22753 assign(res
, binop(Iop_Add32
,
22755 unop(isU
? Iop_16Uto32
: Iop_16Sto32
,
22757 genROR32(srcR
, 8 * rot
)))));
22758 putIRegT(rD
, mkexpr(res
), condT
);
22759 DIP("%cxtah r%u, r%u, r%u, ror #%u\n",
22760 isU
? 'u' : 's', rD
, rN
, rM
, rot
);
22761 goto decode_success
;
22765 /* ------------------- (T1) SXTAB ------------------- */
22766 /* ------------------- (T1) UXTAB ------------------- */
22767 if ((INSN0(15,4) == 0xFA5 // UXTAB
22768 || INSN0(15,4) == 0xFA4) // SXTAB
22769 && INSN1(15,12) == BITS4(1,1,1,1)
22770 && INSN1(7,6) == BITS2(1,0)) {
22771 Bool isU
= INSN0(15,4) == 0xFA5;
22772 UInt rN
= INSN0(3,0);
22773 UInt rD
= INSN1(11,8);
22774 UInt rM
= INSN1(3,0);
22775 UInt rot
= INSN1(5,4);
22776 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22777 IRTemp srcL
= newTemp(Ity_I32
);
22778 IRTemp srcR
= newTemp(Ity_I32
);
22779 IRTemp res
= newTemp(Ity_I32
);
22780 assign(srcR
, getIRegT(rM
));
22781 assign(srcL
, getIRegT(rN
));
22782 assign(res
, binop(Iop_Add32
,
22784 unop(isU
? Iop_8Uto32
: Iop_8Sto32
,
22786 genROR32(srcR
, 8 * rot
)))));
22787 putIRegT(rD
, mkexpr(res
), condT
);
22788 DIP("%cxtab r%u, r%u, r%u, ror #%u\n",
22789 isU
? 'u' : 's', rD
, rN
, rM
, rot
);
22790 goto decode_success
;
22794 /* ------------------- (T1) CLZ ------------------- */
22795 if (INSN0(15,4) == 0xFAB
22796 && INSN1(15,12) == BITS4(1,1,1,1)
22797 && INSN1(7,4) == BITS4(1,0,0,0)) {
22798 UInt rM1
= INSN0(3,0);
22799 UInt rD
= INSN1(11,8);
22800 UInt rM2
= INSN1(3,0);
22801 if (!isBadRegT(rD
) && !isBadRegT(rM1
) && rM1
== rM2
) {
22802 IRTemp arg
= newTemp(Ity_I32
);
22803 IRTemp res
= newTemp(Ity_I32
);
22804 assign(arg
, getIRegT(rM1
));
22805 assign(res
, IRExpr_ITE(
22806 binop(Iop_CmpEQ32
, mkexpr(arg
), mkU32(0)),
22808 unop(Iop_Clz32
, mkexpr(arg
))
22810 putIRegT(rD
, mkexpr(res
), condT
);
22811 DIP("clz r%u, r%u\n", rD
, rM1
);
22812 goto decode_success
;
22816 /* ------------------- (T1) RBIT ------------------- */
22817 if (INSN0(15,4) == 0xFA9
22818 && INSN1(15,12) == BITS4(1,1,1,1)
22819 && INSN1(7,4) == BITS4(1,0,1,0)) {
22820 UInt rM1
= INSN0(3,0);
22821 UInt rD
= INSN1(11,8);
22822 UInt rM2
= INSN1(3,0);
22823 if (!isBadRegT(rD
) && !isBadRegT(rM1
) && rM1
== rM2
) {
22824 IRTemp arg
= newTemp(Ity_I32
);
22825 assign(arg
, getIRegT(rM1
));
22826 IRTemp res
= gen_BITREV(arg
);
22827 putIRegT(rD
, mkexpr(res
), condT
);
22828 DIP("rbit r%u, r%u\n", rD
, rM1
);
22829 goto decode_success
;
22833 /* ------------------- (T2) REV ------------------- */
22834 /* ------------------- (T2) REV16 ------------------- */
22835 if (INSN0(15,4) == 0xFA9
22836 && INSN1(15,12) == BITS4(1,1,1,1)
22837 && ( INSN1(7,4) == BITS4(1,0,0,0) // REV
22838 || INSN1(7,4) == BITS4(1,0,0,1))) { // REV16
22839 UInt rM1
= INSN0(3,0);
22840 UInt rD
= INSN1(11,8);
22841 UInt rM2
= INSN1(3,0);
22842 Bool isREV
= INSN1(7,4) == BITS4(1,0,0,0);
22843 if (!isBadRegT(rD
) && !isBadRegT(rM1
) && rM1
== rM2
) {
22844 IRTemp arg
= newTemp(Ity_I32
);
22845 assign(arg
, getIRegT(rM1
));
22846 IRTemp res
= isREV
? gen_REV(arg
) : gen_REV16(arg
);
22847 putIRegT(rD
, mkexpr(res
), condT
);
22848 DIP("rev%s r%u, r%u\n", isREV
? "" : "16", rD
, rM1
);
22849 goto decode_success
;
22853 /* ------------------- (T2) REVSH ------------------ */
22854 if (INSN0(15,4) == 0xFA9
22855 && INSN1(15,12) == BITS4(1,1,1,1)
22856 && INSN1(7,4) == BITS4(1,0,1,1)) {
22857 UInt rM1
= INSN0(3,0);
22858 UInt rM2
= INSN1(3,0);
22859 UInt rD
= INSN1(11,8);
22860 if (!isBadRegT(rD
) && !isBadRegT(rM1
) && rM1
== rM2
) {
22861 IRTemp irt_rM
= newTemp(Ity_I32
);
22862 IRTemp irt_hi
= newTemp(Ity_I32
);
22863 IRTemp irt_low
= newTemp(Ity_I32
);
22864 IRTemp irt_res
= newTemp(Ity_I32
);
22865 assign(irt_rM
, getIRegT(rM1
));
22868 binop(Iop_Shl32
, mkexpr(irt_rM
), mkU8(24)),
22874 binop(Iop_Shr32
, mkexpr(irt_rM
), mkU8(8)),
22879 binop(Iop_Or32
, mkexpr(irt_hi
), mkexpr(irt_low
))
22881 putIRegT(rD
, mkexpr(irt_res
), condT
);
22882 DIP("revsh r%u, r%u\n", rD
, rM1
);
22883 goto decode_success
;
22887 /* -------------- (T1) MSR apsr, reg -------------- */
22888 if (INSN0(15,4) == 0xF38
22889 && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) {
22890 UInt rN
= INSN0(3,0);
22891 UInt write_ge
= INSN1(10,10);
22892 UInt write_nzcvq
= INSN1(11,11);
22893 if (!isBadRegT(rN
) && (write_nzcvq
|| write_ge
)) {
22894 IRTemp rNt
= newTemp(Ity_I32
);
22895 assign(rNt
, getIRegT(rN
));
22896 desynthesise_APSR( write_nzcvq
, write_ge
, rNt
, condT
);
22897 DIP("msr cpsr_%s%s, r%u\n",
22898 write_nzcvq
? "f" : "", write_ge
? "g" : "", rN
);
22899 goto decode_success
;
22903 /* -------------- (T1) MRS reg, apsr -------------- */
22904 if (INSN0(15,0) == 0xF3EF
22905 && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(7,0) == 0x00) {
22906 UInt rD
= INSN1(11,8);
22907 if (!isBadRegT(rD
)) {
22908 IRTemp apsr
= synthesise_APSR();
22909 putIRegT( rD
, mkexpr(apsr
), condT
);
22910 DIP("mrs r%u, cpsr\n", rD
);
22911 goto decode_success
;
22915 /* ----------------- (T1) LDREX ----------------- */
22916 if (INSN0(15,4) == 0xE85 && INSN1(11,8) == BITS4(1,1,1,1)) {
22917 UInt rN
= INSN0(3,0);
22918 UInt rT
= INSN1(15,12);
22919 UInt imm8
= INSN1(7,0);
22920 if (!isBadRegT(rT
) && rN
!= 15) {
22923 mk_skip_over_T32_if_cond_is_false( condT
);
22925 res
= newTemp(Ity_I32
);
22926 stmt( IRStmt_LLSC(Iend_LE
,
22928 binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
* 4)),
22929 NULL
/*this is a load*/ ));
22930 putIRegT(rT
, mkexpr(res
), IRTemp_INVALID
);
22931 DIP("ldrex r%u, [r%u, #+%u]\n", rT
, rN
, imm8
* 4);
22932 goto decode_success
;
22936 /* --------------- (T1) LDREX{B,H} --------------- */
22937 if (INSN0(15,4) == 0xE8D
22938 && (INSN1(11,0) == 0xF4F || INSN1(11,0) == 0xF5F)) {
22939 UInt rN
= INSN0(3,0);
22940 UInt rT
= INSN1(15,12);
22941 Bool isH
= INSN1(11,0) == 0xF5F;
22942 if (!isBadRegT(rT
) && rN
!= 15) {
22945 mk_skip_over_T32_if_cond_is_false( condT
);
22947 res
= newTemp(isH
? Ity_I16
: Ity_I8
);
22948 stmt( IRStmt_LLSC(Iend_LE
, res
, getIRegT(rN
),
22949 NULL
/*this is a load*/ ));
22950 putIRegT(rT
, unop(isH
? Iop_16Uto32
: Iop_8Uto32
, mkexpr(res
)),
22952 DIP("ldrex%c r%u, [r%u]\n", isH
? 'h' : 'b', rT
, rN
);
22953 goto decode_success
;
22957 /* --------------- (T1) LDREXD --------------- */
22958 if (INSN0(15,4) == 0xE8D && INSN1(7,0) == 0x7F) {
22959 UInt rN
= INSN0(3,0);
22960 UInt rT
= INSN1(15,12);
22961 UInt rT2
= INSN1(11,8);
22962 if (!isBadRegT(rT
) && !isBadRegT(rT2
) && rT
!= rT2
&& rN
!= 15) {
22965 mk_skip_over_T32_if_cond_is_false( condT
);
22967 res
= newTemp(Ity_I64
);
22968 // FIXME: assumes little-endian guest
22969 stmt( IRStmt_LLSC(Iend_LE
, res
, getIRegT(rN
),
22970 NULL
/*this is a load*/ ));
22971 // FIXME: assumes little-endian guest
22972 putIRegT(rT
, unop(Iop_64to32
, mkexpr(res
)), IRTemp_INVALID
);
22973 putIRegT(rT2
, unop(Iop_64HIto32
, mkexpr(res
)), IRTemp_INVALID
);
22974 DIP("ldrexd r%u, r%u, [r%u]\n", rT
, rT2
, rN
);
22975 goto decode_success
;
22979 /* ----------------- (T1) STREX ----------------- */
22980 if (INSN0(15,4) == 0xE84) {
22981 UInt rN
= INSN0(3,0);
22982 UInt rT
= INSN1(15,12);
22983 UInt rD
= INSN1(11,8);
22984 UInt imm8
= INSN1(7,0);
22985 if (!isBadRegT(rD
) && !isBadRegT(rT
) && rN
!= 15
22986 && rD
!= rN
&& rD
!= rT
) {
22987 IRTemp resSC1
, resSC32
;
22989 mk_skip_over_T32_if_cond_is_false( condT
);
22991 /* Ok, now we're unconditional. Do the store. */
22992 resSC1
= newTemp(Ity_I1
);
22993 stmt( IRStmt_LLSC(Iend_LE
,
22995 binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
* 4)),
22997 /* Set rD to 1 on failure, 0 on success. Currently we have
22998 resSC1 == 0 on failure, 1 on success. */
22999 resSC32
= newTemp(Ity_I32
);
23001 unop(Iop_1Uto32
, unop(Iop_Not1
, mkexpr(resSC1
))));
23002 putIRegT(rD
, mkexpr(resSC32
), IRTemp_INVALID
);
23003 DIP("strex r%u, r%u, [r%u, #+%u]\n", rD
, rT
, rN
, imm8
* 4);
23004 goto decode_success
;
23008 /* --------------- (T1) STREX{B,H} --------------- */
23009 if (INSN0(15,4) == 0xE8C
23010 && (INSN1(11,4) == 0xF4 || INSN1(11,4) == 0xF5)) {
23011 UInt rN
= INSN0(3,0);
23012 UInt rT
= INSN1(15,12);
23013 UInt rD
= INSN1(3,0);
23014 Bool isH
= INSN1(11,4) == 0xF5;
23015 if (!isBadRegT(rD
) && !isBadRegT(rT
) && rN
!= 15
23016 && rD
!= rN
&& rD
!= rT
) {
23017 IRTemp resSC1
, resSC32
;
23019 mk_skip_over_T32_if_cond_is_false( condT
);
23021 /* Ok, now we're unconditional. Do the store. */
23022 resSC1
= newTemp(Ity_I1
);
23023 stmt( IRStmt_LLSC(Iend_LE
, resSC1
, getIRegT(rN
),
23024 unop(isH
? Iop_32to16
: Iop_32to8
,
23026 /* Set rD to 1 on failure, 0 on success. Currently we have
23027 resSC1 == 0 on failure, 1 on success. */
23028 resSC32
= newTemp(Ity_I32
);
23030 unop(Iop_1Uto32
, unop(Iop_Not1
, mkexpr(resSC1
))));
23031 putIRegT(rD
, mkexpr(resSC32
), IRTemp_INVALID
);
23032 DIP("strex%c r%u, r%u, [r%u]\n", isH
? 'h' : 'b', rD
, rT
, rN
);
23033 goto decode_success
;
23037 /* ---------------- (T1) STREXD ---------------- */
23038 if (INSN0(15,4) == 0xE8C && INSN1(7,4) == BITS4(0,1,1,1)) {
23039 UInt rN
= INSN0(3,0);
23040 UInt rT
= INSN1(15,12);
23041 UInt rT2
= INSN1(11,8);
23042 UInt rD
= INSN1(3,0);
23043 if (!isBadRegT(rD
) && !isBadRegT(rT
) && !isBadRegT(rT2
)
23044 && rN
!= 15 && rD
!= rN
&& rD
!= rT
&& rD
!= rT2
) {
23045 IRTemp resSC1
, resSC32
, data
;
23047 mk_skip_over_T32_if_cond_is_false( condT
);
23049 /* Ok, now we're unconditional. Do the store. */
23050 resSC1
= newTemp(Ity_I1
);
23051 data
= newTemp(Ity_I64
);
23052 // FIXME: assumes little-endian guest
23053 assign(data
, binop(Iop_32HLto64
, getIRegT(rT2
), getIRegT(rT
)));
23054 // FIXME: assumes little-endian guest
23055 stmt( IRStmt_LLSC(Iend_LE
, resSC1
, getIRegT(rN
), mkexpr(data
)));
23056 /* Set rD to 1 on failure, 0 on success. Currently we have
23057 resSC1 == 0 on failure, 1 on success. */
23058 resSC32
= newTemp(Ity_I32
);
23060 unop(Iop_1Uto32
, unop(Iop_Not1
, mkexpr(resSC1
))));
23061 putIRegT(rD
, mkexpr(resSC32
), IRTemp_INVALID
);
23062 DIP("strexd r%u, r%u, r%u, [r%u]\n", rD
, rT
, rT2
, rN
);
23063 goto decode_success
;
23067 /* -------------- v7 barrier insns -------------- */
23068 if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) {
23069 /* FIXME: should this be unconditional? */
23070 /* XXX this isn't really right, is it? The generated IR does
23071 them unconditionally. I guess it doesn't matter since it
23072 doesn't do any harm to do them even when the guarding
23073 condition is false -- it's just a performance loss. */
23074 switch (INSN1(7,0)) {
23075 case 0x4F: /* DSB sy */
23076 case 0x4E: /* DSB st */
23077 case 0x4B: /* DSB ish */
23078 case 0x4A: /* DSB ishst */
23079 case 0x47: /* DSB nsh */
23080 case 0x46: /* DSB nshst */
23081 case 0x43: /* DSB osh */
23082 case 0x42: /* DSB oshst */
23083 stmt( IRStmt_MBE(Imbe_Fence
) );
23085 goto decode_success
;
23086 case 0x5F: /* DMB sy */
23087 case 0x5E: /* DMB st */
23088 case 0x5B: /* DMB ish */
23089 case 0x5A: /* DMB ishst */
23090 case 0x57: /* DMB nsh */
23091 case 0x56: /* DMB nshst */
23092 case 0x53: /* DMB osh */
23093 case 0x52: /* DMB oshst */
23094 stmt( IRStmt_MBE(Imbe_Fence
) );
23096 goto decode_success
;
23097 case 0x6F: /* ISB */
23098 stmt( IRStmt_MBE(Imbe_Fence
) );
23100 goto decode_success
;
23106 /* ---------------------- PLD{,W} ---------------------- */
23107 if ((INSN0(15,4) & 0xFFD) == 0xF89 && INSN1(15,12) == 0xF) {
23108 /* FIXME: should this be unconditional? */
23109 /* PLD/PLDW immediate, encoding T1 */
23110 UInt rN
= INSN0(3,0);
23111 UInt bW
= INSN0(5,5);
23112 UInt imm12
= INSN1(11,0);
23113 DIP("pld%s [r%u, #%u]\n", bW
? "w" : "", rN
, imm12
);
23114 goto decode_success
;
23117 if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,8) == 0xFC) {
23118 /* FIXME: should this be unconditional? */
23119 /* PLD/PLDW immediate, encoding T2 */
23120 UInt rN
= INSN0(3,0);
23121 UInt bW
= INSN0(5,5);
23122 UInt imm8
= INSN1(7,0);
23123 DIP("pld%s [r%u, #-%u]\n", bW
? "w" : "", rN
, imm8
);
23124 goto decode_success
;
23127 if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,6) == 0x3C0) {
23128 /* FIXME: should this be unconditional? */
23129 /* PLD/PLDW register, encoding T1 */
23130 UInt rN
= INSN0(3,0);
23131 UInt rM
= INSN1(3,0);
23132 UInt bW
= INSN0(5,5);
23133 UInt imm2
= INSN1(5,4);
23134 if (!isBadRegT(rM
)) {
23135 DIP("pld%s [r%u, r%u, lsl %u]\n", bW
? "w" : "", rN
, rM
, imm2
);
23136 goto decode_success
;
23141 /* -------------- read CP15 TPIDRURO register ------------- */
23142 /* mrc p15, 0, r0, c13, c0, 3 up to
23143 mrc p15, 0, r14, c13, c0, 3
23145 /* I don't know whether this is really v7-only. But anyway, we
23146 have to support it since arm-linux uses TPIDRURO as a thread
23148 if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) {
23149 UInt rD
= INSN1(15,12);
23150 if (!isBadRegT(rD
)) {
23151 putIRegT(rD
, IRExpr_Get(OFFB_TPIDRURO
, Ity_I32
), condT
);
23152 DIP("mrc p15,0, r%u, c13, c0, 3\n", rD
);
23153 goto decode_success
;
23158 /* ------------ read/write CP15 TPIDRURW register ----------- */
23159 /* mcr p15, 0, r0, c13, c0, 2 (r->cr xfer) up to
23160 mcr p15, 0, r14, c13, c0, 2
23162 mrc p15, 0, r0, c13, c0, 2 (rc->r xfer) up to
23163 mrc p15, 0, r14, c13, c0, 2
23165 if ((INSN0(15,0) == 0xEE0D) && (INSN1(11,0) == 0x0F50)) {
23166 UInt rS
= INSN1(15,12);
23167 if (!isBadRegT(rS
)) {
23168 putMiscReg32(OFFB_TPIDRURW
, getIRegT(rS
), condT
);
23169 DIP("mcr p15,0, r%u, c13, c0, 2\n", rS
);
23170 goto decode_success
;
23174 if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F50)) {
23175 UInt rD
= INSN1(15,12);
23176 if (!isBadRegT(rD
)) {
23177 putIRegT(rD
, IRExpr_Get(OFFB_TPIDRURW
, Ity_I32
), condT
);
23178 DIP("mrc p15,0, r%u, c13, c0, 2\n", rD
);
23179 goto decode_success
;
23184 /* -------------- read CP15 PMUSRENR register ------------- */
23185 /* mrc p15, 0, r0, c9, c14, 0 up to
23186 mrc p15, 0, r14, c9, c14, 0
23187 See comment on the ARM equivalent of this (above) for details.
23189 if ((INSN0(15,0) == 0xEE19) && (INSN1(11,0) == 0x0F1E)) {
23190 UInt rD
= INSN1(15,12);
23191 if (!isBadRegT(rD
)) {
23192 putIRegT(rD
, mkU32(0), condT
);
23193 DIP("mrc p15,0, r%u, c9, c14, 0\n", rD
);
23194 goto decode_success
;
23199 /* ------------------- CLREX ------------------ */
23200 if (INSN0(15,0) == 0xF3BF && INSN1(15,0) == 0x8F2F) {
23201 /* AFAICS, this simply cancels a (all?) reservations made by a
23202 (any?) preceding LDREX(es). Arrange to hand it through to
23204 mk_skip_over_T32_if_cond_is_false( condT
);
23205 stmt( IRStmt_MBE(Imbe_CancelReservation
) );
23207 goto decode_success
;
23210 /* ------------------- NOP ------------------ */
23211 if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) {
23213 goto decode_success
;
23216 /* -------------- (T1) LDRT reg+#imm8 -------------- */
23217 /* Load Register Unprivileged:
23218 ldrt Rt, [Rn, #imm8]
23220 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,1) && INSN0(5,4) == BITS2(0,1)
23221 && INSN1(11,8) == BITS4(1,1,1,0)) {
23222 UInt rT
= INSN1(15,12);
23223 UInt rN
= INSN0(3,0);
23224 UInt imm8
= INSN1(7,0);
23226 if (rN
== 15 || isBadRegT(rT
)) valid
= False
;
23228 put_ITSTATE(old_itstate
);
23229 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23230 IRTemp newRt
= newTemp(Ity_I32
);
23231 loadGuardedLE( newRt
, ILGop_Ident32
, ea
, llGetIReg(rT
), condT
);
23232 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
23233 put_ITSTATE(new_itstate
);
23234 DIP("ldrt r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23235 goto decode_success
;
23239 /* -------------- (T1) STRT reg+#imm8 -------------- */
23240 /* Store Register Unprivileged:
23241 strt Rt, [Rn, #imm8]
23243 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,1) && INSN0(5,4) == BITS2(0,0)
23244 && INSN1(11,8) == BITS4(1,1,1,0)) {
23245 UInt rT
= INSN1(15,12);
23246 UInt rN
= INSN0(3,0);
23247 UInt imm8
= INSN1(7,0);
23249 if (rN
== 15 || isBadRegT(rT
)) valid
= False
;
23251 put_ITSTATE(old_itstate
);
23252 IRExpr
* address
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23253 storeGuardedLE( address
, llGetIReg(rT
), condT
);
23254 put_ITSTATE(new_itstate
);
23255 DIP("strt r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23256 goto decode_success
;
23260 /* -------------- (T1) STRBT reg+#imm8 -------------- */
23261 /* Store Register Byte Unprivileged:
23262 strbt Rt, [Rn, #imm8]
23264 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,0) && INSN0(5,4) == BITS2(0,0)
23265 && INSN1(11,8) == BITS4(1,1,1,0)) {
23266 UInt rT
= INSN1(15,12);
23267 UInt rN
= INSN0(3,0);
23268 UInt imm8
= INSN1(7,0);
23270 if (rN
== 15 || isBadRegT(rT
)) valid
= False
;
23272 put_ITSTATE(old_itstate
);
23273 IRExpr
* address
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23274 IRExpr
* data
= unop(Iop_32to8
, llGetIReg(rT
));
23275 storeGuardedLE( address
, data
, condT
);
23276 put_ITSTATE(new_itstate
);
23277 DIP("strbt r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23278 goto decode_success
;
23282 /* -------------- (T1) LDRHT reg+#imm8 -------------- */
23283 /* Load Register Halfword Unprivileged:
23284 ldrht Rt, [Rn, #imm8]
23286 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,0) && INSN0(5,4) == BITS2(1,1)
23287 && INSN1(11,8) == BITS4(1,1,1,0)) {
23288 UInt rN
= INSN0(3,0);
23291 /* In this case our instruction is LDRH (literal), in fact:
23292 LDRH (literal) was realized earlier, so we don't want to
23296 UInt rT
= INSN1(15,12);
23297 UInt imm8
= INSN1(7,0);
23298 if (isBadRegT(rT
)) valid
= False
;
23300 put_ITSTATE(old_itstate
);
23301 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23302 IRTemp newRt
= newTemp(Ity_I32
);
23303 loadGuardedLE( newRt
, ILGop_16Uto32
, ea
, llGetIReg(rT
), condT
);
23304 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
23305 put_ITSTATE(new_itstate
);
23306 DIP("ldrht r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23307 goto decode_success
;
23311 /* -------------- (T1) LDRSHT reg+#imm8 -------------- */
23312 /* Load Register Signed Halfword Unprivileged:
23313 ldrsht Rt, [Rn, #imm8]
23315 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,1,0,0) && INSN0(5,4) == BITS2(1,1)
23316 && INSN1(11,8) == BITS4(1,1,1,0)) {
23317 UInt rN
= INSN0(3,0);
23320 /* In this case our instruction is LDRSH (literal), in fact:
23321 LDRSH (literal) was realized earlier, so we don't want to
23325 UInt rT
= INSN1(15,12);
23326 UInt imm8
= INSN1(7,0);
23327 if (isBadRegT(rT
)) valid
= False
;
23329 put_ITSTATE(old_itstate
);
23330 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23331 IRTemp newRt
= newTemp(Ity_I32
);
23332 loadGuardedLE( newRt
, ILGop_16Sto32
, ea
, llGetIReg(rT
), condT
);
23333 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
23334 put_ITSTATE(new_itstate
);
23335 DIP("ldrsht r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23336 goto decode_success
;
23340 /* -------------- (T1) STRHT reg+#imm8 -------------- */
23341 /* Store Register Halfword Unprivileged:
23342 strht Rt, [Rn, #imm8]
23344 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,0) && INSN0(5,4) == BITS2(1,0)
23345 && INSN1(11,8) == BITS4(1,1,1,0)) {
23346 UInt rT
= INSN1(15,12);
23347 UInt rN
= INSN0(3,0);
23348 UInt imm8
= INSN1(7,0);
23350 if (rN
== 15 || isBadRegT(rT
)) valid
= False
;
23352 put_ITSTATE(old_itstate
);
23353 IRExpr
* address
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23354 IRExpr
* data
= unop(Iop_32to16
, llGetIReg(rT
));
23355 storeGuardedLE( address
, data
, condT
);
23356 put_ITSTATE(new_itstate
);
23357 DIP("strht r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23358 goto decode_success
;
23362 /* -------------- (T1) LDRBT reg+#imm8 -------------- */
23363 /* Load Register Byte Unprivileged:
23364 ldrbt Rt, [Rn, #imm8]
23366 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,0) && INSN0(5,4) == BITS2(0,1)
23367 && INSN1(11,8) == BITS4(1,1,1,0)) {
23368 UInt rN
= INSN0(3,0);
23369 UInt rT
= INSN1(15,12);
23370 UInt imm8
= INSN1(7,0);
23372 if (rN
== 15 /* insn is LDRB (literal) */) valid
= False
;
23373 if (isBadRegT(rT
)) valid
= False
;
23375 put_ITSTATE(old_itstate
);
23376 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23377 IRTemp newRt
= newTemp(Ity_I32
);
23378 loadGuardedLE( newRt
, ILGop_8Uto32
, ea
, llGetIReg(rT
), condT
);
23379 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
23380 put_ITSTATE(new_itstate
);
23381 DIP("ldrbt r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23382 goto decode_success
;
23386 /* -------------- (T1) LDRSBT reg+#imm8 -------------- */
23387 /* Load Register Signed Byte Unprivileged:
23388 ldrsbt Rt, [Rn, #imm8]
23390 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,1,0,0) && INSN0(5,4) == BITS2(0,1)
23391 && INSN1(11,8) == BITS4(1,1,1,0)) {
23392 UInt rN
= INSN0(3,0);
23394 UInt rT
= INSN1(15,12);
23395 UInt imm8
= INSN1(7,0);
23396 if (rN
== 15 /* insn is LDRSB (literal) */) valid
= False
;
23397 if (isBadRegT(rT
)) valid
= False
;
23399 put_ITSTATE(old_itstate
);
23400 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23401 IRTemp newRt
= newTemp(Ity_I32
);
23402 loadGuardedLE( newRt
, ILGop_8Sto32
, ea
, llGetIReg(rT
), condT
);
23403 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
23404 put_ITSTATE(new_itstate
);
23405 DIP("ldrsbt r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23406 goto decode_success
;
23410 /* -------------- (T1) PLI reg+#imm12 -------------- */
23411 /* Preload Instruction:
23414 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,1,1,0) && INSN0(5,4) == BITS2(0,1)
23415 && INSN1(15,12) == BITS4(1,1,1,1)) {
23416 UInt rN
= INSN0(3,0);
23417 UInt imm12
= INSN1(11,0);
23419 DIP("pli [r%u, #%u]\n", rN
, imm12
);
23420 goto decode_success
;
23424 /* -------------- (T2) PLI reg-#imm8 -------------- */
23425 /* Preload Instruction:
23428 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,1,0,0) && INSN0(5,4) == BITS2(0,1)
23429 && INSN1(15,8) == BITS8(1,1,1,1,1,1,0,0)) {
23430 UInt rN
= INSN0(3,0);
23431 UInt imm8
= INSN1(7,0);
23433 DIP("pli [r%u, #-%u]\n", rN
, imm8
);
23434 goto decode_success
;
23438 /* -------------- (T3) PLI PC+/-#imm12 -------------- */
23439 /* Preload Instruction:
23440 pli [PC, #+/-imm12]
23442 if (INSN0(15,8) == BITS8(1,1,1,1,1,0,0,1)
23443 && INSN0(6,0) == BITS7(0,0,1,1,1,1,1)
23444 && INSN1(15,12) == BITS4(1,1,1,1)) {
23445 UInt imm12
= INSN1(11,0);
23446 UInt bU
= INSN0(7,7);
23447 DIP("pli [pc, #%c%u]\n", bU
== 1 ? '+' : '-', imm12
);
23448 goto decode_success
;
23451 /* ----------------------------------------------------------- */
23452 /* -- VFP (CP 10, CP 11) instructions (in Thumb mode) -- */
23453 /* ----------------------------------------------------------- */
23455 if (INSN0(15,12) == BITS4(1,1,1,0)) {
23456 UInt insn28
= (INSN0(11,0) << 16) | INSN1(15,0);
23457 Bool ok_vfp
= decode_CP10_CP11_instruction (
23458 &dres
, insn28
, condT
, ARMCondAL
/*bogus*/,
23462 goto decode_success
;
23465 /* ----------------------------------------------------------- */
23466 /* -- NEON instructions (only v7 and below, in Thumb mode) -- */
23467 /* ----------------------------------------------------------- */
23469 if (archinfo
->hwcaps
& VEX_HWCAPS_ARM_NEON
) {
23470 UInt insn32
= (INSN0(15,0) << 16) | INSN1(15,0);
23471 Bool ok_neon
= decode_NEON_instruction_ARMv7_and_below(
23472 &dres
, insn32
, condT
, True
/*isT*/
23475 goto decode_success
;
23478 /* ----------------------------------------------------------- */
23479 /* -- v6 media instructions (in Thumb mode) -- */
23480 /* ----------------------------------------------------------- */
23482 { UInt insn32
= (INSN0(15,0) << 16) | INSN1(15,0);
23483 Bool ok_v6m
= decode_V6MEDIA_instruction(
23484 &dres
, insn32
, condT
, ARMCondAL
/*bogus*/,
23488 goto decode_success
;
23491 /* ----------------------------------------------------------- */
23492 /* -- v8 instructions (in Thumb mode) -- */
23493 /* ----------------------------------------------------------- */
23495 /* If we get here, it means that all attempts to decode the
23496 instruction as ARMv7 or earlier have failed. So, if we're doing
23497 ARMv8 or later, here is the point to try for it. */
23499 if (VEX_ARM_ARCHLEVEL(archinfo
->hwcaps
) >= 8) {
23500 UInt insn32
= (INSN0(15,0) << 16) | INSN1(15,0);
23502 = decode_V8_instruction( &dres
, insn32
, condT
, True
/*isT*/,
23503 old_itstate
, new_itstate
);
23505 goto decode_success
;
23508 /* ----------------------------------------------------------- */
23509 /* -- Undecodable -- */
23510 /* ----------------------------------------------------------- */
23512 goto decode_failure
;
23516 /* All decode failures end up here. */
23518 vex_printf("disInstr(thumb): unhandled instruction: "
23519 "0x%04x 0x%04x\n", (UInt
)insn0
, (UInt
)insn1
);
23521 /* Back up ITSTATE to the initial value for this instruction.
23522 If we don't do that, any subsequent restart of the instruction
23523 will restart with the wrong value. */
23524 if (old_itstate
!= IRTemp_INVALID
)
23525 put_ITSTATE(old_itstate
);
23527 /* Tell the dispatcher that this insn cannot be decoded, and so has
23528 not been executed, and (is currently) the next to be executed.
23529 R15 should be up-to-date since it made so at the start of each
23530 insn, but nevertheless be paranoid and update it again right
23532 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
23533 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC
| 1) );
23535 dres
.whatNext
= Dis_StopHere
;
23536 dres
.jk_StopHere
= Ijk_NoDecode
;
23537 dres
.continueAt
= 0;
23541 /* All decode successes end up here. */
23542 vassert(dres
.len
== 4 || dres
.len
== 2 || dres
.len
== 20);
23543 switch (dres
.whatNext
) {
23545 llPutIReg(15, mkU32(dres
.len
+ (guest_R15_curr_instr_notENC
| 1)));
23549 llPutIReg(15, mkU32(dres
.continueAt
));
23569 /* Helper table for figuring out how many insns an IT insn
23572 An ITxyz instruction of the format "1011 1111 firstcond mask"
23573 conditionalises some number of instructions, as indicated by the
23574 following table. A value of zero indicates the instruction is
23575 invalid in some way.
23577 mask = 0 means this isn't an IT instruction
23578 fc = 15 (NV) means unpredictable
23580 The line fc = 14 (AL) is different from the others; there are
23581 additional constraints in this case.
23584 +--------------------------------
23585 fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23586 .. | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23587 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23588 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23589 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23590 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23591 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23592 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23593 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23594 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23595 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23596 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23597 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23598 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23599 | 0 4 3 0 2 0 0 0 1 0 0 0 0 0 0 0
23600 15) | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
23602 To be conservative with the analysis, let's rule out the mask = 0
23603 case, since that isn't an IT insn at all. But for all the other
23604 cases where the table contains zero, that means unpredictable, so
23605 let's say 4 to be conservative. Hence we have a safe value for any
23606 IT (mask,fc) pair that the CPU would actually identify as an IT
23607 instruction. The final table is
23610 +--------------------------------
23611 fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23612 .. | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23613 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23614 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23615 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23616 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23617 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23618 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23619 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23620 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23621 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23622 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23623 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23624 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23625 | 0 4 3 4 2 4 4 4 1 4 4 4 4 4 4 4
23626 15) | 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
23628 static const UChar it_length_table
[256]
23629 = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23630 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23631 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23632 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23633 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23634 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23635 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23636 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23637 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23638 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23639 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23640 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23641 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23642 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
23643 0, 4, 3, 4, 2, 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4,
23644 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
23648 /*------------------------------------------------------------*/
23649 /*--- Top-level fn ---*/
23650 /*------------------------------------------------------------*/
23652 /* Disassemble a single instruction into IR. The instruction
23653 is located in host memory at &guest_code[delta]. */
23655 DisResult
disInstr_ARM ( IRSB
* irsb_IN
,
23656 Bool (*resteerOkFn
) ( void*, Addr
),
23658 void* callback_opaque
,
23659 const UChar
* guest_code_IN
,
23660 Long delta_ENCODED
,
23661 Addr guest_IP_ENCODED
,
23662 VexArch guest_arch
,
23663 const VexArchInfo
* archinfo
,
23664 const VexAbiInfo
* abiinfo
,
23665 VexEndness host_endness_IN
,
23666 Bool sigill_diag_IN
)
23669 Bool isThumb
= (Bool
)(guest_IP_ENCODED
& 1);
23671 /* Set globals (see top of this file) */
23672 vassert(guest_arch
== VexArchARM
);
23675 host_endness
= host_endness_IN
;
23676 __curr_is_Thumb
= isThumb
;
23679 guest_R15_curr_instr_notENC
= (Addr32
)guest_IP_ENCODED
- 1;
23681 guest_R15_curr_instr_notENC
= (Addr32
)guest_IP_ENCODED
;
23685 dres
= disInstr_THUMB_WRK ( resteerOkFn
,
23686 resteerCisOk
, callback_opaque
,
23687 &guest_code_IN
[delta_ENCODED
- 1],
23688 archinfo
, abiinfo
, sigill_diag_IN
);
23690 dres
= disInstr_ARM_WRK ( resteerOkFn
,
23691 resteerCisOk
, callback_opaque
,
23692 &guest_code_IN
[delta_ENCODED
],
23693 archinfo
, abiinfo
, sigill_diag_IN
);
23699 /* Test program for the conversion of IRCmpF64Result values to VFP
23700 nzcv values. See handling of FCMPD et al above. */
23702 UInt foo ( UInt x )
23704 UInt ix = ((x >> 5) & 3) | (x & 1);
23705 UInt termL = (((((ix ^ 1) << 30) - 1) >> 29) + 1);
23706 UInt termR = (ix & (ix >> 1) & 1);
23707 return termL - termR;
23710 void try ( char* s, UInt ir, UInt req )
23712 UInt act = foo(ir);
23713 printf("%s 0x%02x -> req %d%d%d%d act %d%d%d%d (0x%x)\n",
23714 s, ir, (req >> 3) & 1, (req >> 2) & 1,
23715 (req >> 1) & 1, (req >> 0) & 1,
23716 (act >> 3) & 1, (act >> 2) & 1,
23717 (act >> 1) & 1, (act >> 0) & 1, act);
23724 try("UN", 0x45, 0b0011);
23725 try("LT", 0x01, 0b1000);
23726 try("GT", 0x00, 0b0010);
23727 try("EQ", 0x40, 0b0110);
23733 /* Spare code for doing reference implementations of various 64-bit
23734 SIMD interleaves/deinterleaves/concatenation ops. */
23736 // Split a 64 bit value into 4 16 bit ones, in 32-bit IRTemps with
23737 // the top halves guaranteed to be zero.
23738 static void break64to16s ( IRTemp* out3, IRTemp* out2, IRTemp* out1,
23739 IRTemp* out0, IRTemp v64 )
23741 if (out3) *out3 = newTemp(Ity_I32);
23742 if (out2) *out2 = newTemp(Ity_I32);
23743 if (out1) *out1 = newTemp(Ity_I32);
23744 if (out0) *out0 = newTemp(Ity_I32);
23745 IRTemp hi32 = newTemp(Ity_I32);
23746 IRTemp lo32 = newTemp(Ity_I32);
23747 assign(hi32, unop(Iop_64HIto32, mkexpr(v64)) );
23748 assign(lo32, unop(Iop_64to32, mkexpr(v64)) );
23749 if (out3) assign(*out3, binop(Iop_Shr32, mkexpr(hi32), mkU8(16)));
23750 if (out2) assign(*out2, binop(Iop_And32, mkexpr(hi32), mkU32(0xFFFF)));
23751 if (out1) assign(*out1, binop(Iop_Shr32, mkexpr(lo32), mkU8(16)));
23752 if (out0) assign(*out0, binop(Iop_And32, mkexpr(lo32), mkU32(0xFFFF)));
23755 // Make a 64 bit value from 4 16 bit ones, each of which is in a 32 bit
23757 static IRTemp mk64from16s ( IRTemp in3, IRTemp in2, IRTemp in1, IRTemp in0 )
23759 IRTemp hi32 = newTemp(Ity_I32);
23760 IRTemp lo32 = newTemp(Ity_I32);
23763 binop(Iop_Shl32, mkexpr(in3), mkU8(16)),
23764 binop(Iop_And32, mkexpr(in2), mkU32(0xFFFF))));
23767 binop(Iop_Shl32, mkexpr(in1), mkU8(16)),
23768 binop(Iop_And32, mkexpr(in0), mkU32(0xFFFF))));
23769 IRTemp res = newTemp(Ity_I64);
23770 assign(res, binop(Iop_32HLto64, mkexpr(hi32), mkexpr(lo32)));
23774 static IRExpr* mk_InterleaveLO16x4 ( IRTemp a3210, IRTemp b3210 )
23776 // returns a1 b1 a0 b0
23777 IRTemp a1, a0, b1, b0;
23778 break64to16s(NULL, NULL, &a1, &a0, a3210);
23779 break64to16s(NULL, NULL, &b1, &b0, b3210);
23780 return mkexpr(mk64from16s(a1, b1, a0, b0));
23783 static IRExpr* mk_InterleaveHI16x4 ( IRTemp a3210, IRTemp b3210 )
23785 // returns a3 b3 a2 b2
23786 IRTemp a3, a2, b3, b2;
23787 break64to16s(&a3, &a2, NULL, NULL, a3210);
23788 break64to16s(&b3, &b2, NULL, NULL, b3210);
23789 return mkexpr(mk64from16s(a3, b3, a2, b2));
23792 static IRExpr* mk_CatEvenLanes16x4 ( IRTemp a3210, IRTemp b3210 )
23794 // returns a2 a0 b2 b0
23795 IRTemp a2, a0, b2, b0;
23796 break64to16s(NULL, &a2, NULL, &a0, a3210);
23797 break64to16s(NULL, &b2, NULL, &b0, b3210);
23798 return mkexpr(mk64from16s(a2, a0, b2, b0));
23801 static IRExpr* mk_CatOddLanes16x4 ( IRTemp a3210, IRTemp b3210 )
23803 // returns a3 a1 b3 b1
23804 IRTemp a3, a1, b3, b1;
23805 break64to16s(&a3, NULL, &a1, NULL, a3210);
23806 break64to16s(&b3, NULL, &b1, NULL, b3210);
23807 return mkexpr(mk64from16s(a3, a1, b3, b1));
23810 static IRExpr* mk_InterleaveOddLanes16x4 ( IRTemp a3210, IRTemp b3210 )
23812 // returns a3 b3 a1 b1
23813 IRTemp a3, b3, a1, b1;
23814 break64to16s(&a3, NULL, &a1, NULL, a3210);
23815 break64to16s(&b3, NULL, &b1, NULL, b3210);
23816 return mkexpr(mk64from16s(a3, b3, a1, b1));
23819 static IRExpr* mk_InterleaveEvenLanes16x4 ( IRTemp a3210, IRTemp b3210 )
23821 // returns a2 b2 a0 b0
23822 IRTemp a2, b2, a0, b0;
23823 break64to16s(NULL, &a2, NULL, &a0, a3210);
23824 break64to16s(NULL, &b2, NULL, &b0, b3210);
23825 return mkexpr(mk64from16s(a2, b2, a0, b0));
23828 static void break64to8s ( IRTemp* out7, IRTemp* out6, IRTemp* out5,
23829 IRTemp* out4, IRTemp* out3, IRTemp* out2,
23830 IRTemp* out1,IRTemp* out0, IRTemp v64 )
23832 if (out7) *out7 = newTemp(Ity_I32);
23833 if (out6) *out6 = newTemp(Ity_I32);
23834 if (out5) *out5 = newTemp(Ity_I32);
23835 if (out4) *out4 = newTemp(Ity_I32);
23836 if (out3) *out3 = newTemp(Ity_I32);
23837 if (out2) *out2 = newTemp(Ity_I32);
23838 if (out1) *out1 = newTemp(Ity_I32);
23839 if (out0) *out0 = newTemp(Ity_I32);
23840 IRTemp hi32 = newTemp(Ity_I32);
23841 IRTemp lo32 = newTemp(Ity_I32);
23842 assign(hi32, unop(Iop_64HIto32, mkexpr(v64)) );
23843 assign(lo32, unop(Iop_64to32, mkexpr(v64)) );
23845 assign(*out7, binop(Iop_And32,
23846 binop(Iop_Shr32, mkexpr(hi32), mkU8(24)),
23849 assign(*out6, binop(Iop_And32,
23850 binop(Iop_Shr32, mkexpr(hi32), mkU8(16)),
23853 assign(*out5, binop(Iop_And32,
23854 binop(Iop_Shr32, mkexpr(hi32), mkU8(8)),
23857 assign(*out4, binop(Iop_And32, mkexpr(hi32), mkU32(0xFF)));
23859 assign(*out3, binop(Iop_And32,
23860 binop(Iop_Shr32, mkexpr(lo32), mkU8(24)),
23863 assign(*out2, binop(Iop_And32,
23864 binop(Iop_Shr32, mkexpr(lo32), mkU8(16)),
23867 assign(*out1, binop(Iop_And32,
23868 binop(Iop_Shr32, mkexpr(lo32), mkU8(8)),
23871 assign(*out0, binop(Iop_And32, mkexpr(lo32), mkU32(0xFF)));
23874 static IRTemp mk64from8s ( IRTemp in7, IRTemp in6, IRTemp in5, IRTemp in4,
23875 IRTemp in3, IRTemp in2, IRTemp in1, IRTemp in0 )
23877 IRTemp hi32 = newTemp(Ity_I32);
23878 IRTemp lo32 = newTemp(Ity_I32);
23883 binop(Iop_And32, mkexpr(in7), mkU32(0xFF)),
23886 binop(Iop_And32, mkexpr(in6), mkU32(0xFF)),
23890 binop(Iop_And32, mkexpr(in5), mkU32(0xFF)), mkU8(8)),
23892 mkexpr(in4), mkU32(0xFF)))));
23897 binop(Iop_And32, mkexpr(in3), mkU32(0xFF)),
23900 binop(Iop_And32, mkexpr(in2), mkU32(0xFF)),
23904 binop(Iop_And32, mkexpr(in1), mkU32(0xFF)), mkU8(8)),
23906 mkexpr(in0), mkU32(0xFF)))));
23907 IRTemp res = newTemp(Ity_I64);
23908 assign(res, binop(Iop_32HLto64, mkexpr(hi32), mkexpr(lo32)));
23912 static IRExpr* mk_InterleaveLO8x8 ( IRTemp a76543210, IRTemp b76543210 )
23914 // returns a3 b3 a2 b2 a1 b1 a0 b0
23915 IRTemp a3, b3, a2, b2, a1, a0, b1, b0;
23916 break64to8s(NULL, NULL, NULL, NULL, &a3, &a2, &a1, &a0, a76543210);
23917 break64to8s(NULL, NULL, NULL, NULL, &b3, &b2, &b1, &b0, b76543210);
23918 return mkexpr(mk64from8s(a3, b3, a2, b2, a1, b1, a0, b0));
23921 static IRExpr* mk_InterleaveHI8x8 ( IRTemp a76543210, IRTemp b76543210 )
23923 // returns a7 b7 a6 b6 a5 b5 a4 b4
23924 IRTemp a7, b7, a6, b6, a5, b5, a4, b4;
23925 break64to8s(&a7, &a6, &a5, &a4, NULL, NULL, NULL, NULL, a76543210);
23926 break64to8s(&b7, &b6, &b5, &b4, NULL, NULL, NULL, NULL, b76543210);
23927 return mkexpr(mk64from8s(a7, b7, a6, b6, a5, b5, a4, b4));
23930 static IRExpr* mk_CatEvenLanes8x8 ( IRTemp a76543210, IRTemp b76543210 )
23932 // returns a6 a4 a2 a0 b6 b4 b2 b0
23933 IRTemp a6, a4, a2, a0, b6, b4, b2, b0;
23934 break64to8s(NULL, &a6, NULL, &a4, NULL, &a2, NULL, &a0, a76543210);
23935 break64to8s(NULL, &b6, NULL, &b4, NULL, &b2, NULL, &b0, b76543210);
23936 return mkexpr(mk64from8s(a6, a4, a2, a0, b6, b4, b2, b0));
23939 static IRExpr* mk_CatOddLanes8x8 ( IRTemp a76543210, IRTemp b76543210 )
23941 // returns a7 a5 a3 a1 b7 b5 b3 b1
23942 IRTemp a7, a5, a3, a1, b7, b5, b3, b1;
23943 break64to8s(&a7, NULL, &a5, NULL, &a3, NULL, &a1, NULL, a76543210);
23944 break64to8s(&b7, NULL, &b5, NULL, &b3, NULL, &b1, NULL, b76543210);
23945 return mkexpr(mk64from8s(a7, a5, a3, a1, b7, b5, b3, b1));
23948 static IRExpr* mk_InterleaveEvenLanes8x8 ( IRTemp a76543210, IRTemp b76543210 )
23950 // returns a6 b6 a4 b4 a2 b2 a0 b0
23951 IRTemp a6, b6, a4, b4, a2, b2, a0, b0;
23952 break64to8s(NULL, &a6, NULL, &a4, NULL, &a2, NULL, &a0, a76543210);
23953 break64to8s(NULL, &b6, NULL, &b4, NULL, &b2, NULL, &b0, b76543210);
23954 return mkexpr(mk64from8s(a6, b6, a4, b4, a2, b2, a0, b0));
23957 static IRExpr* mk_InterleaveOddLanes8x8 ( IRTemp a76543210, IRTemp b76543210 )
23959 // returns a7 b7 a5 b5 a3 b3 a1 b1
23960 IRTemp a7, b7, a5, b5, a3, b3, a1, b1;
23961 break64to8s(&a7, NULL, &a5, NULL, &a3, NULL, &a1, NULL, a76543210);
23962 break64to8s(&b7, NULL, &b5, NULL, &b3, NULL, &b1, NULL, b76543210);
23963 return mkexpr(mk64from8s(a7, b7, a5, b5, a3, b3, a1, b1));
23966 static IRExpr* mk_InterleaveLO32x2 ( IRTemp a10, IRTemp b10 )
23969 return binop(Iop_32HLto64, unop(Iop_64to32, mkexpr(a10)),
23970 unop(Iop_64to32, mkexpr(b10)));
23973 static IRExpr* mk_InterleaveHI32x2 ( IRTemp a10, IRTemp b10 )
23976 return binop(Iop_32HLto64, unop(Iop_64HIto32, mkexpr(a10)),
23977 unop(Iop_64HIto32, mkexpr(b10)));
23981 /*--------------------------------------------------------------------*/
23982 /*--- end guest_arm_toIR.c ---*/
23983 /*--------------------------------------------------------------------*/