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
,
6511 /* else fall through */
6513 dreg
= ((theInstr
>> 18) & 0x10) | ((theInstr
>> 12) & 0xF);
6514 mreg
= ((theInstr
>> 1) & 0x10) | (theInstr
& 0xF);
6519 if ((theInstr
>> 8) & 1) {
6522 op
= U
? Iop_ShrN16x8
: Iop_SarN16x8
;
6523 cvt
= U
? Iop_QNarrowUn16Uto8Ux8
: Iop_QNarrowUn16Sto8Sx8
;
6524 cvt2
= U
? Iop_Widen8Uto16x8
: Iop_Widen8Sto16x8
;
6527 op
= U
? Iop_ShrN32x4
: Iop_SarN32x4
;
6528 cvt
= U
? Iop_QNarrowUn32Uto16Ux4
: Iop_QNarrowUn32Sto16Sx4
;
6529 cvt2
= U
? Iop_Widen16Uto32x4
: Iop_Widen16Sto32x4
;
6532 op
= U
? Iop_ShrN64x2
: Iop_SarN64x2
;
6533 cvt
= U
? Iop_QNarrowUn64Uto32Ux2
: Iop_QNarrowUn64Sto32Sx2
;
6534 cvt2
= U
? Iop_Widen32Uto64x2
: Iop_Widen32Sto64x2
;
6539 DIP("vq%sshrn.%c%d d%u, q%u, #%u\n", B
? "r" : "",
6540 U
? 'u' : 's', 8 << size
, dreg
, mreg
, shift_imm
);
6546 cvt
= Iop_QNarrowUn16Sto8Ux8
;
6547 cvt2
= Iop_Widen8Uto16x8
;
6551 cvt
= Iop_QNarrowUn32Sto16Ux4
;
6552 cvt2
= Iop_Widen16Uto32x4
;
6556 cvt
= Iop_QNarrowUn64Sto32Ux2
;
6557 cvt2
= Iop_Widen32Uto64x2
;
6562 DIP("vq%sshrun.s%d d%u, q%u, #%u\n", B
? "r" : "",
6563 8 << size
, dreg
, mreg
, shift_imm
);
6566 if (shift_imm
> 0) {
6569 case 1: imm
= (imm
<< 16) | imm
; /* fall through */
6570 case 2: imm
= (imm
<< 32) | imm
; /* fall through */
6572 case 0: default: vassert(0);
6575 case 1: add
= Iop_Add16x8
; break;
6576 case 2: add
= Iop_Add32x4
; break;
6577 case 3: add
= Iop_Add64x2
; break;
6578 case 0: default: vassert(0);
6582 reg_m
= newTemp(Ity_V128
);
6583 res
= newTemp(Ity_V128
);
6584 assign(reg_m
, getQReg(mreg
));
6586 /* VQRSHRN, VQRSHRUN */
6587 assign(res
, binop(add
,
6588 binop(op
, mkexpr(reg_m
), mkU8(shift_imm
)),
6592 mkU8(shift_imm
- 1)),
6595 /* VQSHRN, VQSHRUN */
6596 assign(res
, binop(op
, mkexpr(reg_m
), mkU8(shift_imm
)));
6598 setFlag_QC(unop(cvt2
, unop(cvt
, mkexpr(res
))), mkexpr(res
),
6600 putDRegI64(dreg
, unop(cvt
, mkexpr(res
)), condT
);
6604 VMOVL ::= VSHLL #0 */
6610 shift_imm
= (8 << size
) - shift_imm
;
6611 res
= newTemp(Ity_V128
);
6615 cvt
= U
? Iop_Widen8Uto16x8
: Iop_Widen8Sto16x8
;
6619 cvt
= U
? Iop_Widen16Uto32x4
: Iop_Widen16Sto32x4
;
6623 cvt
= U
? Iop_Widen32Uto64x2
: Iop_Widen32Sto64x2
;
6630 assign(res
, binop(op
, unop(cvt
, getDRegI64(mreg
)), mkU8(shift_imm
)));
6631 putQReg(dreg
, mkexpr(res
), condT
);
6632 if (shift_imm
== 0) {
6633 DIP("vmovl.%c%d q%u, d%u\n", U
? 'u' : 's', 8 << size
,
6636 DIP("vshll.%c%d q%u, d%u, #%u\n", U
? 'u' : 's', 8 << size
,
6637 dreg
, mreg
, shift_imm
);
6642 /* VCVT floating-point <-> fixed-point */
6643 if ((theInstr
>> 8) & 1) {
6645 op
= Q
? Iop_F32ToFixed32Ux4_RZ
: Iop_F32ToFixed32Ux2_RZ
;
6647 op
= Q
? Iop_F32ToFixed32Sx4_RZ
: Iop_F32ToFixed32Sx2_RZ
;
6649 DIP("vcvt.%c32.f32 %c%u, %c%u, #%u\n", U
? 'u' : 's',
6650 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
,
6651 64 - ((theInstr
>> 16) & 0x3f));
6654 op
= Q
? Iop_Fixed32UToF32x4_RN
: Iop_Fixed32UToF32x2_RN
;
6656 op
= Q
? Iop_Fixed32SToF32x4_RN
: Iop_Fixed32SToF32x2_RN
;
6658 DIP("vcvt.f32.%c32 %c%u, %c%u, #%u\n", U
? 'u' : 's',
6659 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
,
6660 64 - ((theInstr
>> 16) & 0x3f));
6662 if (((theInstr
>> 21) & 1) == 0)
6665 putQReg(dreg
, binop(op
, getQReg(mreg
),
6666 mkU8(64 - ((theInstr
>> 16) & 0x3f))), condT
);
6668 putDRegI64(dreg
, binop(op
, getDRegI64(mreg
),
6669 mkU8(64 - ((theInstr
>> 16) & 0x3f))), condT
);
6679 /* A7.4.5 Two registers, miscellaneous */
6681 Bool
dis_neon_data_2reg_misc ( UInt theInstr
, IRTemp condT
)
6683 UInt A
= (theInstr
>> 16) & 3;
6684 UInt B
= (theInstr
>> 6) & 0x1f;
6685 UInt Q
= (theInstr
>> 6) & 1;
6686 UInt U
= (theInstr
>> 24) & 1;
6687 UInt size
= (theInstr
>> 18) & 3;
6688 UInt dreg
= get_neon_d_regno(theInstr
);
6689 UInt mreg
= get_neon_m_regno(theInstr
);
6690 UInt F
= (theInstr
>> 10) & 1;
6691 IRTemp arg_d
= IRTemp_INVALID
;
6692 IRTemp arg_m
= IRTemp_INVALID
;
6693 IRTemp res
= IRTemp_INVALID
;
6697 arg_m
= newTemp(Ity_V128
);
6698 res
= newTemp(Ity_V128
);
6699 assign(arg_m
, getQReg(mreg
));
6701 arg_m
= newTemp(Ity_I64
);
6702 res
= newTemp(Ity_I64
);
6703 assign(arg_m
, getDRegI64(mreg
));
6711 op
= Q
? Iop_Reverse8sIn64_x2
: Iop_Reverse8sIn64_x1
;
6714 op
= Q
? Iop_Reverse16sIn64_x2
: Iop_Reverse16sIn64_x1
;
6717 op
= Q
? Iop_Reverse32sIn64_x2
: Iop_Reverse32sIn64_x1
;
6724 assign(res
, unop(op
, mkexpr(arg_m
)));
6725 DIP("vrev64.%d %c%u, %c%u\n", 8 << size
,
6726 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
6734 op
= Q
? Iop_Reverse8sIn32_x4
: Iop_Reverse8sIn32_x2
;
6737 op
= Q
? Iop_Reverse16sIn32_x4
: Iop_Reverse16sIn32_x2
;
6745 assign(res
, unop(op
, mkexpr(arg_m
)));
6746 DIP("vrev32.%d %c%u, %c%u\n", 8 << size
,
6747 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
6755 op
= Q
? Iop_Reverse8sIn16_x8
: Iop_Reverse8sIn16_x4
;
6764 assign(res
, unop(op
, mkexpr(arg_m
)));
6765 DIP("vrev16.%d %c%u, %c%u\n", 8 << size
,
6766 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
6775 U
= (theInstr
>> 7) & 1;
6778 case 0: op
= U
? Iop_PwAddL8Ux16
: Iop_PwAddL8Sx16
; break;
6779 case 1: op
= U
? Iop_PwAddL16Ux8
: Iop_PwAddL16Sx8
; break;
6780 case 2: op
= U
? Iop_PwAddL32Ux4
: Iop_PwAddL32Sx4
; break;
6781 case 3: return False
;
6782 default: vassert(0);
6786 case 0: op
= U
? Iop_PwAddL8Ux8
: Iop_PwAddL8Sx8
; break;
6787 case 1: op
= U
? Iop_PwAddL16Ux4
: Iop_PwAddL16Sx4
; break;
6788 case 2: op
= U
? Iop_PwAddL32Ux2
: Iop_PwAddL32Sx2
; break;
6789 case 3: return False
;
6790 default: vassert(0);
6793 assign(res
, unop(op
, mkexpr(arg_m
)));
6794 DIP("vpaddl.%c%d %c%u, %c%u\n", U
? 'u' : 's', 8 << size
,
6795 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
6805 case 0: op
= Q
? Iop_Cls8x16
: Iop_Cls8x8
; break;
6806 case 1: op
= Q
? Iop_Cls16x8
: Iop_Cls16x4
; break;
6807 case 2: op
= Q
? Iop_Cls32x4
: Iop_Cls32x2
; break;
6808 case 3: return False
;
6809 default: vassert(0);
6811 assign(res
, unop(op
, mkexpr(arg_m
)));
6812 DIP("vcls.s%d %c%u, %c%u\n", 8 << size
, Q
? 'q' : 'd', dreg
,
6813 Q
? 'q' : 'd', mreg
);
6820 case 0: op
= Q
? Iop_Clz8x16
: Iop_Clz8x8
; break;
6821 case 1: op
= Q
? Iop_Clz16x8
: Iop_Clz16x4
; break;
6822 case 2: op
= Q
? Iop_Clz32x4
: Iop_Clz32x2
; break;
6823 case 3: return False
;
6824 default: vassert(0);
6826 assign(res
, unop(op
, mkexpr(arg_m
)));
6827 DIP("vclz.i%d %c%u, %c%u\n", 8 << size
, Q
? 'q' : 'd', dreg
,
6828 Q
? 'q' : 'd', mreg
);
6833 assign(res
, unop(Q
? Iop_Cnt8x16
: Iop_Cnt8x8
, mkexpr(arg_m
)));
6834 DIP("vcnt.8 %c%u, %c%u\n", Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd',
6840 assign(res
, unop(Iop_NotV128
, mkexpr(arg_m
)));
6842 assign(res
, unop(Iop_Not64
, mkexpr(arg_m
)));
6843 DIP("vmvn %c%u, %c%u\n", Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd',
6850 U
= (theInstr
>> 7) & 1;
6854 op
= U
? Iop_PwAddL8Ux16
: Iop_PwAddL8Sx16
;
6855 add_op
= Iop_Add16x8
;
6858 op
= U
? Iop_PwAddL16Ux8
: Iop_PwAddL16Sx8
;
6859 add_op
= Iop_Add32x4
;
6862 op
= U
? Iop_PwAddL32Ux4
: Iop_PwAddL32Sx4
;
6863 add_op
= Iop_Add64x2
;
6873 op
= U
? Iop_PwAddL8Ux8
: Iop_PwAddL8Sx8
;
6874 add_op
= Iop_Add16x4
;
6877 op
= U
? Iop_PwAddL16Ux4
: Iop_PwAddL16Sx4
;
6878 add_op
= Iop_Add32x2
;
6881 op
= U
? Iop_PwAddL32Ux2
: Iop_PwAddL32Sx2
;
6891 arg_d
= newTemp(Ity_V128
);
6892 assign(arg_d
, getQReg(dreg
));
6894 arg_d
= newTemp(Ity_I64
);
6895 assign(arg_d
, getDRegI64(dreg
));
6897 assign(res
, binop(add_op
, unop(op
, mkexpr(arg_m
)),
6899 DIP("vpadal.%c%d %c%u, %c%u\n", U
? 'u' : 's', 8 << size
,
6900 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
6905 IROp op_sub
, op_qsub
, op_cmp
;
6907 IRExpr
*zero1
, *zero2
;
6910 zero1
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
6911 zero2
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
6912 mask
= newTemp(Ity_V128
);
6913 tmp
= newTemp(Ity_V128
);
6917 mask
= newTemp(Ity_I64
);
6918 tmp
= newTemp(Ity_I64
);
6922 op_sub
= Q
? Iop_Sub8x16
: Iop_Sub8x8
;
6923 op_qsub
= Q
? Iop_QSub8Sx16
: Iop_QSub8Sx8
;
6924 op_cmp
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
;
6927 op_sub
= Q
? Iop_Sub16x8
: Iop_Sub16x4
;
6928 op_qsub
= Q
? Iop_QSub16Sx8
: Iop_QSub16Sx4
;
6929 op_cmp
= Q
? Iop_CmpGT16Sx8
: Iop_CmpGT16Sx4
;
6932 op_sub
= Q
? Iop_Sub32x4
: Iop_Sub32x2
;
6933 op_qsub
= Q
? Iop_QSub32Sx4
: Iop_QSub32Sx2
;
6934 op_cmp
= Q
? Iop_CmpGT32Sx4
: Iop_CmpGT32Sx2
;
6941 assign(mask
, binop(op_cmp
, mkexpr(arg_m
), zero1
));
6942 neg
= binop(op_qsub
, zero2
, mkexpr(arg_m
));
6943 neg2
= binop(op_sub
, zero2
, mkexpr(arg_m
));
6944 assign(res
, binop(Q
? Iop_OrV128
: Iop_Or64
,
6945 binop(Q
? Iop_AndV128
: Iop_And64
,
6948 binop(Q
? Iop_AndV128
: Iop_And64
,
6949 unop(Q
? Iop_NotV128
: Iop_Not64
,
6952 assign(tmp
, binop(Q
? Iop_OrV128
: Iop_Or64
,
6953 binop(Q
? Iop_AndV128
: Iop_And64
,
6956 binop(Q
? Iop_AndV128
: Iop_And64
,
6957 unop(Q
? Iop_NotV128
: Iop_Not64
,
6960 setFlag_QC(mkexpr(res
), mkexpr(tmp
), Q
, condT
);
6961 DIP("vqabs.s%d %c%u, %c%u\n", 8 << size
, Q
? 'q' : 'd', dreg
,
6962 Q
? 'q' : 'd', mreg
);
6970 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
6976 op
= Q
? Iop_QSub8Sx16
: Iop_QSub8Sx8
;
6977 op2
= Q
? Iop_Sub8x16
: Iop_Sub8x8
;
6980 op
= Q
? Iop_QSub16Sx8
: Iop_QSub16Sx4
;
6981 op2
= Q
? Iop_Sub16x8
: Iop_Sub16x4
;
6984 op
= Q
? Iop_QSub32Sx4
: Iop_QSub32Sx2
;
6985 op2
= Q
? Iop_Sub32x4
: Iop_Sub32x2
;
6992 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
6993 setFlag_QC(mkexpr(res
), binop(op2
, zero
, mkexpr(arg_m
)),
6995 DIP("vqneg.s%d %c%u, %c%u\n", 8 << size
, Q
? 'q' : 'd', dreg
,
6996 Q
? 'q' : 'd', mreg
);
7003 putQReg(dreg
, mkexpr(res
), condT
);
7005 putDRegI64(dreg
, mkexpr(res
), condT
);
7010 arg_m
= newTemp(Ity_V128
);
7011 res
= newTemp(Ity_V128
);
7012 assign(arg_m
, getQReg(mreg
));
7014 arg_m
= newTemp(Ity_I64
);
7015 res
= newTemp(Ity_I64
);
7016 assign(arg_m
, getDRegI64(mreg
));
7018 switch ((B
>> 1) & 0x7) {
7024 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7030 case 0: case 1: case 3: return False
;
7031 case 2: op
= Q
? Iop_CmpGT32Fx4
: Iop_CmpGT32Fx2
; break;
7032 default: vassert(0);
7036 case 0: op
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
; break;
7037 case 1: op
= Q
? Iop_CmpGT16Sx8
: Iop_CmpGT16Sx4
; break;
7038 case 2: op
= Q
? Iop_CmpGT32Sx4
: Iop_CmpGT32Sx2
; break;
7039 case 3: return False
;
7040 default: vassert(0);
7043 assign(res
, binop(op
, mkexpr(arg_m
), zero
));
7044 DIP("vcgt.%c%d %c%u, %c%u, #0\n", F
? 'f' : 's', 8 << size
,
7045 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7053 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7059 case 0: case 1: case 3: return False
;
7060 case 2: op
= Q
? Iop_CmpGE32Fx4
: Iop_CmpGE32Fx2
; break;
7061 default: vassert(0);
7063 assign(res
, binop(op
, mkexpr(arg_m
), zero
));
7066 case 0: op
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
; break;
7067 case 1: op
= Q
? Iop_CmpGT16Sx8
: Iop_CmpGT16Sx4
; break;
7068 case 2: op
= Q
? Iop_CmpGT32Sx4
: Iop_CmpGT32Sx2
; break;
7069 case 3: return False
;
7070 default: vassert(0);
7072 assign(res
, unop(Q
? Iop_NotV128
: Iop_Not64
,
7073 binop(op
, zero
, mkexpr(arg_m
))));
7075 DIP("vcge.%c%d %c%u, %c%u, #0\n", F
? 'f' : 's', 8 << size
,
7076 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7085 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7090 case 0: case 1: case 3: return False
;
7091 case 2: op
= Q
? Iop_CmpEQ32Fx4
: Iop_CmpEQ32Fx2
; break;
7092 default: vassert(0);
7094 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
7097 case 0: op
= Q
? Iop_CmpNEZ8x16
: Iop_CmpNEZ8x8
; break;
7098 case 1: op
= Q
? Iop_CmpNEZ16x8
: Iop_CmpNEZ16x4
; break;
7099 case 2: op
= Q
? Iop_CmpNEZ32x4
: Iop_CmpNEZ32x2
; break;
7100 case 3: return False
;
7101 default: vassert(0);
7103 assign(res
, unop(Q
? Iop_NotV128
: Iop_Not64
,
7104 unop(op
, mkexpr(arg_m
))));
7106 DIP("vceq.%c%d %c%u, %c%u, #0\n", F
? 'f' : 'i', 8 << size
,
7107 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7115 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7121 case 0: case 1: case 3: return False
;
7122 case 2: op
= Q
? Iop_CmpGE32Fx4
: Iop_CmpGE32Fx2
; break;
7123 default: vassert(0);
7125 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
7128 case 0: op
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
; break;
7129 case 1: op
= Q
? Iop_CmpGT16Sx8
: Iop_CmpGT16Sx4
; break;
7130 case 2: op
= Q
? Iop_CmpGT32Sx4
: Iop_CmpGT32Sx2
; break;
7131 case 3: return False
;
7132 default: vassert(0);
7134 assign(res
, unop(Q
? Iop_NotV128
: Iop_Not64
,
7135 binop(op
, mkexpr(arg_m
), zero
)));
7137 DIP("vcle.%c%d %c%u, %c%u, #0\n", F
? 'f' : 's', 8 << size
,
7138 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7146 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7152 case 0: case 1: case 3: return False
;
7153 case 2: op
= Q
? Iop_CmpGT32Fx4
: Iop_CmpGT32Fx2
; break;
7154 default: vassert(0);
7156 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
7159 case 0: op
= Q
? Iop_CmpGT8Sx16
: Iop_CmpGT8Sx8
; break;
7160 case 1: op
= Q
? Iop_CmpGT16Sx8
: Iop_CmpGT16Sx4
; break;
7161 case 2: op
= Q
? Iop_CmpGT32Sx4
: Iop_CmpGT32Sx2
; break;
7162 case 3: return False
;
7163 default: vassert(0);
7165 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
7167 DIP("vclt.%c%d %c%u, %c%u, #0\n", F
? 'f' : 's', 8 << size
,
7168 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7178 case 0: op
= Q
? Iop_Abs8x16
: Iop_Abs8x8
; break;
7179 case 1: op
= Q
? Iop_Abs16x8
: Iop_Abs16x4
; break;
7180 case 2: op
= Q
? Iop_Abs32x4
: Iop_Abs32x2
; break;
7181 case 3: return False
;
7182 default: vassert(0);
7184 assign(res
, unop(op
, mkexpr(arg_m
)));
7186 assign(res
, unop(Q
? Iop_Abs32Fx4
: Iop_Abs32Fx2
,
7189 DIP("vabs.%c%d %c%u, %c%u\n",
7190 F
? 'f' : 's', 8 << size
, Q
? 'q' : 'd', dreg
,
7191 Q
? 'q' : 'd', mreg
);
7200 case 0: case 1: case 3: return False
;
7201 case 2: op
= Q
? Iop_Neg32Fx4
: Iop_Neg32Fx2
; break;
7202 default: vassert(0);
7204 assign(res
, unop(op
, mkexpr(arg_m
)));
7207 zero
= binop(Iop_64HLtoV128
, mkU64(0), mkU64(0));
7212 case 0: op
= Q
? Iop_Sub8x16
: Iop_Sub8x8
; break;
7213 case 1: op
= Q
? Iop_Sub16x8
: Iop_Sub16x4
; break;
7214 case 2: op
= Q
? Iop_Sub32x4
: Iop_Sub32x2
; break;
7215 case 3: return False
;
7216 default: vassert(0);
7218 assign(res
, binop(op
, zero
, mkexpr(arg_m
)));
7220 DIP("vneg.%c%d %c%u, %c%u\n",
7221 F
? 'f' : 's', 8 << size
, Q
? 'q' : 'd', dreg
,
7222 Q
? 'q' : 'd', mreg
);
7229 putQReg(dreg
, mkexpr(res
), condT
);
7231 putDRegI64(dreg
, mkexpr(res
), condT
);
7235 if ((B
>> 1) == 0) {
7238 arg_m
= newTemp(Ity_V128
);
7239 assign(arg_m
, getQReg(mreg
));
7240 putQReg(mreg
, getQReg(dreg
), condT
);
7241 putQReg(dreg
, mkexpr(arg_m
), condT
);
7243 arg_m
= newTemp(Ity_I64
);
7244 assign(arg_m
, getDRegI64(mreg
));
7245 putDRegI64(mreg
, getDRegI64(dreg
), condT
);
7246 putDRegI64(dreg
, mkexpr(arg_m
), condT
);
7248 DIP("vswp %c%u, %c%u\n",
7249 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7251 } else if ((B
>> 1) == 1) {
7253 IROp op_odd
= Iop_INVALID
, op_even
= Iop_INVALID
;
7254 IRTemp old_m
, old_d
, new_d
, new_m
;
7256 old_m
= newTemp(Ity_V128
);
7257 old_d
= newTemp(Ity_V128
);
7258 new_m
= newTemp(Ity_V128
);
7259 new_d
= newTemp(Ity_V128
);
7260 assign(old_m
, getQReg(mreg
));
7261 assign(old_d
, getQReg(dreg
));
7263 old_m
= newTemp(Ity_I64
);
7264 old_d
= newTemp(Ity_I64
);
7265 new_m
= newTemp(Ity_I64
);
7266 new_d
= newTemp(Ity_I64
);
7267 assign(old_m
, getDRegI64(mreg
));
7268 assign(old_d
, getDRegI64(dreg
));
7273 op_odd
= Iop_InterleaveOddLanes8x16
;
7274 op_even
= Iop_InterleaveEvenLanes8x16
;
7277 op_odd
= Iop_InterleaveOddLanes16x8
;
7278 op_even
= Iop_InterleaveEvenLanes16x8
;
7281 op_odd
= Iop_InterleaveOddLanes32x4
;
7282 op_even
= Iop_InterleaveEvenLanes32x4
;
7292 op_odd
= Iop_InterleaveOddLanes8x8
;
7293 op_even
= Iop_InterleaveEvenLanes8x8
;
7296 op_odd
= Iop_InterleaveOddLanes16x4
;
7297 op_even
= Iop_InterleaveEvenLanes16x4
;
7300 op_odd
= Iop_InterleaveHI32x2
;
7301 op_even
= Iop_InterleaveLO32x2
;
7309 assign(new_d
, binop(op_even
, mkexpr(old_m
), mkexpr(old_d
)));
7310 assign(new_m
, binop(op_odd
, mkexpr(old_m
), mkexpr(old_d
)));
7312 putQReg(dreg
, mkexpr(new_d
), condT
);
7313 putQReg(mreg
, mkexpr(new_m
), condT
);
7315 putDRegI64(dreg
, mkexpr(new_d
), condT
);
7316 putDRegI64(mreg
, mkexpr(new_m
), condT
);
7318 DIP("vtrn.%d %c%u, %c%u\n",
7319 8 << size
, Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7321 } else if ((B
>> 1) == 2) {
7323 IROp op_even
, op_odd
;
7324 IRTemp old_m
, old_d
, new_m
, new_d
;
7325 if (!Q
&& size
== 2)
7328 old_m
= newTemp(Ity_V128
);
7329 old_d
= newTemp(Ity_V128
);
7330 new_m
= newTemp(Ity_V128
);
7331 new_d
= newTemp(Ity_V128
);
7332 assign(old_m
, getQReg(mreg
));
7333 assign(old_d
, getQReg(dreg
));
7335 old_m
= newTemp(Ity_I64
);
7336 old_d
= newTemp(Ity_I64
);
7337 new_m
= newTemp(Ity_I64
);
7338 new_d
= newTemp(Ity_I64
);
7339 assign(old_m
, getDRegI64(mreg
));
7340 assign(old_d
, getDRegI64(dreg
));
7344 op_odd
= Q
? Iop_CatOddLanes8x16
: Iop_CatOddLanes8x8
;
7345 op_even
= Q
? Iop_CatEvenLanes8x16
: Iop_CatEvenLanes8x8
;
7348 op_odd
= Q
? Iop_CatOddLanes16x8
: Iop_CatOddLanes16x4
;
7349 op_even
= Q
? Iop_CatEvenLanes16x8
: Iop_CatEvenLanes16x4
;
7352 op_odd
= Iop_CatOddLanes32x4
;
7353 op_even
= Iop_CatEvenLanes32x4
;
7360 assign(new_d
, binop(op_even
, mkexpr(old_m
), mkexpr(old_d
)));
7361 assign(new_m
, binop(op_odd
, mkexpr(old_m
), mkexpr(old_d
)));
7363 putQReg(dreg
, mkexpr(new_d
), condT
);
7364 putQReg(mreg
, mkexpr(new_m
), condT
);
7366 putDRegI64(dreg
, mkexpr(new_d
), condT
);
7367 putDRegI64(mreg
, mkexpr(new_m
), condT
);
7369 DIP("vuzp.%d %c%u, %c%u\n",
7370 8 << size
, Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7372 } else if ((B
>> 1) == 3) {
7375 IRTemp old_m
, old_d
, new_m
, new_d
;
7376 if (!Q
&& size
== 2)
7379 old_m
= newTemp(Ity_V128
);
7380 old_d
= newTemp(Ity_V128
);
7381 new_m
= newTemp(Ity_V128
);
7382 new_d
= newTemp(Ity_V128
);
7383 assign(old_m
, getQReg(mreg
));
7384 assign(old_d
, getQReg(dreg
));
7386 old_m
= newTemp(Ity_I64
);
7387 old_d
= newTemp(Ity_I64
);
7388 new_m
= newTemp(Ity_I64
);
7389 new_d
= newTemp(Ity_I64
);
7390 assign(old_m
, getDRegI64(mreg
));
7391 assign(old_d
, getDRegI64(dreg
));
7395 op_hi
= Q
? Iop_InterleaveHI8x16
: Iop_InterleaveHI8x8
;
7396 op_lo
= Q
? Iop_InterleaveLO8x16
: Iop_InterleaveLO8x8
;
7399 op_hi
= Q
? Iop_InterleaveHI16x8
: Iop_InterleaveHI16x4
;
7400 op_lo
= Q
? Iop_InterleaveLO16x8
: Iop_InterleaveLO16x4
;
7403 op_hi
= Iop_InterleaveHI32x4
;
7404 op_lo
= Iop_InterleaveLO32x4
;
7411 assign(new_d
, binop(op_lo
, mkexpr(old_m
), mkexpr(old_d
)));
7412 assign(new_m
, binop(op_hi
, mkexpr(old_m
), mkexpr(old_d
)));
7414 putQReg(dreg
, mkexpr(new_d
), condT
);
7415 putQReg(mreg
, mkexpr(new_m
), condT
);
7417 putDRegI64(dreg
, mkexpr(new_d
), condT
);
7418 putDRegI64(mreg
, mkexpr(new_m
), condT
);
7420 DIP("vzip.%d %c%u, %c%u\n",
7421 8 << size
, Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7423 } else if (B
== 8) {
7428 case 0: op
= Iop_NarrowUn16to8x8
; break;
7429 case 1: op
= Iop_NarrowUn32to16x4
; break;
7430 case 2: op
= Iop_NarrowUn64to32x2
; break;
7431 case 3: return False
;
7432 default: vassert(0);
7434 putDRegI64(dreg
, unop(op
, getQReg(mreg
)), condT
);
7435 DIP("vmovn.i%d d%u, q%u\n", 16 << size
, dreg
, mreg
);
7437 } else if (B
== 9 || (B
>> 1) == 5) {
7438 /* VQMOVN, VQMOVUN */
7441 dreg
= ((theInstr
>> 18) & 0x10) | ((theInstr
>> 12) & 0xF);
7442 mreg
= ((theInstr
>> 1) & 0x10) | (theInstr
& 0xF);
7447 case 0: op2
= Iop_NarrowUn16to8x8
; break;
7448 case 1: op2
= Iop_NarrowUn32to16x4
; break;
7449 case 2: op2
= Iop_NarrowUn64to32x2
; break;
7450 case 3: return False
;
7451 default: vassert(0);
7458 case 0: op
= Iop_QNarrowUn16Sto8Ux8
; break;
7459 case 1: op
= Iop_QNarrowUn32Sto16Ux4
; break;
7460 case 2: op
= Iop_QNarrowUn64Sto32Ux2
; break;
7461 case 3: return False
;
7462 default: vassert(0);
7464 DIP("vqmovun.s%d d%u, q%u\n", 16 << size
, dreg
, mreg
);
7468 case 0: op
= Iop_QNarrowUn16Sto8Sx8
; break;
7469 case 1: op
= Iop_QNarrowUn32Sto16Sx4
; break;
7470 case 2: op
= Iop_QNarrowUn64Sto32Sx2
; break;
7471 case 3: return False
;
7472 default: vassert(0);
7474 DIP("vqmovn.s%d d%u, q%u\n", 16 << size
, dreg
, mreg
);
7478 case 0: op
= Iop_QNarrowUn16Uto8Ux8
; break;
7479 case 1: op
= Iop_QNarrowUn32Uto16Ux4
; break;
7480 case 2: op
= Iop_QNarrowUn64Uto32Ux2
; break;
7481 case 3: return False
;
7482 default: vassert(0);
7484 DIP("vqmovn.u%d d%u, q%u\n", 16 << size
, dreg
, mreg
);
7489 res
= newTemp(Ity_I64
);
7490 tmp
= newTemp(Ity_I64
);
7491 assign(res
, unop(op
, getQReg(mreg
)));
7492 assign(tmp
, unop(op2
, getQReg(mreg
)));
7493 setFlag_QC(mkexpr(res
), mkexpr(tmp
), False
, condT
);
7494 putDRegI64(dreg
, mkexpr(res
), condT
);
7496 } else if (B
== 12) {
7497 /* VSHLL (maximum shift) */
7505 shift_imm
= 8 << size
;
7506 res
= newTemp(Ity_V128
);
7508 case 0: op
= Iop_ShlN16x8
; cvt
= Iop_Widen8Uto16x8
; break;
7509 case 1: op
= Iop_ShlN32x4
; cvt
= Iop_Widen16Uto32x4
; break;
7510 case 2: op
= Iop_ShlN64x2
; cvt
= Iop_Widen32Uto64x2
; break;
7511 case 3: return False
;
7512 default: vassert(0);
7514 assign(res
, binop(op
, unop(cvt
, getDRegI64(mreg
)),
7516 putQReg(dreg
, mkexpr(res
), condT
);
7517 DIP("vshll.i%d q%u, d%u, #%d\n", 8 << size
, dreg
, mreg
, 8 << size
);
7519 } else if ((B
>> 3) == 3 && (B
& 3) == 0) {
7520 /* VCVT (half<->single) */
7521 /* Half-precision extensions are needed to run this */
7523 if (((theInstr
>> 18) & 3) != 1)
7525 if ((theInstr
>> 8) & 1) {
7529 putQReg(dreg
, unop(Iop_F16toF32x4
, getDRegI64(mreg
)),
7531 DIP("vcvt.f32.f16 q%u, d%u\n", dreg
, mreg
);
7536 putDRegI64(dreg
, unop(Iop_F32toF16x4_DEP
, getQReg(mreg
)),
7538 DIP("vcvt.f16.f32 d%u, q%u\n", dreg
, mreg
);
7547 if (((B
>> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,0)) {
7550 F
= (theInstr
>> 8) & 1;
7554 op
= F
? Iop_RecipEst32Fx4
: Iop_RecipEst32Ux4
;
7555 putQReg(dreg
, unop(op
, getQReg(mreg
)), condT
);
7556 DIP("vrecpe.%c32 q%u, q%u\n", F
? 'f' : 'u', dreg
, mreg
);
7558 op
= F
? Iop_RecipEst32Fx2
: Iop_RecipEst32Ux2
;
7559 putDRegI64(dreg
, unop(op
, getDRegI64(mreg
)), condT
);
7560 DIP("vrecpe.%c32 d%u, d%u\n", F
? 'f' : 'u', dreg
, mreg
);
7563 } else if (((B
>> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,1)) {
7571 op
= Q
? Iop_RSqrtEst32Fx4
: Iop_RSqrtEst32Fx2
;
7574 op
= Q
? Iop_RSqrtEst32Ux4
: Iop_RSqrtEst32Ux2
;
7577 putQReg(dreg
, unop(op
, getQReg(mreg
)), condT
);
7578 DIP("vrsqrte.%c32 q%u, q%u\n", F
? 'f' : 'u', dreg
, mreg
);
7580 putDRegI64(dreg
, unop(op
, getDRegI64(mreg
)), condT
);
7581 DIP("vrsqrte.%c32 d%u, d%u\n", F
? 'f' : 'u', dreg
, mreg
);
7584 } else if ((B
>> 3) == 3) {
7585 /* VCVT (fp<->integer) */
7589 switch ((B
>> 1) & 3) {
7591 op
= Q
? Iop_I32StoF32x4_DEP
: Iop_I32StoF32x2_DEP
;
7592 DIP("vcvt.f32.s32 %c%u, %c%u\n",
7593 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7596 op
= Q
? Iop_I32UtoF32x4_DEP
: Iop_I32UtoF32x2_DEP
;
7597 DIP("vcvt.f32.u32 %c%u, %c%u\n",
7598 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7601 op
= Q
? Iop_F32toI32Sx4_RZ
: Iop_F32toI32Sx2_RZ
;
7602 DIP("vcvt.s32.f32 %c%u, %c%u\n",
7603 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7606 op
= Q
? Iop_F32toI32Ux4_RZ
: Iop_F32toI32Ux2_RZ
;
7607 DIP("vcvt.u32.f32 %c%u, %c%u\n",
7608 Q
? 'q' : 'd', dreg
, Q
? 'q' : 'd', mreg
);
7614 putQReg(dreg
, unop(op
, getQReg(mreg
)), condT
);
7616 putDRegI64(dreg
, unop(op
, getDRegI64(mreg
)), condT
);
7630 /* A7.4.6 One register and a modified immediate value */
7632 void ppNeonImm(UInt imm
, UInt cmode
, UInt op
)
7636 case 0: case 1: case 8: case 9:
7637 vex_printf("0x%x", imm
);
7639 case 2: case 3: case 10: case 11:
7640 vex_printf("0x%x00", imm
);
7643 vex_printf("0x%x0000", imm
);
7646 vex_printf("0x%x000000", imm
);
7649 vex_printf("0x%xff", imm
);
7652 vex_printf("0x%xffff", imm
);
7657 for (i
= 7; i
>= 0; i
--)
7658 vex_printf("%s", (imm
& (1 << i
)) ? "ff" : "00");
7660 vex_printf("0x%x", imm
);
7664 vex_printf("0x%x", imm
);
7670 const char *ppNeonImmType(UInt cmode
, UInt op
)
7694 void DIPimm(UInt imm
, UInt cmode
, UInt op
,
7695 const char *instr
, UInt Q
, UInt dreg
)
7697 if (vex_traceflags
& VEX_TRACE_FE
) {
7698 vex_printf("%s.%s %c%u, #", instr
,
7699 ppNeonImmType(cmode
, op
), Q
? 'q' : 'd', dreg
);
7700 ppNeonImm(imm
, cmode
, op
);
7706 Bool
dis_neon_data_1reg_and_imm ( UInt theInstr
, IRTemp condT
)
7708 UInt dreg
= get_neon_d_regno(theInstr
);
7709 ULong imm_raw
= ((theInstr
>> 17) & 0x80) | ((theInstr
>> 12) & 0x70) |
7711 ULong imm_raw_pp
= imm_raw
;
7712 UInt cmode
= (theInstr
>> 8) & 0xf;
7713 UInt op_bit
= (theInstr
>> 5) & 1;
7715 UInt Q
= (theInstr
>> 6) & 1;
7723 imm_raw
= imm_raw
<< 8;
7726 imm_raw
= imm_raw
<< 8;
7729 imm_raw
= imm_raw
<< 8;
7732 imm
= (imm_raw
<< 32) | imm_raw
;
7735 imm_raw
= imm_raw
<< 8;
7738 imm_raw
= (imm_raw
<< 16) | imm_raw
;
7739 imm
= (imm_raw
<< 32) | imm_raw
;
7742 imm_raw
= (imm_raw
<< 8) | 0xff;
7745 imm_raw
= (imm_raw
<< 8) | 0xff;
7746 imm
= (imm_raw
<< 32) | imm_raw
;
7750 for(i
= 0; i
< 8; i
++) {
7751 imm
= (imm
<< 8) | imm_raw
;
7754 for(i
= 7; i
>= 0; i
--) {
7756 for(j
= 0; j
< 8; j
++) {
7757 tmp
= (tmp
<< 1) | ((imm_raw
>> i
) & 1);
7759 imm
= (imm
<< 8) | tmp
;
7764 imm
= (imm_raw
& 0x80) << 5;
7765 imm
|= ((~imm_raw
& 0x40) << 5);
7766 for(i
= 1; i
<= 4; i
++)
7767 imm
|= (imm_raw
& 0x40) << i
;
7768 imm
|= (imm_raw
& 0x7f);
7770 imm
= (imm
<< 32) | imm
;
7776 imm_val
= binop(Iop_64HLtoV128
, mkU64(imm
), mkU64(imm
));
7778 imm_val
= mkU64(imm
);
7780 if (((op_bit
== 0) &&
7781 (((cmode
& 9) == 0) || ((cmode
& 13) == 8) || ((cmode
& 12) == 12))) ||
7782 ((op_bit
== 1) && (cmode
== 14))) {
7783 /* VMOV (immediate) */
7785 putQReg(dreg
, imm_val
, condT
);
7787 putDRegI64(dreg
, imm_val
, condT
);
7789 DIPimm(imm_raw_pp
, cmode
, op_bit
, "vmov", Q
, dreg
);
7792 if ((op_bit
== 1) &&
7793 (((cmode
& 9) == 0) || ((cmode
& 13) == 8) || ((cmode
& 14) == 12))) {
7794 /* VMVN (immediate) */
7796 putQReg(dreg
, unop(Iop_NotV128
, imm_val
), condT
);
7798 putDRegI64(dreg
, unop(Iop_Not64
, imm_val
), condT
);
7800 DIPimm(imm_raw_pp
, cmode
, op_bit
, "vmvn", Q
, dreg
);
7804 tmp_var
= newTemp(Ity_V128
);
7805 assign(tmp_var
, getQReg(dreg
));
7807 tmp_var
= newTemp(Ity_I64
);
7808 assign(tmp_var
, getDRegI64(dreg
));
7810 if ((op_bit
== 0) && (((cmode
& 9) == 1) || ((cmode
& 13) == 9))) {
7811 /* VORR (immediate) */
7813 expr
= binop(Iop_OrV128
, mkexpr(tmp_var
), imm_val
);
7815 expr
= binop(Iop_Or64
, mkexpr(tmp_var
), imm_val
);
7816 DIPimm(imm_raw_pp
, cmode
, op_bit
, "vorr", Q
, dreg
);
7817 } else if ((op_bit
== 1) && (((cmode
& 9) == 1) || ((cmode
& 13) == 9))) {
7818 /* VBIC (immediate) */
7820 expr
= binop(Iop_AndV128
, mkexpr(tmp_var
),
7821 unop(Iop_NotV128
, imm_val
));
7823 expr
= binop(Iop_And64
, mkexpr(tmp_var
), unop(Iop_Not64
, imm_val
));
7824 DIPimm(imm_raw_pp
, cmode
, op_bit
, "vbic", Q
, dreg
);
7829 putQReg(dreg
, expr
, condT
);
7831 putDRegI64(dreg
, expr
, condT
);
7835 /* A7.4 Advanced SIMD data-processing instructions */
7837 Bool
dis_neon_data_processing ( UInt theInstr
, IRTemp condT
)
7839 UInt A
= (theInstr
>> 19) & 0x1F;
7840 UInt B
= (theInstr
>> 8) & 0xF;
7841 UInt C
= (theInstr
>> 4) & 0xF;
7842 UInt U
= (theInstr
>> 24) & 0x1;
7845 return dis_neon_data_3same(theInstr
, condT
);
7847 if (((A
& 0x17) == 0x10) && ((C
& 0x9) == 0x1)) {
7848 return dis_neon_data_1reg_and_imm(theInstr
, condT
);
7851 return dis_neon_data_2reg_and_shift(theInstr
, condT
);
7853 if (((C
& 5) == 0) && (((A
& 0x14) == 0x10) || ((A
& 0x16) == 0x14))) {
7854 return dis_neon_data_3diff(theInstr
, condT
);
7856 if (((C
& 5) == 4) && (((A
& 0x14) == 0x10) || ((A
& 0x16) == 0x14))) {
7857 return dis_neon_data_2reg_and_scalar(theInstr
, condT
);
7859 if ((A
& 0x16) == 0x16) {
7860 if ((U
== 0) && ((C
& 1) == 0)) {
7861 return dis_neon_vext(theInstr
, condT
);
7863 if ((U
!= 1) || ((C
& 1) == 1))
7866 return dis_neon_data_2reg_misc(theInstr
, condT
);
7868 if ((B
& 12) == 8) {
7869 return dis_neon_vtb(theInstr
, condT
);
7871 if ((B
== 12) && ((C
& 9) == 0)) {
7872 return dis_neon_vdup(theInstr
, condT
);
7879 /*------------------------------------------------------------*/
7880 /*--- NEON loads and stores ---*/
7881 /*------------------------------------------------------------*/
7883 /* For NEON memory operations, we use the standard scheme to handle
7884 conditionalisation: generate a jump around the instruction if the
7885 condition is false. That's only necessary in Thumb mode, however,
7886 since in ARM mode NEON instructions are unconditional. */
7888 /* A helper function for what follows. It assumes we already went
7889 uncond as per comments at the top of this section. */
7891 void mk_neon_elem_load_to_one_lane( UInt rD
, UInt inc
, UInt index
,
7892 UInt N
, UInt size
, IRTemp addr
)
7897 putDRegI64(rD
, triop(Iop_SetElem8x8
, getDRegI64(rD
), mkU8(index
),
7898 loadLE(Ity_I8
, mkexpr(addr
))), IRTemp_INVALID
);
7901 putDRegI64(rD
, triop(Iop_SetElem16x4
, getDRegI64(rD
), mkU8(index
),
7902 loadLE(Ity_I16
, mkexpr(addr
))), IRTemp_INVALID
);
7905 putDRegI64(rD
, triop(Iop_SetElem32x2
, getDRegI64(rD
), mkU8(index
),
7906 loadLE(Ity_I32
, mkexpr(addr
))), IRTemp_INVALID
);
7911 for (i
= 1; i
<= N
; i
++) {
7914 putDRegI64(rD
+ i
* inc
,
7915 triop(Iop_SetElem8x8
,
7916 getDRegI64(rD
+ i
* inc
),
7918 loadLE(Ity_I8
, binop(Iop_Add32
,
7924 putDRegI64(rD
+ i
* inc
,
7925 triop(Iop_SetElem16x4
,
7926 getDRegI64(rD
+ i
* inc
),
7928 loadLE(Ity_I16
, binop(Iop_Add32
,
7934 putDRegI64(rD
+ i
* inc
,
7935 triop(Iop_SetElem32x2
,
7936 getDRegI64(rD
+ i
* inc
),
7938 loadLE(Ity_I32
, binop(Iop_Add32
,
7949 /* A(nother) helper function for what follows. It assumes we already
7950 went uncond as per comments at the top of this section. */
7952 void mk_neon_elem_store_from_one_lane( UInt rD
, UInt inc
, UInt index
,
7953 UInt N
, UInt size
, IRTemp addr
)
7958 storeLE(mkexpr(addr
),
7959 binop(Iop_GetElem8x8
, getDRegI64(rD
), mkU8(index
)));
7962 storeLE(mkexpr(addr
),
7963 binop(Iop_GetElem16x4
, getDRegI64(rD
), mkU8(index
)));
7966 storeLE(mkexpr(addr
),
7967 binop(Iop_GetElem32x2
, getDRegI64(rD
), mkU8(index
)));
7972 for (i
= 1; i
<= N
; i
++) {
7975 storeLE(binop(Iop_Add32
, mkexpr(addr
), mkU32(i
* 1)),
7976 binop(Iop_GetElem8x8
, getDRegI64(rD
+ i
* inc
),
7980 storeLE(binop(Iop_Add32
, mkexpr(addr
), mkU32(i
* 2)),
7981 binop(Iop_GetElem16x4
, getDRegI64(rD
+ i
* inc
),
7985 storeLE(binop(Iop_Add32
, mkexpr(addr
), mkU32(i
* 4)),
7986 binop(Iop_GetElem32x2
, getDRegI64(rD
+ i
* inc
),
7995 /* Generate 2x64 -> 2x64 deinterleave code, for VLD2. Caller must
7996 make *u0 and *u1 be valid IRTemps before the call. */
7997 static void math_DEINTERLEAVE_2 (/*OUT*/IRTemp
* u0
, /*OUT*/IRTemp
* u1
,
7998 IRTemp i0
, IRTemp i1
, Int laneszB
)
8000 /* The following assumes that the guest is little endian, and hence
8001 that the memory-side (interleaved) data is stored
8004 /* This is pretty easy, since we have primitives directly to
8007 // memLE(128 bits) == A0 B0 A1 B1
8008 // i0 == B0 A0, i1 == B1 A1
8009 // u0 == A1 A0, u1 == B1 B0
8010 assign(*u0
, binop(Iop_InterleaveLO32x2
, mkexpr(i1
), mkexpr(i0
)));
8011 assign(*u1
, binop(Iop_InterleaveHI32x2
, mkexpr(i1
), mkexpr(i0
)));
8012 } else if (laneszB
== 2) {
8013 // memLE(128 bits) == A0 B0 A1 B1 A2 B2 A3 B3
8014 // i0 == B1 A1 B0 A0, i1 == B3 A3 B2 A2
8015 // u0 == A3 A2 A1 A0, u1 == B3 B2 B1 B0
8016 assign(*u0
, binop(Iop_CatEvenLanes16x4
, mkexpr(i1
), mkexpr(i0
)));
8017 assign(*u1
, binop(Iop_CatOddLanes16x4
, mkexpr(i1
), mkexpr(i0
)));
8018 } else if (laneszB
== 1) {
8019 // memLE(128 bits) == A0 B0 A1 B1 A2 B2 A3 B3 A4 B4 A5 B5 A6 B6 A7 B7
8020 // i0 == B3 A3 B2 A2 B1 A1 B0 A0, i1 == B7 A7 B6 A6 B5 A5 B4 A4
8021 // u0 == A7 A6 A5 A4 A3 A2 A1 A0, u1 == B7 B6 B5 B4 B3 B2 B1 B0
8022 assign(*u0
, binop(Iop_CatEvenLanes8x8
, mkexpr(i1
), mkexpr(i0
)));
8023 assign(*u1
, binop(Iop_CatOddLanes8x8
, mkexpr(i1
), mkexpr(i0
)));
8025 // Can never happen, since VLD2 only has valid lane widths of 32,
8027 vpanic("math_DEINTERLEAVE_2");
8031 /* Generate 2x64 -> 2x64 interleave code, for VST2. Caller must make
8032 *u0 and *u1 be valid IRTemps before the call. */
8033 static void math_INTERLEAVE_2 (/*OUT*/IRTemp
* i0
, /*OUT*/IRTemp
* i1
,
8034 IRTemp u0
, IRTemp u1
, Int laneszB
)
8036 /* The following assumes that the guest is little endian, and hence
8037 that the memory-side (interleaved) data is stored
8040 /* This is pretty easy, since we have primitives directly to
8043 // memLE(128 bits) == A0 B0 A1 B1
8044 // i0 == B0 A0, i1 == B1 A1
8045 // u0 == A1 A0, u1 == B1 B0
8046 assign(*i0
, binop(Iop_InterleaveLO32x2
, mkexpr(u1
), mkexpr(u0
)));
8047 assign(*i1
, binop(Iop_InterleaveHI32x2
, mkexpr(u1
), mkexpr(u0
)));
8048 } else if (laneszB
== 2) {
8049 // memLE(128 bits) == A0 B0 A1 B1 A2 B2 A3 B3
8050 // i0 == B1 A1 B0 A0, i1 == B3 A3 B2 A2
8051 // u0 == A3 A2 A1 A0, u1 == B3 B2 B1 B0
8052 assign(*i0
, binop(Iop_InterleaveLO16x4
, mkexpr(u1
), mkexpr(u0
)));
8053 assign(*i1
, binop(Iop_InterleaveHI16x4
, mkexpr(u1
), mkexpr(u0
)));
8054 } else if (laneszB
== 1) {
8055 // memLE(128 bits) == A0 B0 A1 B1 A2 B2 A3 B3 A4 B4 A5 B5 A6 B6 A7 B7
8056 // i0 == B3 A3 B2 A2 B1 A1 B0 A0, i1 == B7 A7 B6 A6 B5 A5 B4 A4
8057 // u0 == A7 A6 A5 A4 A3 A2 A1 A0, u1 == B7 B6 B5 B4 B3 B2 B1 B0
8058 assign(*i0
, binop(Iop_InterleaveLO8x8
, mkexpr(u1
), mkexpr(u0
)));
8059 assign(*i1
, binop(Iop_InterleaveHI8x8
, mkexpr(u1
), mkexpr(u0
)));
8061 // Can never happen, since VST2 only has valid lane widths of 32,
8063 vpanic("math_INTERLEAVE_2");
8067 // Helper function for generating arbitrary slicing 'n' dicing of
8068 // 3 8x8 vectors, as needed for VLD3.8 and VST3.8.
8069 static IRExpr
* math_PERM_8x8x3(const UChar
* desc
,
8070 IRTemp s0
, IRTemp s1
, IRTemp s2
)
8072 // desc is an array of 8 pairs, encoded as 16 bytes,
8073 // that describe how to assemble the result lanes, starting with
8074 // lane 7. Each pair is: first component (0..2) says which of
8075 // s0/s1/s2 to use. Second component (0..7) is the lane number
8076 // in the source to use.
8078 for (si
= 0; si
< 7; si
++) {
8079 vassert(desc
[2 * si
+ 0] <= 2);
8080 vassert(desc
[2 * si
+ 1] <= 7);
8082 IRTemp h3
= newTemp(Ity_I64
);
8083 IRTemp h2
= newTemp(Ity_I64
);
8084 IRTemp h1
= newTemp(Ity_I64
);
8085 IRTemp h0
= newTemp(Ity_I64
);
8086 IRTemp srcs
[3] = {s0
, s1
, s2
};
8087 # define SRC_VEC(_lane) mkexpr(srcs[desc[2 * (7-(_lane)) + 0]])
8088 # define SRC_SHIFT(_lane) mkU8(56-8*(desc[2 * (7-(_lane)) + 1]))
8089 assign(h3
, binop(Iop_InterleaveHI8x8
,
8090 binop(Iop_Shl64
, SRC_VEC(7), SRC_SHIFT(7)),
8091 binop(Iop_Shl64
, SRC_VEC(6), SRC_SHIFT(6))));
8092 assign(h2
, binop(Iop_InterleaveHI8x8
,
8093 binop(Iop_Shl64
, SRC_VEC(5), SRC_SHIFT(5)),
8094 binop(Iop_Shl64
, SRC_VEC(4), SRC_SHIFT(4))));
8095 assign(h1
, binop(Iop_InterleaveHI8x8
,
8096 binop(Iop_Shl64
, SRC_VEC(3), SRC_SHIFT(3)),
8097 binop(Iop_Shl64
, SRC_VEC(2), SRC_SHIFT(2))));
8098 assign(h0
, binop(Iop_InterleaveHI8x8
,
8099 binop(Iop_Shl64
, SRC_VEC(1), SRC_SHIFT(1)),
8100 binop(Iop_Shl64
, SRC_VEC(0), SRC_SHIFT(0))));
8103 // Now h3..h0 are 64 bit vectors with useful information only
8104 // in the top 16 bits. We now concatentate those four 16-bit
8105 // groups so as to produce the final result.
8106 IRTemp w1
= newTemp(Ity_I64
);
8107 IRTemp w0
= newTemp(Ity_I64
);
8108 assign(w1
, binop(Iop_InterleaveHI16x4
, mkexpr(h3
), mkexpr(h2
)));
8109 assign(w0
, binop(Iop_InterleaveHI16x4
, mkexpr(h1
), mkexpr(h0
)));
8110 return binop(Iop_InterleaveHI32x2
, mkexpr(w1
), mkexpr(w0
));
8113 /* Generate 3x64 -> 3x64 deinterleave code, for VLD3. Caller must
8114 make *u0, *u1 and *u2 be valid IRTemps before the call. */
8115 static void math_DEINTERLEAVE_3 (
8116 /*OUT*/IRTemp
* u0
, /*OUT*/IRTemp
* u1
, /*OUT*/IRTemp
* u2
,
8117 IRTemp i0
, IRTemp i1
, IRTemp i2
, Int laneszB
8120 # define IHI32x2(_e1, _e2) binop(Iop_InterleaveHI32x2, (_e1), (_e2))
8121 # define IHI16x4(_e1, _e2) binop(Iop_InterleaveHI16x4, (_e1), (_e2))
8122 # define SHL64(_tmp, _amt) binop(Iop_Shl64, mkexpr(_tmp), mkU8(_amt))
8123 /* The following assumes that the guest is little endian, and hence
8124 that the memory-side (interleaved) data is stored
8126 vassert(u0
&& u1
&& u2
);
8128 // memLE(192 bits) == A0 B0 C0 A1 B1 C1
8129 // i0 == B0 A0, i1 == A1 C0, i2 == C1 B1
8130 // u0 == A1 A0, u1 == B1 B0, u2 == C1 C0
8131 assign(*u0
, IHI32x2(SHL64(i1
, 0), SHL64(i0
, 32)));
8132 assign(*u1
, IHI32x2(SHL64(i2
, 32), SHL64(i0
, 0)));
8133 assign(*u2
, IHI32x2(SHL64(i2
, 0), SHL64(i1
, 32)));
8134 } else if (laneszB
== 2) {
8135 // memLE(192 bits) == A0 B0 C0 A1, B1 C1 A2 B2, C2 A3 B3 C3
8136 // i0 == A1 C0 B0 A0, i1 == B2 A2 C1 B1, i2 == C3 B3 A3 C2
8137 // u0 == A3 A2 A1 A0, u1 == B3 B2 B1 B0, u2 == C3 C2 C1 C0
8138 # define XXX(_tmp3,_la3,_tmp2,_la2,_tmp1,_la1,_tmp0,_la0) \
8140 IHI16x4(SHL64((_tmp3),48-16*(_la3)), \
8141 SHL64((_tmp2),48-16*(_la2))), \
8142 IHI16x4(SHL64((_tmp1),48-16*(_la1)), \
8143 SHL64((_tmp0),48-16*(_la0))))
8144 assign(*u0
, XXX(i2
,1, i1
,2, i0
,3, i0
,0));
8145 assign(*u1
, XXX(i2
,2, i1
,3, i1
,0, i0
,1));
8146 assign(*u2
, XXX(i2
,3, i2
,0, i1
,1, i0
,2));
8148 } else if (laneszB
== 1) {
8149 // These describe how the result vectors [7..0] are
8150 // assembled from the source vectors. Each pair is
8151 // (source vector number, lane number).
8152 static const UChar de0
[16] = {2,5, 2,2, 1,7, 1,4, 1,1, 0,6, 0,3, 0,0};
8153 static const UChar de1
[16] = {2,6, 2,3, 2,0, 1,5, 1,2, 0,7, 0,4, 0,1};
8154 static const UChar de2
[16] = {2,7, 2,4, 2,1, 1,6, 1,3, 1,0, 0,5, 0,2};
8155 assign(*u0
, math_PERM_8x8x3(de0
, i0
, i1
, i2
));
8156 assign(*u1
, math_PERM_8x8x3(de1
, i0
, i1
, i2
));
8157 assign(*u2
, math_PERM_8x8x3(de2
, i0
, i1
, i2
));
8159 // Can never happen, since VLD3 only has valid lane widths of 32,
8161 vpanic("math_DEINTERLEAVE_3");
8168 /* Generate 3x64 -> 3x64 interleave code, for VST3. Caller must
8169 make *i0, *i1 and *i2 be valid IRTemps before the call. */
8170 static void math_INTERLEAVE_3 (
8171 /*OUT*/IRTemp
* i0
, /*OUT*/IRTemp
* i1
, /*OUT*/IRTemp
* i2
,
8172 IRTemp u0
, IRTemp u1
, IRTemp u2
, Int laneszB
8175 # define IHI32x2(_e1, _e2) binop(Iop_InterleaveHI32x2, (_e1), (_e2))
8176 # define IHI16x4(_e1, _e2) binop(Iop_InterleaveHI16x4, (_e1), (_e2))
8177 # define SHL64(_tmp, _amt) binop(Iop_Shl64, mkexpr(_tmp), mkU8(_amt))
8178 /* The following assumes that the guest is little endian, and hence
8179 that the memory-side (interleaved) data is stored
8181 vassert(i0
&& i1
&& i2
);
8183 // memLE(192 bits) == A0 B0 C0 A1 B1 C1
8184 // i0 == B0 A0, i1 == A1 C0, i2 == C1 B1
8185 // u0 == A1 A0, u1 == B1 B0, u2 == C1 C0
8186 assign(*i0
, IHI32x2(SHL64(u1
, 32), SHL64(u0
, 32)));
8187 assign(*i1
, IHI32x2(SHL64(u0
, 0), SHL64(u2
, 32)));
8188 assign(*i2
, IHI32x2(SHL64(u2
, 0), SHL64(u1
, 0)));
8189 } else if (laneszB
== 2) {
8190 // memLE(192 bits) == A0 B0 C0 A1, B1 C1 A2 B2, C2 A3 B3 C3
8191 // i0 == A1 C0 B0 A0, i1 == B2 A2 C1 B1, i2 == C3 B3 A3 C2
8192 // u0 == A3 A2 A1 A0, u1 == B3 B2 B1 B0, u2 == C3 C2 C1 C0
8193 # define XXX(_tmp3,_la3,_tmp2,_la2,_tmp1,_la1,_tmp0,_la0) \
8195 IHI16x4(SHL64((_tmp3),48-16*(_la3)), \
8196 SHL64((_tmp2),48-16*(_la2))), \
8197 IHI16x4(SHL64((_tmp1),48-16*(_la1)), \
8198 SHL64((_tmp0),48-16*(_la0))))
8199 assign(*i0
, XXX(u0
,1, u2
,0, u1
,0, u0
,0));
8200 assign(*i1
, XXX(u1
,2, u0
,2, u2
,1, u1
,1));
8201 assign(*i2
, XXX(u2
,3, u1
,3, u0
,3, u2
,2));
8203 } else if (laneszB
== 1) {
8204 // These describe how the result vectors [7..0] are
8205 // assembled from the source vectors. Each pair is
8206 // (source vector number, lane number).
8207 static const UChar in0
[16] = {1,2, 0,2, 2,1, 1,1, 0,1, 2,0, 1,0, 0,0};
8208 static const UChar in1
[16] = {0,5, 2,4, 1,4, 0,4, 2,3, 1,3, 0,3, 2,2};
8209 static const UChar in2
[16] = {2,7, 1,7, 0,7, 2,6, 1,6, 0,6, 2,5, 1,5};
8210 assign(*i0
, math_PERM_8x8x3(in0
, u0
, u1
, u2
));
8211 assign(*i1
, math_PERM_8x8x3(in1
, u0
, u1
, u2
));
8212 assign(*i2
, math_PERM_8x8x3(in2
, u0
, u1
, u2
));
8214 // Can never happen, since VST3 only has valid lane widths of 32,
8216 vpanic("math_INTERLEAVE_3");
8223 /* Generate 4x64 -> 4x64 deinterleave code, for VLD4. Caller must
8224 make *u0, *u1, *u2 and *u3 be valid IRTemps before the call. */
8225 static void math_DEINTERLEAVE_4 (
8226 /*OUT*/IRTemp
* u0
, /*OUT*/IRTemp
* u1
,
8227 /*OUT*/IRTemp
* u2
, /*OUT*/IRTemp
* u3
,
8228 IRTemp i0
, IRTemp i1
, IRTemp i2
, IRTemp i3
, Int laneszB
8231 # define IHI32x2(_t1, _t2) \
8232 binop(Iop_InterleaveHI32x2, mkexpr(_t1), mkexpr(_t2))
8233 # define ILO32x2(_t1, _t2) \
8234 binop(Iop_InterleaveLO32x2, mkexpr(_t1), mkexpr(_t2))
8235 # define IHI16x4(_t1, _t2) \
8236 binop(Iop_InterleaveHI16x4, mkexpr(_t1), mkexpr(_t2))
8237 # define ILO16x4(_t1, _t2) \
8238 binop(Iop_InterleaveLO16x4, mkexpr(_t1), mkexpr(_t2))
8239 # define IHI8x8(_t1, _e2) \
8240 binop(Iop_InterleaveHI8x8, mkexpr(_t1), _e2)
8241 # define SHL64(_tmp, _amt) \
8242 binop(Iop_Shl64, mkexpr(_tmp), mkU8(_amt))
8243 /* The following assumes that the guest is little endian, and hence
8244 that the memory-side (interleaved) data is stored
8246 vassert(u0
&& u1
&& u2
&& u3
);
8248 assign(*u0
, ILO32x2(i2
, i0
));
8249 assign(*u1
, IHI32x2(i2
, i0
));
8250 assign(*u2
, ILO32x2(i3
, i1
));
8251 assign(*u3
, IHI32x2(i3
, i1
));
8252 } else if (laneszB
== 2) {
8253 IRTemp b1b0a1a0
= newTemp(Ity_I64
);
8254 IRTemp b3b2a3a2
= newTemp(Ity_I64
);
8255 IRTemp d1d0c1c0
= newTemp(Ity_I64
);
8256 IRTemp d3d2c3c2
= newTemp(Ity_I64
);
8257 assign(b1b0a1a0
, ILO16x4(i1
, i0
));
8258 assign(b3b2a3a2
, ILO16x4(i3
, i2
));
8259 assign(d1d0c1c0
, IHI16x4(i1
, i0
));
8260 assign(d3d2c3c2
, IHI16x4(i3
, i2
));
8261 // And now do what we did for the 32-bit case.
8262 assign(*u0
, ILO32x2(b3b2a3a2
, b1b0a1a0
));
8263 assign(*u1
, IHI32x2(b3b2a3a2
, b1b0a1a0
));
8264 assign(*u2
, ILO32x2(d3d2c3c2
, d1d0c1c0
));
8265 assign(*u3
, IHI32x2(d3d2c3c2
, d1d0c1c0
));
8266 } else if (laneszB
== 1) {
8267 // Deinterleave into 16-bit chunks, then do as the 16-bit case.
8268 IRTemp i0x
= newTemp(Ity_I64
);
8269 IRTemp i1x
= newTemp(Ity_I64
);
8270 IRTemp i2x
= newTemp(Ity_I64
);
8271 IRTemp i3x
= newTemp(Ity_I64
);
8272 assign(i0x
, IHI8x8(i0
, SHL64(i0
, 32)));
8273 assign(i1x
, IHI8x8(i1
, SHL64(i1
, 32)));
8274 assign(i2x
, IHI8x8(i2
, SHL64(i2
, 32)));
8275 assign(i3x
, IHI8x8(i3
, SHL64(i3
, 32)));
8276 // From here on is like the 16 bit case.
8277 IRTemp b1b0a1a0
= newTemp(Ity_I64
);
8278 IRTemp b3b2a3a2
= newTemp(Ity_I64
);
8279 IRTemp d1d0c1c0
= newTemp(Ity_I64
);
8280 IRTemp d3d2c3c2
= newTemp(Ity_I64
);
8281 assign(b1b0a1a0
, ILO16x4(i1x
, i0x
));
8282 assign(b3b2a3a2
, ILO16x4(i3x
, i2x
));
8283 assign(d1d0c1c0
, IHI16x4(i1x
, i0x
));
8284 assign(d3d2c3c2
, IHI16x4(i3x
, i2x
));
8285 // And now do what we did for the 32-bit case.
8286 assign(*u0
, ILO32x2(b3b2a3a2
, b1b0a1a0
));
8287 assign(*u1
, IHI32x2(b3b2a3a2
, b1b0a1a0
));
8288 assign(*u2
, ILO32x2(d3d2c3c2
, d1d0c1c0
));
8289 assign(*u3
, IHI32x2(d3d2c3c2
, d1d0c1c0
));
8291 // Can never happen, since VLD4 only has valid lane widths of 32,
8293 vpanic("math_DEINTERLEAVE_4");
8303 /* Generate 4x64 -> 4x64 interleave code, for VST4. Caller must
8304 make *i0, *i1, *i2 and *i3 be valid IRTemps before the call. */
8305 static void math_INTERLEAVE_4 (
8306 /*OUT*/IRTemp
* i0
, /*OUT*/IRTemp
* i1
,
8307 /*OUT*/IRTemp
* i2
, /*OUT*/IRTemp
* i3
,
8308 IRTemp u0
, IRTemp u1
, IRTemp u2
, IRTemp u3
, Int laneszB
8311 # define IHI32x2(_t1, _t2) \
8312 binop(Iop_InterleaveHI32x2, mkexpr(_t1), mkexpr(_t2))
8313 # define ILO32x2(_t1, _t2) \
8314 binop(Iop_InterleaveLO32x2, mkexpr(_t1), mkexpr(_t2))
8315 # define CEV16x4(_t1, _t2) \
8316 binop(Iop_CatEvenLanes16x4, mkexpr(_t1), mkexpr(_t2))
8317 # define COD16x4(_t1, _t2) \
8318 binop(Iop_CatOddLanes16x4, mkexpr(_t1), mkexpr(_t2))
8319 # define COD8x8(_t1, _e2) \
8320 binop(Iop_CatOddLanes8x8, mkexpr(_t1), _e2)
8321 # define SHL64(_tmp, _amt) \
8322 binop(Iop_Shl64, mkexpr(_tmp), mkU8(_amt))
8323 /* The following assumes that the guest is little endian, and hence
8324 that the memory-side (interleaved) data is stored
8326 vassert(u0
&& u1
&& u2
&& u3
);
8328 assign(*i0
, ILO32x2(u1
, u0
));
8329 assign(*i1
, ILO32x2(u3
, u2
));
8330 assign(*i2
, IHI32x2(u1
, u0
));
8331 assign(*i3
, IHI32x2(u3
, u2
));
8332 } else if (laneszB
== 2) {
8333 // First, interleave at the 32-bit lane size.
8334 IRTemp b1b0a1a0
= newTemp(Ity_I64
);
8335 IRTemp b3b2a3a2
= newTemp(Ity_I64
);
8336 IRTemp d1d0c1c0
= newTemp(Ity_I64
);
8337 IRTemp d3d2c3c2
= newTemp(Ity_I64
);
8338 assign(b1b0a1a0
, ILO32x2(u1
, u0
));
8339 assign(b3b2a3a2
, IHI32x2(u1
, u0
));
8340 assign(d1d0c1c0
, ILO32x2(u3
, u2
));
8341 assign(d3d2c3c2
, IHI32x2(u3
, u2
));
8342 // And interleave (cat) at the 16 bit size.
8343 assign(*i0
, CEV16x4(d1d0c1c0
, b1b0a1a0
));
8344 assign(*i1
, COD16x4(d1d0c1c0
, b1b0a1a0
));
8345 assign(*i2
, CEV16x4(d3d2c3c2
, b3b2a3a2
));
8346 assign(*i3
, COD16x4(d3d2c3c2
, b3b2a3a2
));
8347 } else if (laneszB
== 1) {
8348 // First, interleave at the 32-bit lane size.
8349 IRTemp b1b0a1a0
= newTemp(Ity_I64
);
8350 IRTemp b3b2a3a2
= newTemp(Ity_I64
);
8351 IRTemp d1d0c1c0
= newTemp(Ity_I64
);
8352 IRTemp d3d2c3c2
= newTemp(Ity_I64
);
8353 assign(b1b0a1a0
, ILO32x2(u1
, u0
));
8354 assign(b3b2a3a2
, IHI32x2(u1
, u0
));
8355 assign(d1d0c1c0
, ILO32x2(u3
, u2
));
8356 assign(d3d2c3c2
, IHI32x2(u3
, u2
));
8357 // And interleave (cat) at the 16 bit size.
8358 IRTemp i0x
= newTemp(Ity_I64
);
8359 IRTemp i1x
= newTemp(Ity_I64
);
8360 IRTemp i2x
= newTemp(Ity_I64
);
8361 IRTemp i3x
= newTemp(Ity_I64
);
8362 assign(i0x
, CEV16x4(d1d0c1c0
, b1b0a1a0
));
8363 assign(i1x
, COD16x4(d1d0c1c0
, b1b0a1a0
));
8364 assign(i2x
, CEV16x4(d3d2c3c2
, b3b2a3a2
));
8365 assign(i3x
, COD16x4(d3d2c3c2
, b3b2a3a2
));
8366 // And rearrange within each word, to get the right 8 bit lanes.
8367 assign(*i0
, COD8x8(i0x
, SHL64(i0x
, 8)));
8368 assign(*i1
, COD8x8(i1x
, SHL64(i1x
, 8)));
8369 assign(*i2
, COD8x8(i2x
, SHL64(i2x
, 8)));
8370 assign(*i3
, COD8x8(i3x
, SHL64(i3x
, 8)));
8372 // Can never happen, since VLD4 only has valid lane widths of 32,
8374 vpanic("math_DEINTERLEAVE_4");
8384 /* A7.7 Advanced SIMD element or structure load/store instructions */
8386 Bool
dis_neon_load_or_store ( UInt theInstr
,
8387 Bool isT
, IRTemp condT
)
8389 # define INSN(_bMax,_bMin) SLICE_UInt(theInstr, (_bMax), (_bMin))
8390 UInt bA
= INSN(23,23);
8391 UInt fB
= INSN(11,8);
8392 UInt bL
= INSN(21,21);
8393 UInt rD
= (INSN(22,22) << 4) | INSN(15,12);
8394 UInt rN
= INSN(19,16);
8395 UInt rM
= INSN(3,0);
8401 vassert(condT
!= IRTemp_INVALID
);
8403 vassert(condT
== IRTemp_INVALID
);
8405 /* So now, if condT is not IRTemp_INVALID, we know we're
8406 dealing with Thumb code. */
8408 if (INSN(20,20) != 0)
8411 IRTemp initialRn
= newTemp(Ity_I32
);
8412 assign(initialRn
, isT
? getIRegT(rN
) : getIRegA(rN
));
8414 IRTemp initialRm
= newTemp(Ity_I32
);
8415 assign(initialRm
, isT
? getIRegT(rM
) : getIRegA(rM
));
8417 /* There are 3 cases:
8418 (1) VSTn / VLDn (n-element structure from/to one lane)
8419 (2) VLDn (single element to all lanes)
8420 (3) VSTn / VLDn (multiple n-element structures)
8424 if ((fB
>> 2) < 3) {
8425 /* ------------ Case (1) ------------
8426 VSTn / VLDn (n-element structure from/to one lane) */
8431 case 0: i
= INSN(7,5); inc
= 1; break;
8432 case 1: i
= INSN(7,6); inc
= INSN(5,5) ? 2 : 1; break;
8433 case 2: i
= INSN(7,7); inc
= INSN(6,6) ? 2 : 1; break;
8434 case 3: return False
;
8435 default: vassert(0);
8438 IRTemp addr
= newTemp(Ity_I32
);
8439 assign(addr
, mkexpr(initialRn
));
8442 if (condT
!= IRTemp_INVALID
)
8443 mk_skip_over_T32_if_cond_is_false(condT
);
8447 mk_neon_elem_load_to_one_lane(rD
, inc
, i
, N
, size
, addr
);
8449 mk_neon_elem_store_from_one_lane(rD
, inc
, i
, N
, size
, addr
);
8450 DIP("v%s%u.%d {", bL
? "ld" : "st", N
+ 1, 8 << size
);
8451 for (j
= 0; j
<= N
; j
++) {
8454 DIP("d%u[%u]", rD
+ j
* inc
, i
);
8456 DIP("}, [r%u]", rN
);
8457 if (rM
!= 13 && rM
!= 15) {
8460 DIP("%s\n", (rM
!= 15) ? "!" : "");
8463 /* ------------ Case (2) ------------
8464 VLDn (single element to all lanes) */
8469 inc
= INSN(5,5) + 1;
8472 /* size == 3 and size == 2 cases differ in alignment constraints */
8473 if (size
== 3 && N
== 3 && INSN(4,4) == 1)
8476 if (size
== 0 && N
== 0 && INSN(4,4) == 1)
8478 if (N
== 2 && INSN(4,4) == 1)
8484 if (condT
!= IRTemp_INVALID
)
8485 mk_skip_over_T32_if_cond_is_false(condT
);
8488 IRTemp addr
= newTemp(Ity_I32
);
8489 assign(addr
, mkexpr(initialRn
));
8491 if (N
== 0 && INSN(5,5))
8494 for (r
= 0; r
< regs
; r
++) {
8497 putDRegI64(rD
+ r
, unop(Iop_Dup8x8
,
8498 loadLE(Ity_I8
, mkexpr(addr
))),
8502 putDRegI64(rD
+ r
, unop(Iop_Dup16x4
,
8503 loadLE(Ity_I16
, mkexpr(addr
))),
8507 putDRegI64(rD
+ r
, unop(Iop_Dup32x2
,
8508 loadLE(Ity_I32
, mkexpr(addr
))),
8514 for (i
= 1; i
<= N
; i
++) {
8517 putDRegI64(rD
+ r
+ i
* inc
,
8519 loadLE(Ity_I8
, binop(Iop_Add32
,
8525 putDRegI64(rD
+ r
+ i
* inc
,
8527 loadLE(Ity_I16
, binop(Iop_Add32
,
8533 putDRegI64(rD
+ r
+ i
* inc
,
8535 loadLE(Ity_I32
, binop(Iop_Add32
,
8545 DIP("vld%u.%d {", N
+ 1, 8 << size
);
8546 for (r
= 0; r
< regs
; r
++) {
8547 for (i
= 0; i
<= N
; i
++) {
8550 DIP("d%u[]", rD
+ r
+ i
* inc
);
8553 DIP("}, [r%u]", rN
);
8554 if (rM
!= 13 && rM
!= 15) {
8557 DIP("%s\n", (rM
!= 15) ? "!" : "");
8560 /* Writeback. We're uncond here, so no condT-ing. */
8563 IRExpr
* e
= binop(Iop_Add32
,
8565 mkU32((1 << size
) * (N
+ 1)));
8567 putIRegT(rN
, e
, IRTemp_INVALID
);
8569 putIRegA(rN
, e
, IRTemp_INVALID
, Ijk_Boring
);
8571 IRExpr
* e
= binop(Iop_Add32
,
8575 putIRegT(rN
, e
, IRTemp_INVALID
);
8577 putIRegA(rN
, e
, IRTemp_INVALID
, Ijk_Boring
);
8582 /* ------------ Case (3) ------------
8583 VSTn / VLDn (multiple n-element structures) */
8586 if (fB
== BITS4(0,0,1,0) // Dd, Dd+1, Dd+2, Dd+3 inc = 1 regs = 4
8587 || fB
== BITS4(0,1,1,0) // Dd, Dd+1, Dd+2 inc = 1 regs = 3
8588 || fB
== BITS4(0,1,1,1) // Dd inc = 2 regs = 1
8589 || fB
== BITS4(1,0,1,0)) { // Dd, Dd+1 inc = 1 regs = 2
8590 N
= 0; // VLD1/VST1. 'inc' does not appear to have any
8591 // meaning for the VLD1/VST1 cases. 'regs' is the number of
8592 // registers involved.
8593 if (rD
+ regs
> 32) return False
;
8596 if (fB
== BITS4(0,0,1,1) // Dd, Dd+1, Dd+2, Dd+3 inc=2 regs = 2
8597 || fB
== BITS4(1,0,0,0) // Dd, Dd+1 inc=1 regs = 1
8598 || fB
== BITS4(1,0,0,1)) { // Dd, Dd+2 inc=2 regs = 1
8599 N
= 1; // VLD2/VST2. 'regs' is the number of register-pairs involved
8600 if (regs
== 1 && inc
== 1 && rD
+ 1 >= 32) return False
;
8601 if (regs
== 1 && inc
== 2 && rD
+ 2 >= 32) return False
;
8602 if (regs
== 2 && inc
== 2 && rD
+ 3 >= 32) return False
;
8603 } else if (fB
== BITS4(0,1,0,0) || fB
== BITS4(0,1,0,1)) {
8605 if (inc
== 1 && rD
+ 2 >= 32) return False
;
8606 if (inc
== 2 && rD
+ 4 >= 32) return False
;
8607 } else if (fB
== BITS4(0,0,0,0) || fB
== BITS4(0,0,0,1)) {
8609 if (inc
== 1 && rD
+ 3 >= 32) return False
;
8610 if (inc
== 2 && rD
+ 6 >= 32) return False
;
8615 if (N
== 1 && fB
== BITS4(0,0,1,1)) {
8617 } else if (N
== 0) {
8618 if (fB
== BITS4(1,0,1,0)) {
8620 } else if (fB
== BITS4(0,1,1,0)) {
8622 } else if (fB
== BITS4(0,0,1,0)) {
8628 if (N
== 0 && size
== 3)
8634 if (condT
!= IRTemp_INVALID
)
8635 mk_skip_over_T32_if_cond_is_false(condT
);
8638 IRTemp addr
= newTemp(Ity_I32
);
8639 assign(addr
, mkexpr(initialRn
));
8641 if (N
== 0 /* No interleaving -- VLD1/VST1 */) {
8643 vassert(regs
== 1 || regs
== 2 || regs
== 3 || regs
== 4);
8644 /* inc has no relevance here */
8645 for (r
= 0; r
< regs
; r
++) {
8647 putDRegI64(rD
+r
, loadLE(Ity_I64
, mkexpr(addr
)), IRTemp_INVALID
);
8649 storeLE(mkexpr(addr
), getDRegI64(rD
+r
));
8650 IRTemp tmp
= newTemp(Ity_I32
);
8651 assign(tmp
, binop(Iop_Add32
, mkexpr(addr
), mkU32(8)));
8656 if (N
== 1 /* 2-interleaving -- VLD2/VST2 */) {
8657 vassert( (regs
== 1 && (inc
== 1 || inc
== 2))
8658 || (regs
== 2 && inc
== 2) );
8659 // Make 'nregs' be the number of registers and 'regstep'
8660 // equal the actual register-step. The ARM encoding, using 'regs'
8661 // and 'inc', is bizarre. After this, we have:
8662 // Dd, Dd+1 regs = 1, inc = 1, nregs = 2, regstep = 1
8663 // Dd, Dd+2 regs = 1, inc = 2, nregs = 2, regstep = 2
8664 // Dd, Dd+1, Dd+2, Dd+3 regs = 2, inc = 2, nregs = 4, regstep = 1
8667 if (regs
== 1 && inc
== 1) {
8669 } else if (regs
== 1 && inc
== 2) {
8671 } else if (regs
== 2 && inc
== 2) {
8677 // 'di' is interleaved data, 'du' is uninterleaved data
8679 IRExpr
* a0
= binop(Iop_Add32
, mkexpr(addr
), mkU32(0));
8680 IRExpr
* a1
= binop(Iop_Add32
, mkexpr(addr
), mkU32(8));
8681 IRTemp di0
= newTemp(Ity_I64
);
8682 IRTemp di1
= newTemp(Ity_I64
);
8683 IRTemp du0
= newTemp(Ity_I64
);
8684 IRTemp du1
= newTemp(Ity_I64
);
8686 assign(di0
, loadLE(Ity_I64
, a0
));
8687 assign(di1
, loadLE(Ity_I64
, a1
));
8688 math_DEINTERLEAVE_2(&du0
, &du1
, di0
, di1
, 1 << size
);
8689 putDRegI64(rD
+ 0 * regstep
, mkexpr(du0
), IRTemp_INVALID
);
8690 putDRegI64(rD
+ 1 * regstep
, mkexpr(du1
), IRTemp_INVALID
);
8692 assign(du0
, getDRegI64(rD
+ 0 * regstep
));
8693 assign(du1
, getDRegI64(rD
+ 1 * regstep
));
8694 math_INTERLEAVE_2(&di0
, &di1
, du0
, du1
, 1 << size
);
8695 storeLE(a0
, mkexpr(di0
));
8696 storeLE(a1
, mkexpr(di1
));
8698 IRTemp tmp
= newTemp(Ity_I32
);
8699 assign(tmp
, binop(Iop_Add32
, mkexpr(addr
), mkU32(16)));
8702 vassert(nregs
== 4);
8703 vassert(regstep
== 1);
8704 IRExpr
* a0
= binop(Iop_Add32
, mkexpr(addr
), mkU32(0));
8705 IRExpr
* a1
= binop(Iop_Add32
, mkexpr(addr
), mkU32(8));
8706 IRExpr
* a2
= binop(Iop_Add32
, mkexpr(addr
), mkU32(16));
8707 IRExpr
* a3
= binop(Iop_Add32
, mkexpr(addr
), mkU32(24));
8708 IRTemp di0
= newTemp(Ity_I64
);
8709 IRTemp di1
= newTemp(Ity_I64
);
8710 IRTemp di2
= newTemp(Ity_I64
);
8711 IRTemp di3
= newTemp(Ity_I64
);
8712 IRTemp du0
= newTemp(Ity_I64
);
8713 IRTemp du1
= newTemp(Ity_I64
);
8714 IRTemp du2
= newTemp(Ity_I64
);
8715 IRTemp du3
= newTemp(Ity_I64
);
8717 assign(di0
, loadLE(Ity_I64
, a0
));
8718 assign(di1
, loadLE(Ity_I64
, a1
));
8719 assign(di2
, loadLE(Ity_I64
, a2
));
8720 assign(di3
, loadLE(Ity_I64
, a3
));
8721 // Note spooky interleaving: du0, du2, di0, di1 etc
8722 math_DEINTERLEAVE_2(&du0
, &du2
, di0
, di1
, 1 << size
);
8723 math_DEINTERLEAVE_2(&du1
, &du3
, di2
, di3
, 1 << size
);
8724 putDRegI64(rD
+ 0 * regstep
, mkexpr(du0
), IRTemp_INVALID
);
8725 putDRegI64(rD
+ 1 * regstep
, mkexpr(du1
), IRTemp_INVALID
);
8726 putDRegI64(rD
+ 2 * regstep
, mkexpr(du2
), IRTemp_INVALID
);
8727 putDRegI64(rD
+ 3 * regstep
, mkexpr(du3
), IRTemp_INVALID
);
8729 assign(du0
, getDRegI64(rD
+ 0 * regstep
));
8730 assign(du1
, getDRegI64(rD
+ 1 * regstep
));
8731 assign(du2
, getDRegI64(rD
+ 2 * regstep
));
8732 assign(du3
, getDRegI64(rD
+ 3 * regstep
));
8733 // Note spooky interleaving: du0, du2, di0, di1 etc
8734 math_INTERLEAVE_2(&di0
, &di1
, du0
, du2
, 1 << size
);
8735 math_INTERLEAVE_2(&di2
, &di3
, du1
, du3
, 1 << size
);
8736 storeLE(a0
, mkexpr(di0
));
8737 storeLE(a1
, mkexpr(di1
));
8738 storeLE(a2
, mkexpr(di2
));
8739 storeLE(a3
, mkexpr(di3
));
8742 IRTemp tmp
= newTemp(Ity_I32
);
8743 assign(tmp
, binop(Iop_Add32
, mkexpr(addr
), mkU32(32)));
8748 if (N
== 2 /* 3-interleaving -- VLD3/VST3 */) {
8749 // Dd, Dd+1, Dd+2 regs = 1, inc = 1
8750 // Dd, Dd+2, Dd+4 regs = 1, inc = 2
8751 vassert(regs
== 1 && (inc
== 1 || inc
== 2));
8752 IRExpr
* a0
= binop(Iop_Add32
, mkexpr(addr
), mkU32(0));
8753 IRExpr
* a1
= binop(Iop_Add32
, mkexpr(addr
), mkU32(8));
8754 IRExpr
* a2
= binop(Iop_Add32
, mkexpr(addr
), mkU32(16));
8755 IRTemp di0
= newTemp(Ity_I64
);
8756 IRTemp di1
= newTemp(Ity_I64
);
8757 IRTemp di2
= newTemp(Ity_I64
);
8758 IRTemp du0
= newTemp(Ity_I64
);
8759 IRTemp du1
= newTemp(Ity_I64
);
8760 IRTemp du2
= newTemp(Ity_I64
);
8762 assign(di0
, loadLE(Ity_I64
, a0
));
8763 assign(di1
, loadLE(Ity_I64
, a1
));
8764 assign(di2
, loadLE(Ity_I64
, a2
));
8765 math_DEINTERLEAVE_3(&du0
, &du1
, &du2
, di0
, di1
, di2
, 1 << size
);
8766 putDRegI64(rD
+ 0 * inc
, mkexpr(du0
), IRTemp_INVALID
);
8767 putDRegI64(rD
+ 1 * inc
, mkexpr(du1
), IRTemp_INVALID
);
8768 putDRegI64(rD
+ 2 * inc
, mkexpr(du2
), IRTemp_INVALID
);
8770 assign(du0
, getDRegI64(rD
+ 0 * inc
));
8771 assign(du1
, getDRegI64(rD
+ 1 * inc
));
8772 assign(du2
, getDRegI64(rD
+ 2 * inc
));
8773 math_INTERLEAVE_3(&di0
, &di1
, &di2
, du0
, du1
, du2
, 1 << size
);
8774 storeLE(a0
, mkexpr(di0
));
8775 storeLE(a1
, mkexpr(di1
));
8776 storeLE(a2
, mkexpr(di2
));
8778 IRTemp tmp
= newTemp(Ity_I32
);
8779 assign(tmp
, binop(Iop_Add32
, mkexpr(addr
), mkU32(24)));
8783 if (N
== 3 /* 4-interleaving -- VLD4/VST4 */) {
8784 // Dd, Dd+1, Dd+2, Dd+3 regs = 1, inc = 1
8785 // Dd, Dd+2, Dd+4, Dd+6 regs = 1, inc = 2
8786 vassert(regs
== 1 && (inc
== 1 || inc
== 2));
8787 IRExpr
* a0
= binop(Iop_Add32
, mkexpr(addr
), mkU32(0));
8788 IRExpr
* a1
= binop(Iop_Add32
, mkexpr(addr
), mkU32(8));
8789 IRExpr
* a2
= binop(Iop_Add32
, mkexpr(addr
), mkU32(16));
8790 IRExpr
* a3
= binop(Iop_Add32
, mkexpr(addr
), mkU32(24));
8791 IRTemp di0
= newTemp(Ity_I64
);
8792 IRTemp di1
= newTemp(Ity_I64
);
8793 IRTemp di2
= newTemp(Ity_I64
);
8794 IRTemp di3
= newTemp(Ity_I64
);
8795 IRTemp du0
= newTemp(Ity_I64
);
8796 IRTemp du1
= newTemp(Ity_I64
);
8797 IRTemp du2
= newTemp(Ity_I64
);
8798 IRTemp du3
= newTemp(Ity_I64
);
8800 assign(di0
, loadLE(Ity_I64
, a0
));
8801 assign(di1
, loadLE(Ity_I64
, a1
));
8802 assign(di2
, loadLE(Ity_I64
, a2
));
8803 assign(di3
, loadLE(Ity_I64
, a3
));
8804 math_DEINTERLEAVE_4(&du0
, &du1
, &du2
, &du3
,
8805 di0
, di1
, di2
, di3
, 1 << size
);
8806 putDRegI64(rD
+ 0 * inc
, mkexpr(du0
), IRTemp_INVALID
);
8807 putDRegI64(rD
+ 1 * inc
, mkexpr(du1
), IRTemp_INVALID
);
8808 putDRegI64(rD
+ 2 * inc
, mkexpr(du2
), IRTemp_INVALID
);
8809 putDRegI64(rD
+ 3 * inc
, mkexpr(du3
), IRTemp_INVALID
);
8811 assign(du0
, getDRegI64(rD
+ 0 * inc
));
8812 assign(du1
, getDRegI64(rD
+ 1 * inc
));
8813 assign(du2
, getDRegI64(rD
+ 2 * inc
));
8814 assign(du3
, getDRegI64(rD
+ 3 * inc
));
8815 math_INTERLEAVE_4(&di0
, &di1
, &di2
, &di3
,
8816 du0
, du1
, du2
, du3
, 1 << size
);
8817 storeLE(a0
, mkexpr(di0
));
8818 storeLE(a1
, mkexpr(di1
));
8819 storeLE(a2
, mkexpr(di2
));
8820 storeLE(a3
, mkexpr(di3
));
8822 IRTemp tmp
= newTemp(Ity_I32
);
8823 assign(tmp
, binop(Iop_Add32
, mkexpr(addr
), mkU32(32)));
8834 e
= binop(Iop_Add32
, mkexpr(initialRn
),
8835 mkU32(8 * (N
+ 1) * regs
));
8837 e
= binop(Iop_Add32
, mkexpr(initialRn
),
8841 putIRegT(rN
, e
, IRTemp_INVALID
);
8843 putIRegA(rN
, e
, IRTemp_INVALID
, Ijk_Boring
);
8846 DIP("v%s%u.%d {", bL
? "ld" : "st", N
+ 1, 8 << INSN(7,6));
8847 if ((inc
== 1 && regs
* (N
+ 1) > 1)
8848 || (inc
== 2 && regs
> 1 && N
> 0)) {
8849 DIP("d%u-d%u", rD
, rD
+ regs
* (N
+ 1) - 1);
8852 for (r
= 0; r
< regs
; r
++) {
8853 for (i
= 0; i
<= N
; i
++) {
8856 DIP("d%u", rD
+ r
+ i
* inc
);
8860 DIP("}, [r%u]", rN
);
8861 if (rM
!= 13 && rM
!= 15) {
8864 DIP("%s\n", (rM
!= 15) ? "!" : "");
8872 /*------------------------------------------------------------*/
8873 /*--- NEON, top level control ---*/
8874 /*------------------------------------------------------------*/
8876 /* Both ARM and Thumb */
8878 /* Translate a NEON instruction. If successful, returns
8879 True and *dres may or may not be updated. If failure, returns
8880 False and doesn't change *dres nor create any IR.
8882 The Thumb and ARM encodings are similar for the 24 bottom bits, but
8883 the top 8 bits are slightly different. In both cases, the caller
8884 must pass the entire 32 bits. Callers may pass any instruction;
8885 this ignores non-NEON ones.
8887 Caller must supply an IRTemp 'condT' holding the gating condition,
8888 or IRTemp_INVALID indicating the insn is always executed. In ARM
8889 code, this must always be IRTemp_INVALID because NEON insns are
8890 unconditional for ARM.
8892 Finally, the caller must indicate whether this occurs in ARM or in
8895 This only handles NEON for ARMv7 and below. The NEON extensions
8896 for v8 are handled by decode_V8_instruction.
8898 static Bool
decode_NEON_instruction_ARMv7_and_below (
8899 /*MOD*/DisResult
* dres
,
8905 # define INSN(_bMax,_bMin) SLICE_UInt(insn32, (_bMax), (_bMin))
8907 /* There are two kinds of instruction to deal with: load/store and
8908 data processing. In each case, in ARM mode we merely identify
8909 the kind, and pass it on to the relevant sub-handler. In Thumb
8910 mode we identify the kind, swizzle the bits around to make it
8911 have the same encoding as in ARM, and hand it on to the
8915 /* In ARM mode, NEON instructions can't be conditional. */
8917 vassert(condT
== IRTemp_INVALID
);
8920 Thumb: 111U 1111 AAAA Axxx xxxx BBBB CCCC xxxx
8921 ARM: 1111 001U AAAA Axxx xxxx BBBB CCCC xxxx
8923 if (!isT
&& INSN(31,25) == BITS7(1,1,1,1,0,0,1)) {
8925 return dis_neon_data_processing(INSN(31,0), condT
);
8927 if (isT
&& INSN(31,29) == BITS3(1,1,1)
8928 && INSN(27,24) == BITS4(1,1,1,1)) {
8930 UInt reformatted
= INSN(23,0);
8931 reformatted
|= (((UInt
)INSN(28,28)) << 24); // U bit
8932 reformatted
|= (((UInt
)BITS7(1,1,1,1,0,0,1)) << 25);
8933 return dis_neon_data_processing(reformatted
, condT
);
8937 Thumb: 1111 1001 AxL0 xxxx xxxx BBBB xxxx xxxx
8938 ARM: 1111 0100 AxL0 xxxx xxxx BBBB xxxx xxxx
8940 if (!isT
&& INSN(31,24) == BITS8(1,1,1,1,0,1,0,0)) {
8942 return dis_neon_load_or_store(INSN(31,0), isT
, condT
);
8944 if (isT
&& INSN(31,24) == BITS8(1,1,1,1,1,0,0,1)) {
8945 UInt reformatted
= INSN(23,0);
8946 reformatted
|= (((UInt
)BITS8(1,1,1,1,0,1,0,0)) << 24);
8947 return dis_neon_load_or_store(reformatted
, isT
, condT
);
8950 /* Doesn't match. */
8957 /*------------------------------------------------------------*/
8958 /*--- V6 MEDIA instructions ---*/
8959 /*------------------------------------------------------------*/
8961 /* Both ARM and Thumb */
8963 /* Translate a V6 media instruction. If successful, returns
8964 True and *dres may or may not be updated. If failure, returns
8965 False and doesn't change *dres nor create any IR.
8967 The Thumb and ARM encodings are completely different. In Thumb
8968 mode, the caller must pass the entire 32 bits. In ARM mode it must
8969 pass the lower 28 bits. Apart from that, callers may pass any
8970 instruction; this function ignores anything it doesn't recognise.
8972 Caller must supply an IRTemp 'condT' holding the gating condition,
8973 or IRTemp_INVALID indicating the insn is always executed.
8975 Caller must also supply an ARMCondcode 'conq'. This is only used
8976 for debug printing, no other purpose. For ARM, this is simply the
8977 top 4 bits of the original instruction. For Thumb, the condition
8978 is not (really) known until run time, and so ARMCondAL should be
8979 passed, only so that printing of these instructions does not show
8982 Finally, the caller must indicate whether this occurs in ARM or in
8985 static Bool
decode_V6MEDIA_instruction (
8986 /*MOD*/DisResult
* dres
,
8993 # define INSNA(_bMax,_bMin) SLICE_UInt(insnv6m, (_bMax), (_bMin))
8994 # define INSNT0(_bMax,_bMin) SLICE_UInt( ((insnv6m >> 16) & 0xFFFF), \
8996 # define INSNT1(_bMax,_bMin) SLICE_UInt( ((insnv6m >> 0) & 0xFFFF), \
9002 vassert(conq
== ARMCondAL
);
9004 vassert(INSNA(31,28) == BITS4(0,0,0,0)); // caller's obligation
9005 vassert(conq
>= ARMCondEQ
&& conq
<= ARMCondAL
);
9008 /* ----------- smulbb, smulbt, smultb, smultt ----------- */
9010 UInt regD
= 99, regM
= 99, regN
= 99, bitM
= 0, bitN
= 0;
9014 if (INSNT0(15,4) == 0xFB1 && INSNT1(15,12) == BITS4(1,1,1,1)
9015 && INSNT1(7,6) == BITS2(0,0)) {
9016 regD
= INSNT1(11,8);
9021 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9025 if (BITS8(0,0,0,1,0,1,1,0) == INSNA(27,20) &&
9026 BITS4(0,0,0,0) == INSNA(15,12) &&
9027 BITS4(1,0,0,0) == (INSNA(7,4) & BITS4(1,0,0,1)) ) {
9028 regD
= INSNA(19,16);
9033 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9039 IRTemp srcN
= newTemp(Ity_I32
);
9040 IRTemp srcM
= newTemp(Ity_I32
);
9041 IRTemp res
= newTemp(Ity_I32
);
9043 assign( srcN
, binop(Iop_Sar32
,
9045 isT
? getIRegT(regN
) : getIRegA(regN
),
9046 mkU8(bitN
? 0 : 16)), mkU8(16)) );
9047 assign( srcM
, binop(Iop_Sar32
,
9049 isT
? getIRegT(regM
) : getIRegA(regM
),
9050 mkU8(bitM
? 0 : 16)), mkU8(16)) );
9051 assign( res
, binop(Iop_Mul32
, mkexpr(srcN
), mkexpr(srcM
)) );
9054 putIRegT( regD
, mkexpr(res
), condT
);
9056 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9058 DIP( "smul%c%c%s r%u, r%u, r%u\n", bitN
? 't' : 'b', bitM
? 't' : 'b',
9059 nCC(conq
), regD
, regN
, regM
);
9065 /* ------------ smulwb<y><c> <Rd>,<Rn>,<Rm> ------------- */
9066 /* ------------ smulwt<y><c> <Rd>,<Rn>,<Rm> ------------- */
9068 UInt regD
= 99, regN
= 99, regM
= 99, bitM
= 0;
9072 if (INSNT0(15,4) == 0xFB3 && INSNT1(15,12) == BITS4(1,1,1,1)
9073 && INSNT1(7,5) == BITS3(0,0,0)) {
9075 regD
= INSNT1(11,8);
9078 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9082 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
9083 INSNA(15,12) == BITS4(0,0,0,0) &&
9084 (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,1,0)) {
9085 regD
= INSNA(19,16);
9089 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9095 IRTemp irt_prod
= newTemp(Ity_I64
);
9099 isT
? getIRegT(regN
) : getIRegA(regN
),
9102 isT
? getIRegT(regM
) : getIRegA(regM
),
9103 mkU8(bitM
? 0 : 16)),
9106 IRExpr
* ire_result
= binop(Iop_Or32
,
9108 unop(Iop_64HIto32
, mkexpr(irt_prod
)),
9111 unop(Iop_64to32
, mkexpr(irt_prod
)),
9115 putIRegT( regD
, ire_result
, condT
);
9117 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
9119 DIP("smulw%c%s r%u, r%u, r%u\n",
9120 bitM
? 't' : 'b', nCC(conq
),regD
,regN
,regM
);
9126 /* ------------ pkhbt<c> Rd, Rn, Rm {,LSL #imm} ------------- */
9127 /* ------------ pkhtb<c> Rd, Rn, Rm {,ASR #imm} ------------- */
9129 UInt regD
= 99, regN
= 99, regM
= 99, imm5
= 99, shift_type
= 99;
9130 Bool tbform
= False
;
9134 if (INSNT0(15,4) == 0xEAC
9135 && INSNT1(15,15) == 0 && INSNT1(4,4) == 0) {
9137 regD
= INSNT1(11,8);
9139 imm5
= (INSNT1(14,12) << 2) | INSNT1(7,6);
9140 shift_type
= (INSNT1(5,5) << 1) | 0;
9141 tbform
= (INSNT1(5,5) == 0) ? False
: True
;
9142 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9146 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
9147 INSNA(5,4) == BITS2(0,1) /* &&
9148 (INSNA(6,6) == 0 || INSNA(6,6) == 1)
9149 This last bit with INSNA(6,6) is correct, but gcc 8 complains
9150 (correctly) that it is always true. So I commented it out
9151 to keep gcc quiet. */ ) {
9152 regD
= INSNA(15,12);
9153 regN
= INSNA(19,16);
9156 shift_type
= (INSNA(6,6) << 1) | 0;
9157 tbform
= (INSNA(6,6) == 0) ? False
: True
;
9158 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9164 IRTemp irt_regM
= newTemp(Ity_I32
);
9165 IRTemp irt_regM_shift
= newTemp(Ity_I32
);
9166 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9167 compute_result_and_C_after_shift_by_imm5(
9168 dis_buf
, &irt_regM_shift
, NULL
, irt_regM
, shift_type
, imm5
, regM
);
9170 UInt mask
= (tbform
== True
) ? 0x0000FFFF : 0xFFFF0000;
9173 binop(Iop_And32
, mkexpr(irt_regM_shift
), mkU32(mask
)),
9174 binop(Iop_And32
, isT
? getIRegT(regN
) : getIRegA(regN
),
9175 unop(Iop_Not32
, mkU32(mask
))) );
9178 putIRegT( regD
, ire_result
, condT
);
9180 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
9182 DIP( "pkh%s%s r%u, r%u, r%u %s\n", tbform
? "tb" : "bt",
9183 nCC(conq
), regD
, regN
, regM
, dis_buf
);
9190 /* ---------- usat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
9192 UInt regD
= 99, regN
= 99, shift_type
= 99, imm5
= 99, sat_imm
= 99;
9196 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,1,0)
9198 && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
9199 regD
= INSNT1(11,8);
9201 shift_type
= (INSNT0(5,5) << 1) | 0;
9202 imm5
= (INSNT1(14,12) << 2) | INSNT1(7,6);
9203 sat_imm
= INSNT1(4,0);
9204 if (!isBadRegT(regD
) && !isBadRegT(regN
))
9206 if (shift_type
== BITS2(1,0) && imm5
== 0)
9210 if (INSNA(27,21) == BITS7(0,1,1,0,1,1,1) &&
9211 INSNA(5,4) == BITS2(0,1)) {
9212 regD
= INSNA(15,12);
9214 shift_type
= (INSNA(6,6) << 1) | 0;
9216 sat_imm
= INSNA(20,16);
9217 if (regD
!= 15 && regN
!= 15)
9223 IRTemp irt_regN
= newTemp(Ity_I32
);
9224 IRTemp irt_regN_shift
= newTemp(Ity_I32
);
9225 IRTemp irt_sat_Q
= newTemp(Ity_I32
);
9226 IRTemp irt_result
= newTemp(Ity_I32
);
9228 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9229 compute_result_and_C_after_shift_by_imm5(
9230 dis_buf
, &irt_regN_shift
, NULL
,
9231 irt_regN
, shift_type
, imm5
, regN
);
9233 armUnsignedSatQ( &irt_result
, &irt_sat_Q
, irt_regN_shift
, sat_imm
);
9234 or_into_QFLAG32( mkexpr(irt_sat_Q
), condT
);
9237 putIRegT( regD
, mkexpr(irt_result
), condT
);
9239 putIRegA( regD
, mkexpr(irt_result
), condT
, Ijk_Boring
);
9241 DIP("usat%s r%u, #0x%04x, %s\n",
9242 nCC(conq
), regD
, imm5
, dis_buf
);
9248 /* ----------- ssat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
9250 UInt regD
= 99, regN
= 99, shift_type
= 99, imm5
= 99, sat_imm
= 99;
9254 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0)
9256 && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
9257 regD
= INSNT1(11,8);
9259 shift_type
= (INSNT0(5,5) << 1) | 0;
9260 imm5
= (INSNT1(14,12) << 2) | INSNT1(7,6);
9261 sat_imm
= INSNT1(4,0) + 1;
9262 if (!isBadRegT(regD
) && !isBadRegT(regN
))
9264 if (shift_type
== BITS2(1,0) && imm5
== 0)
9268 if (INSNA(27,21) == BITS7(0,1,1,0,1,0,1) &&
9269 INSNA(5,4) == BITS2(0,1)) {
9270 regD
= INSNA(15,12);
9272 shift_type
= (INSNA(6,6) << 1) | 0;
9274 sat_imm
= INSNA(20,16) + 1;
9275 if (regD
!= 15 && regN
!= 15)
9281 IRTemp irt_regN
= newTemp(Ity_I32
);
9282 IRTemp irt_regN_shift
= newTemp(Ity_I32
);
9283 IRTemp irt_sat_Q
= newTemp(Ity_I32
);
9284 IRTemp irt_result
= newTemp(Ity_I32
);
9286 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9287 compute_result_and_C_after_shift_by_imm5(
9288 dis_buf
, &irt_regN_shift
, NULL
,
9289 irt_regN
, shift_type
, imm5
, regN
);
9291 armSignedSatQ( irt_regN_shift
, sat_imm
, &irt_result
, &irt_sat_Q
);
9292 or_into_QFLAG32( mkexpr(irt_sat_Q
), condT
);
9295 putIRegT( regD
, mkexpr(irt_result
), condT
);
9297 putIRegA( regD
, mkexpr(irt_result
), condT
, Ijk_Boring
);
9299 DIP( "ssat%s r%u, #0x%04x, %s\n",
9300 nCC(conq
), regD
, imm5
, dis_buf
);
9306 /* ----------- ssat16<c> <Rd>,#<imm>,<Rn> ----------- */
9308 UInt regD
= 99, regN
= 99, sat_imm
= 99;
9312 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0)
9313 && INSNT0(5,4) == BITS2(1,0)
9314 && INSNT1(15,12) == BITS4(0,0,0,0)
9315 && INSNT1(7,4) == BITS4(0,0,0,0)) {
9316 regD
= INSNT1(11,8);
9318 sat_imm
= INSNT1(3,0) + 1;
9319 if (!isBadRegT(regD
) && !isBadRegT(regN
))
9323 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,1,0) &&
9324 INSNA(11,4) == BITS8(1,1,1,1,0,0,1,1)) {
9325 regD
= INSNA(15,12);
9327 sat_imm
= INSNA(19,16) + 1;
9328 if (regD
!= 15 && regN
!= 15)
9334 IRTemp irt_regN
= newTemp(Ity_I32
);
9335 IRTemp irt_regN_lo
= newTemp(Ity_I32
);
9336 IRTemp irt_regN_hi
= newTemp(Ity_I32
);
9337 IRTemp irt_Q_lo
= newTemp(Ity_I32
);
9338 IRTemp irt_Q_hi
= newTemp(Ity_I32
);
9339 IRTemp irt_res_lo
= newTemp(Ity_I32
);
9340 IRTemp irt_res_hi
= newTemp(Ity_I32
);
9342 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9343 assign( irt_regN_lo
,
9345 binop(Iop_Shl32
, mkexpr(irt_regN
), mkU8(16)),
9347 assign( irt_regN_hi
, binop(Iop_Sar32
, mkexpr(irt_regN
), mkU8(16)) );
9349 armSignedSatQ( irt_regN_lo
, sat_imm
, &irt_res_lo
, &irt_Q_lo
);
9350 or_into_QFLAG32( mkexpr(irt_Q_lo
), condT
);
9352 armSignedSatQ( irt_regN_hi
, sat_imm
, &irt_res_hi
, &irt_Q_hi
);
9353 or_into_QFLAG32( mkexpr(irt_Q_hi
), condT
);
9357 binop(Iop_And32
, mkexpr(irt_res_lo
), mkU32(0xFFFF)),
9358 binop(Iop_Shl32
, mkexpr(irt_res_hi
), mkU8(16)));
9360 putIRegT( regD
, ire_result
, condT
);
9362 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
9364 DIP( "ssat16%s r%u, #0x%04x, r%u\n", nCC(conq
), regD
, sat_imm
, regN
);
9370 /* -------------- usat16<c> <Rd>,#<imm4>,<Rn> --------------- */
9372 UInt regD
= 99, regN
= 99, sat_imm
= 99;
9376 if (INSNT0(15,4) == 0xF3A && (INSNT1(15,0) & 0xF0F0) == 0x0000) {
9378 regD
= INSNT1(11,8);
9379 sat_imm
= INSNT1(3,0);
9380 if (!isBadRegT(regD
) && !isBadRegT(regN
))
9384 if (INSNA(27,20) == BITS8(0,1,1,0,1,1,1,0) &&
9385 INSNA(11,8) == BITS4(1,1,1,1) &&
9386 INSNA(7,4) == BITS4(0,0,1,1)) {
9387 regD
= INSNA(15,12);
9389 sat_imm
= INSNA(19,16);
9390 if (regD
!= 15 && regN
!= 15)
9396 IRTemp irt_regN
= newTemp(Ity_I32
);
9397 IRTemp irt_regN_lo
= newTemp(Ity_I32
);
9398 IRTemp irt_regN_hi
= newTemp(Ity_I32
);
9399 IRTemp irt_Q_lo
= newTemp(Ity_I32
);
9400 IRTemp irt_Q_hi
= newTemp(Ity_I32
);
9401 IRTemp irt_res_lo
= newTemp(Ity_I32
);
9402 IRTemp irt_res_hi
= newTemp(Ity_I32
);
9404 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9405 assign( irt_regN_lo
, binop( Iop_Sar32
,
9406 binop(Iop_Shl32
, mkexpr(irt_regN
), mkU8(16)),
9408 assign( irt_regN_hi
, binop(Iop_Sar32
, mkexpr(irt_regN
), mkU8(16)) );
9410 armUnsignedSatQ( &irt_res_lo
, &irt_Q_lo
, irt_regN_lo
, sat_imm
);
9411 or_into_QFLAG32( mkexpr(irt_Q_lo
), condT
);
9413 armUnsignedSatQ( &irt_res_hi
, &irt_Q_hi
, irt_regN_hi
, sat_imm
);
9414 or_into_QFLAG32( mkexpr(irt_Q_hi
), condT
);
9416 IRExpr
* ire_result
= binop( Iop_Or32
,
9417 binop(Iop_Shl32
, mkexpr(irt_res_hi
), mkU8(16)),
9418 mkexpr(irt_res_lo
) );
9421 putIRegT( regD
, ire_result
, condT
);
9423 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
9425 DIP( "usat16%s r%u, #0x%04x, r%u\n", nCC(conq
), regD
, sat_imm
, regN
);
9431 /* -------------- uadd16<c> <Rd>,<Rn>,<Rm> -------------- */
9433 UInt regD
= 99, regN
= 99, regM
= 99;
9437 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
9439 regD
= INSNT1(11,8);
9441 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9445 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9446 INSNA(11,8) == BITS4(1,1,1,1) &&
9447 INSNA(7,4) == BITS4(0,0,0,1)) {
9448 regD
= INSNA(15,12);
9449 regN
= INSNA(19,16);
9451 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9457 IRTemp rNt
= newTemp(Ity_I32
);
9458 IRTemp rMt
= newTemp(Ity_I32
);
9459 IRTemp res
= newTemp(Ity_I32
);
9460 IRTemp reso
= newTemp(Ity_I32
);
9462 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9463 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9465 assign(res
, binop(Iop_Add16x2
, mkexpr(rNt
), mkexpr(rMt
)));
9467 putIRegT( regD
, mkexpr(res
), condT
);
9469 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9471 assign(reso
, binop(Iop_HAdd16Ux2
, mkexpr(rNt
), mkexpr(rMt
)));
9472 set_GE_32_10_from_bits_31_15(reso
, condT
);
9474 DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9480 /* -------------- sadd16<c> <Rd>,<Rn>,<Rm> -------------- */
9482 UInt regD
= 99, regN
= 99, regM
= 99;
9486 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9488 regD
= INSNT1(11,8);
9490 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9494 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9495 INSNA(11,8) == BITS4(1,1,1,1) &&
9496 INSNA(7,4) == BITS4(0,0,0,1)) {
9497 regD
= INSNA(15,12);
9498 regN
= INSNA(19,16);
9500 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9506 IRTemp rNt
= newTemp(Ity_I32
);
9507 IRTemp rMt
= newTemp(Ity_I32
);
9508 IRTemp res
= newTemp(Ity_I32
);
9509 IRTemp reso
= newTemp(Ity_I32
);
9511 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9512 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9514 assign(res
, binop(Iop_Add16x2
, mkexpr(rNt
), mkexpr(rMt
)));
9516 putIRegT( regD
, mkexpr(res
), condT
);
9518 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9520 assign(reso
, unop(Iop_Not32
,
9521 binop(Iop_HAdd16Sx2
, mkexpr(rNt
), mkexpr(rMt
))));
9522 set_GE_32_10_from_bits_31_15(reso
, condT
);
9524 DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9530 /* ---------------- usub16<c> <Rd>,<Rn>,<Rm> ---------------- */
9532 UInt regD
= 99, regN
= 99, regM
= 99;
9536 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
9538 regD
= INSNT1(11,8);
9540 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9544 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9545 INSNA(11,8) == BITS4(1,1,1,1) &&
9546 INSNA(7,4) == BITS4(0,1,1,1)) {
9547 regD
= INSNA(15,12);
9548 regN
= INSNA(19,16);
9550 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9556 IRTemp rNt
= newTemp(Ity_I32
);
9557 IRTemp rMt
= newTemp(Ity_I32
);
9558 IRTemp res
= newTemp(Ity_I32
);
9559 IRTemp reso
= newTemp(Ity_I32
);
9561 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9562 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9564 assign(res
, binop(Iop_Sub16x2
, mkexpr(rNt
), mkexpr(rMt
)));
9566 putIRegT( regD
, mkexpr(res
), condT
);
9568 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9570 assign(reso
, unop(Iop_Not32
,
9571 binop(Iop_HSub16Ux2
, mkexpr(rNt
), mkexpr(rMt
))));
9572 set_GE_32_10_from_bits_31_15(reso
, condT
);
9574 DIP("usub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9580 /* -------------- ssub16<c> <Rd>,<Rn>,<Rm> -------------- */
9582 UInt regD
= 99, regN
= 99, regM
= 99;
9586 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9588 regD
= INSNT1(11,8);
9590 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9594 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9595 INSNA(11,8) == BITS4(1,1,1,1) &&
9596 INSNA(7,4) == BITS4(0,1,1,1)) {
9597 regD
= INSNA(15,12);
9598 regN
= INSNA(19,16);
9600 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9606 IRTemp rNt
= newTemp(Ity_I32
);
9607 IRTemp rMt
= newTemp(Ity_I32
);
9608 IRTemp res
= newTemp(Ity_I32
);
9609 IRTemp reso
= newTemp(Ity_I32
);
9611 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9612 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9614 assign(res
, binop(Iop_Sub16x2
, mkexpr(rNt
), mkexpr(rMt
)));
9616 putIRegT( regD
, mkexpr(res
), condT
);
9618 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9620 assign(reso
, unop(Iop_Not32
,
9621 binop(Iop_HSub16Sx2
, mkexpr(rNt
), mkexpr(rMt
))));
9622 set_GE_32_10_from_bits_31_15(reso
, condT
);
9624 DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9630 /* ----------------- uadd8<c> <Rd>,<Rn>,<Rm> ---------------- */
9632 UInt regD
= 99, regN
= 99, regM
= 99;
9636 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
9638 regD
= INSNT1(11,8);
9640 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9644 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9645 INSNA(11,8) == BITS4(1,1,1,1) &&
9646 (INSNA(7,4) == BITS4(1,0,0,1))) {
9647 regD
= INSNA(15,12);
9648 regN
= INSNA(19,16);
9650 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9656 IRTemp rNt
= newTemp(Ity_I32
);
9657 IRTemp rMt
= newTemp(Ity_I32
);
9658 IRTemp res
= newTemp(Ity_I32
);
9659 IRTemp reso
= newTemp(Ity_I32
);
9661 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9662 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9664 assign(res
, binop(Iop_Add8x4
, mkexpr(rNt
), mkexpr(rMt
)));
9666 putIRegT( regD
, mkexpr(res
), condT
);
9668 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9670 assign(reso
, binop(Iop_HAdd8Ux4
, mkexpr(rNt
), mkexpr(rMt
)));
9671 set_GE_3_2_1_0_from_bits_31_23_15_7(reso
, condT
);
9673 DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9679 /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
9681 UInt regD
= 99, regN
= 99, regM
= 99;
9685 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9687 regD
= INSNT1(11,8);
9689 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9693 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9694 INSNA(11,8) == BITS4(1,1,1,1) &&
9695 (INSNA(7,4) == BITS4(1,0,0,1))) {
9696 regD
= INSNA(15,12);
9697 regN
= INSNA(19,16);
9699 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9705 IRTemp rNt
= newTemp(Ity_I32
);
9706 IRTemp rMt
= newTemp(Ity_I32
);
9707 IRTemp res
= newTemp(Ity_I32
);
9708 IRTemp reso
= newTemp(Ity_I32
);
9710 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9711 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9713 assign(res
, binop(Iop_Add8x4
, mkexpr(rNt
), mkexpr(rMt
)));
9715 putIRegT( regD
, mkexpr(res
), condT
);
9717 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9719 assign(reso
, unop(Iop_Not32
,
9720 binop(Iop_HAdd8Sx4
, mkexpr(rNt
), mkexpr(rMt
))));
9721 set_GE_3_2_1_0_from_bits_31_23_15_7(reso
, condT
);
9723 DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9729 /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9731 UInt regD
= 99, regN
= 99, regM
= 99;
9735 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
9737 regD
= INSNT1(11,8);
9739 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9743 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9744 INSNA(11,8) == BITS4(1,1,1,1) &&
9745 (INSNA(7,4) == BITS4(1,1,1,1))) {
9746 regD
= INSNA(15,12);
9747 regN
= INSNA(19,16);
9749 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9755 IRTemp rNt
= newTemp(Ity_I32
);
9756 IRTemp rMt
= newTemp(Ity_I32
);
9757 IRTemp res
= newTemp(Ity_I32
);
9758 IRTemp reso
= newTemp(Ity_I32
);
9760 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9761 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9763 assign(res
, binop(Iop_Sub8x4
, mkexpr(rNt
), mkexpr(rMt
)));
9765 putIRegT( regD
, mkexpr(res
), condT
);
9767 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9769 assign(reso
, unop(Iop_Not32
,
9770 binop(Iop_HSub8Ux4
, mkexpr(rNt
), mkexpr(rMt
))));
9771 set_GE_3_2_1_0_from_bits_31_23_15_7(reso
, condT
);
9773 DIP("usub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9779 /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9781 UInt regD
= 99, regN
= 99, regM
= 99;
9785 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9787 regD
= INSNT1(11,8);
9789 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9793 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9794 INSNA(11,8) == BITS4(1,1,1,1) &&
9795 INSNA(7,4) == BITS4(1,1,1,1)) {
9796 regD
= INSNA(15,12);
9797 regN
= INSNA(19,16);
9799 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9805 IRTemp rNt
= newTemp(Ity_I32
);
9806 IRTemp rMt
= newTemp(Ity_I32
);
9807 IRTemp res
= newTemp(Ity_I32
);
9808 IRTemp reso
= newTemp(Ity_I32
);
9810 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9811 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9813 assign(res
, binop(Iop_Sub8x4
, mkexpr(rNt
), mkexpr(rMt
)));
9815 putIRegT( regD
, mkexpr(res
), condT
);
9817 putIRegA( regD
, mkexpr(res
), condT
, Ijk_Boring
);
9819 assign(reso
, unop(Iop_Not32
,
9820 binop(Iop_HSub8Sx4
, mkexpr(rNt
), mkexpr(rMt
))));
9821 set_GE_3_2_1_0_from_bits_31_23_15_7(reso
, condT
);
9823 DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9829 /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9831 UInt regD
= 99, regN
= 99, regM
= 99;
9835 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9837 regD
= INSNT1(11,8);
9839 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9843 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9844 INSNA(11,8) == BITS4(1,1,1,1) &&
9845 INSNA(7,4) == BITS4(1,0,0,1)) {
9846 regD
= INSNA(15,12);
9847 regN
= INSNA(19,16);
9849 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9855 IRTemp rNt
= newTemp(Ity_I32
);
9856 IRTemp rMt
= newTemp(Ity_I32
);
9857 IRTemp res_q
= newTemp(Ity_I32
);
9859 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9860 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9862 assign(res_q
, binop(Iop_QAdd8Sx4
, mkexpr(rNt
), mkexpr(rMt
)));
9864 putIRegT( regD
, mkexpr(res_q
), condT
);
9866 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
9868 DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9874 /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
9876 UInt regD
= 99, regN
= 99, regM
= 99;
9880 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9882 regD
= INSNT1(11,8);
9884 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9888 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9889 INSNA(11,8) == BITS4(1,1,1,1) &&
9890 INSNA(7,4) == BITS4(1,1,1,1)) {
9891 regD
= INSNA(15,12);
9892 regN
= INSNA(19,16);
9894 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9900 IRTemp rNt
= newTemp(Ity_I32
);
9901 IRTemp rMt
= newTemp(Ity_I32
);
9902 IRTemp res_q
= newTemp(Ity_I32
);
9904 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9905 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9907 assign(res_q
, binop(Iop_QSub8Sx4
, mkexpr(rNt
), mkexpr(rMt
)));
9909 putIRegT( regD
, mkexpr(res_q
), condT
);
9911 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
9913 DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9919 /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
9921 UInt regD
= 99, regN
= 99, regM
= 99;
9925 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9927 regD
= INSNT1(11,8);
9929 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9933 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9934 INSNA(11,8) == BITS4(1,1,1,1) &&
9935 (INSNA(7,4) == BITS4(1,0,0,1))) {
9936 regD
= INSNA(15,12);
9937 regN
= INSNA(19,16);
9939 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9945 IRTemp rNt
= newTemp(Ity_I32
);
9946 IRTemp rMt
= newTemp(Ity_I32
);
9947 IRTemp res_q
= newTemp(Ity_I32
);
9949 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9950 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9952 assign(res_q
, binop(Iop_QAdd8Ux4
, mkexpr(rNt
), mkexpr(rMt
)));
9954 putIRegT( regD
, mkexpr(res_q
), condT
);
9956 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
9958 DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
9964 /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9966 UInt regD
= 99, regN
= 99, regM
= 99;
9970 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9972 regD
= INSNT1(11,8);
9974 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
9978 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9979 INSNA(11,8) == BITS4(1,1,1,1) &&
9980 (INSNA(7,4) == BITS4(1,1,1,1))) {
9981 regD
= INSNA(15,12);
9982 regN
= INSNA(19,16);
9984 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
9990 IRTemp rNt
= newTemp(Ity_I32
);
9991 IRTemp rMt
= newTemp(Ity_I32
);
9992 IRTemp res_q
= newTemp(Ity_I32
);
9994 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
9995 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
9997 assign(res_q
, binop(Iop_QSub8Ux4
, mkexpr(rNt
), mkexpr(rMt
)));
9999 putIRegT( regD
, mkexpr(res_q
), condT
);
10001 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10003 DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10009 /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
10011 UInt regD
= 99, regN
= 99, regM
= 99;
10015 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
10016 regN
= INSNT0(3,0);
10017 regD
= INSNT1(11,8);
10018 regM
= INSNT1(3,0);
10019 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10023 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
10024 INSNA(11,8) == BITS4(1,1,1,1) &&
10025 INSNA(7,4) == BITS4(1,0,0,1)) {
10026 regD
= INSNA(15,12);
10027 regN
= INSNA(19,16);
10029 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10035 IRTemp rNt
= newTemp(Ity_I32
);
10036 IRTemp rMt
= newTemp(Ity_I32
);
10037 IRTemp res_q
= newTemp(Ity_I32
);
10039 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10040 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10042 assign(res_q
, binop(Iop_HAdd8Ux4
, mkexpr(rNt
), mkexpr(rMt
)));
10044 putIRegT( regD
, mkexpr(res_q
), condT
);
10046 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10048 DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10054 /* ----------------- uhadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
10056 UInt regD
= 99, regN
= 99, regM
= 99;
10060 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
10061 regN
= INSNT0(3,0);
10062 regD
= INSNT1(11,8);
10063 regM
= INSNT1(3,0);
10064 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10068 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
10069 INSNA(11,8) == BITS4(1,1,1,1) &&
10070 INSNA(7,4) == BITS4(0,0,0,1)) {
10071 regD
= INSNA(15,12);
10072 regN
= INSNA(19,16);
10074 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10080 IRTemp rNt
= newTemp(Ity_I32
);
10081 IRTemp rMt
= newTemp(Ity_I32
);
10082 IRTemp res_q
= newTemp(Ity_I32
);
10084 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10085 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10087 assign(res_q
, binop(Iop_HAdd16Ux2
, mkexpr(rNt
), mkexpr(rMt
)));
10089 putIRegT( regD
, mkexpr(res_q
), condT
);
10091 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10093 DIP("uhadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10099 /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
10101 UInt regD
= 99, regN
= 99, regM
= 99;
10105 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
10106 regN
= INSNT0(3,0);
10107 regD
= INSNT1(11,8);
10108 regM
= INSNT1(3,0);
10109 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10113 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
10114 INSNA(11,8) == BITS4(1,1,1,1) &&
10115 INSNA(7,4) == BITS4(1,0,0,1)) {
10116 regD
= INSNA(15,12);
10117 regN
= INSNA(19,16);
10119 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10125 IRTemp rNt
= newTemp(Ity_I32
);
10126 IRTemp rMt
= newTemp(Ity_I32
);
10127 IRTemp res_q
= newTemp(Ity_I32
);
10129 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10130 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10132 assign(res_q
, binop(Iop_HAdd8Sx4
, mkexpr(rNt
), mkexpr(rMt
)));
10134 putIRegT( regD
, mkexpr(res_q
), condT
);
10136 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10138 DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10144 /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
10146 UInt regD
= 99, regN
= 99, regM
= 99;
10150 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
10151 regN
= INSNT0(3,0);
10152 regD
= INSNT1(11,8);
10153 regM
= INSNT1(3,0);
10154 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10158 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
10159 INSNA(11,8) == BITS4(1,1,1,1) &&
10160 INSNA(7,4) == BITS4(0,0,0,1)) {
10161 regD
= INSNA(15,12);
10162 regN
= INSNA(19,16);
10164 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10170 IRTemp rNt
= newTemp(Ity_I32
);
10171 IRTemp rMt
= newTemp(Ity_I32
);
10172 IRTemp res_q
= newTemp(Ity_I32
);
10174 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10175 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10177 assign(res_q
, binop(Iop_QAdd16Sx2
, mkexpr(rNt
), mkexpr(rMt
)));
10179 putIRegT( regD
, mkexpr(res_q
), condT
);
10181 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10183 DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10189 /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
10191 UInt regD
= 99, regN
= 99, regM
= 99;
10195 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
10196 regN
= INSNT0(3,0);
10197 regD
= INSNT1(11,8);
10198 regM
= INSNT1(3,0);
10199 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10203 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
10204 INSNA(11,8) == BITS4(1,1,1,1) &&
10205 INSNA(7,4) == BITS4(0,1,1,1)) {
10206 regD
= INSNA(15,12);
10207 regN
= INSNA(19,16);
10209 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10215 IRTemp rNt
= newTemp(Ity_I32
);
10216 IRTemp rMt
= newTemp(Ity_I32
);
10217 IRTemp res_q
= newTemp(Ity_I32
);
10219 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10220 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10222 assign(res_q
, binop(Iop_QSub16Sx2
, mkexpr(rNt
), mkexpr(rMt
)));
10224 putIRegT( regD
, mkexpr(res_q
), condT
);
10226 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
10228 DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
10234 /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
10235 /* note: the hardware seems to construct the result differently
10236 from wot the manual says. */
10238 UInt regD
= 99, regN
= 99, regM
= 99;
10242 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
10243 regN
= INSNT0(3,0);
10244 regD
= INSNT1(11,8);
10245 regM
= INSNT1(3,0);
10246 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10250 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
10251 INSNA(11,8) == BITS4(1,1,1,1) &&
10252 INSNA(7,4) == BITS4(0,1,0,1)) {
10253 regD
= INSNA(15,12);
10254 regN
= INSNA(19,16);
10256 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10262 IRTemp irt_regN
= newTemp(Ity_I32
);
10263 IRTemp irt_regM
= newTemp(Ity_I32
);
10264 IRTemp irt_sum
= newTemp(Ity_I32
);
10265 IRTemp irt_diff
= newTemp(Ity_I32
);
10266 IRTemp irt_sum_res
= newTemp(Ity_I32
);
10267 IRTemp irt_diff_res
= newTemp(Ity_I32
);
10269 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10270 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10274 binop( Iop_Sar32
, mkexpr(irt_regN
), mkU8(16) ),
10276 binop(Iop_Shl32
, mkexpr(irt_regM
), mkU8(16)),
10278 armSignedSatQ( irt_diff
, 0x10, &irt_diff_res
, NULL
);
10283 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
10285 binop( Iop_Sar32
, mkexpr(irt_regM
), mkU8(16) )) );
10286 armSignedSatQ( irt_sum
, 0x10, &irt_sum_res
, NULL
);
10288 IRExpr
* ire_result
= binop( Iop_Or32
,
10289 binop( Iop_Shl32
, mkexpr(irt_diff_res
),
10291 binop( Iop_And32
, mkexpr(irt_sum_res
),
10295 putIRegT( regD
, ire_result
, condT
);
10297 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10299 DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
10305 /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */
10307 UInt regD
= 99, regN
= 99, regM
= 99;
10311 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
10312 regN
= INSNT0(3,0);
10313 regD
= INSNT1(11,8);
10314 regM
= INSNT1(3,0);
10315 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10319 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
10320 INSNA(11,8) == BITS4(1,1,1,1) &&
10321 INSNA(7,4) == BITS4(0,0,1,1)) {
10322 regD
= INSNA(15,12);
10323 regN
= INSNA(19,16);
10325 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10331 IRTemp irt_regN
= newTemp(Ity_I32
);
10332 IRTemp irt_regM
= newTemp(Ity_I32
);
10333 IRTemp irt_sum
= newTemp(Ity_I32
);
10334 IRTemp irt_diff
= newTemp(Ity_I32
);
10335 IRTemp irt_res_sum
= newTemp(Ity_I32
);
10336 IRTemp irt_res_diff
= newTemp(Ity_I32
);
10338 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10339 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10344 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
10346 binop( Iop_Sar32
, mkexpr(irt_regM
), mkU8(16) ) ) );
10347 armSignedSatQ( irt_diff
, 0x10, &irt_res_diff
, NULL
);
10351 binop( Iop_Sar32
, mkexpr(irt_regN
), mkU8(16) ),
10353 binop( Iop_Shl32
, mkexpr(irt_regM
), mkU8(16) ),
10355 armSignedSatQ( irt_sum
, 0x10, &irt_res_sum
, NULL
);
10359 binop( Iop_Shl32
, mkexpr(irt_res_sum
), mkU8(16) ),
10360 binop( Iop_And32
, mkexpr(irt_res_diff
), mkU32(0xFFFF) ) );
10363 putIRegT( regD
, ire_result
, condT
);
10365 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10367 DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
10373 /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */
10375 UInt regD
= 99, regN
= 99, regM
= 99;
10379 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
10380 regN
= INSNT0(3,0);
10381 regD
= INSNT1(11,8);
10382 regM
= INSNT1(3,0);
10383 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10387 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
10388 INSNA(11,8) == BITS4(1,1,1,1) &&
10389 INSNA(7,4) == BITS4(0,0,1,1)) {
10390 regD
= INSNA(15,12);
10391 regN
= INSNA(19,16);
10393 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10399 IRTemp irt_regN
= newTemp(Ity_I32
);
10400 IRTemp irt_regM
= newTemp(Ity_I32
);
10401 IRTemp irt_sum
= newTemp(Ity_I32
);
10402 IRTemp irt_diff
= newTemp(Ity_I32
);
10404 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10405 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10410 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
10412 binop( Iop_Sar32
, mkexpr(irt_regM
), mkU8(16) ) ) );
10416 binop( Iop_Sar32
, mkexpr(irt_regN
), mkU8(16) ),
10418 binop( Iop_Shl32
, mkexpr(irt_regM
), mkU8(16) ),
10423 binop( Iop_Shl32
, mkexpr(irt_sum
), mkU8(16) ),
10424 binop( Iop_And32
, mkexpr(irt_diff
), mkU32(0xFFFF) ) );
10426 IRTemp ge10
= newTemp(Ity_I32
);
10427 assign(ge10
, unop(Iop_Not32
, mkexpr(irt_diff
)));
10428 put_GEFLAG32( 0, 31, mkexpr(ge10
), condT
);
10429 put_GEFLAG32( 1, 31, mkexpr(ge10
), condT
);
10431 IRTemp ge32
= newTemp(Ity_I32
);
10432 assign(ge32
, unop(Iop_Not32
, mkexpr(irt_sum
)));
10433 put_GEFLAG32( 2, 31, mkexpr(ge32
), condT
);
10434 put_GEFLAG32( 3, 31, mkexpr(ge32
), condT
);
10437 putIRegT( regD
, ire_result
, condT
);
10439 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10441 DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
10447 /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */
10448 /* --------------- smsad, smsadx<c><Rd>,<Rn>,<Rm> --------------- */
10450 UInt regD
= 99, regN
= 99, regM
= 99, bitM
= 99;
10451 Bool gate
= False
, isAD
= False
;
10454 if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
10455 && (INSNT1(15,0) & 0xF0E0) == 0xF000) {
10456 regN
= INSNT0(3,0);
10457 regD
= INSNT1(11,8);
10458 regM
= INSNT1(3,0);
10459 bitM
= INSNT1(4,4);
10460 isAD
= INSNT0(15,4) == 0xFB2;
10461 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10465 if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
10466 INSNA(15,12) == BITS4(1,1,1,1) &&
10467 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1) ) {
10468 regD
= INSNA(19,16);
10470 regM
= INSNA(11,8);
10472 isAD
= INSNA(6,6) == 0;
10473 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10479 IRTemp irt_regN
= newTemp(Ity_I32
);
10480 IRTemp irt_regM
= newTemp(Ity_I32
);
10481 IRTemp irt_prod_lo
= newTemp(Ity_I32
);
10482 IRTemp irt_prod_hi
= newTemp(Ity_I32
);
10483 IRTemp tmpM
= newTemp(Ity_I32
);
10485 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10487 assign( tmpM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10488 assign( irt_regM
, genROR32(tmpM
, (bitM
& 1) ? 16 : 0) );
10490 assign( irt_prod_lo
,
10493 binop(Iop_Shl32
, mkexpr(irt_regN
), mkU8(16)),
10496 binop(Iop_Shl32
, mkexpr(irt_regM
), mkU8(16)),
10498 assign( irt_prod_hi
, binop(Iop_Mul32
,
10499 binop(Iop_Sar32
, mkexpr(irt_regN
), mkU8(16)),
10500 binop(Iop_Sar32
, mkexpr(irt_regM
), mkU8(16))) );
10502 = binop( isAD
? Iop_Add32
: Iop_Sub32
,
10503 mkexpr(irt_prod_lo
), mkexpr(irt_prod_hi
) );
10506 putIRegT( regD
, ire_result
, condT
);
10508 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10512 signed_overflow_after_Add32( ire_result
,
10513 irt_prod_lo
, irt_prod_hi
),
10518 DIP("smu%cd%s%s r%u, r%u, r%u\n",
10520 bitM
? "x" : "", nCC(conq
), regD
, regN
, regM
);
10526 /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
10527 /* --------------- smlsd{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
10529 UInt regD
= 99, regN
= 99, regM
= 99, regA
= 99, bitM
= 99;
10530 Bool gate
= False
, isAD
= False
;
10533 if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
10534 && INSNT1(7,5) == BITS3(0,0,0)) {
10535 regN
= INSNT0(3,0);
10536 regD
= INSNT1(11,8);
10537 regM
= INSNT1(3,0);
10538 regA
= INSNT1(15,12);
10539 bitM
= INSNT1(4,4);
10540 isAD
= INSNT0(15,4) == 0xFB2;
10541 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
)
10542 && !isBadRegT(regA
))
10546 if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
10547 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
10548 regD
= INSNA(19,16);
10549 regA
= INSNA(15,12);
10551 regM
= INSNA(11,8);
10553 isAD
= INSNA(6,6) == 0;
10554 if (regD
!= 15 && regN
!= 15 && regM
!= 15 && regA
!= 15)
10560 IRTemp irt_regN
= newTemp(Ity_I32
);
10561 IRTemp irt_regM
= newTemp(Ity_I32
);
10562 IRTemp irt_regA
= newTemp(Ity_I32
);
10563 IRTemp irt_prod_lo
= newTemp(Ity_I32
);
10564 IRTemp irt_prod_hi
= newTemp(Ity_I32
);
10565 IRTemp irt_sum
= newTemp(Ity_I32
);
10566 IRTemp tmpM
= newTemp(Ity_I32
);
10568 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10569 assign( irt_regA
, isT
? getIRegT(regA
) : getIRegA(regA
) );
10571 assign( tmpM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10572 assign( irt_regM
, genROR32(tmpM
, (bitM
& 1) ? 16 : 0) );
10574 assign( irt_prod_lo
,
10577 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
10580 binop( Iop_Shl32
, mkexpr(irt_regM
), mkU8(16) ),
10582 assign( irt_prod_hi
,
10584 binop( Iop_Sar32
, mkexpr(irt_regN
), mkU8(16) ),
10585 binop( Iop_Sar32
, mkexpr(irt_regM
), mkU8(16) ) ) );
10586 assign( irt_sum
, binop( isAD
? Iop_Add32
: Iop_Sub32
,
10587 mkexpr(irt_prod_lo
), mkexpr(irt_prod_hi
) ) );
10589 IRExpr
* ire_result
= binop(Iop_Add32
, mkexpr(irt_sum
), mkexpr(irt_regA
));
10592 putIRegT( regD
, ire_result
, condT
);
10594 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10598 signed_overflow_after_Add32( mkexpr(irt_sum
),
10599 irt_prod_lo
, irt_prod_hi
),
10605 signed_overflow_after_Add32( ire_result
, irt_sum
, irt_regA
),
10609 DIP("sml%cd%s%s r%u, r%u, r%u, r%u\n",
10611 bitM
? "x" : "", nCC(conq
), regD
, regN
, regM
, regA
);
10617 /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */
10619 UInt regD
= 99, regN
= 99, regM
= 99, regA
= 99, bitM
= 99, bitN
= 99;
10623 if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) {
10624 regN
= INSNT0(3,0);
10625 regD
= INSNT1(11,8);
10626 regM
= INSNT1(3,0);
10627 regA
= INSNT1(15,12);
10628 bitM
= INSNT1(4,4);
10629 bitN
= INSNT1(5,5);
10630 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
)
10631 && !isBadRegT(regA
))
10635 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
10636 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
10637 regD
= INSNA(19,16);
10639 regM
= INSNA(11,8);
10640 regA
= INSNA(15,12);
10643 if (regD
!= 15 && regN
!= 15 && regM
!= 15 && regA
!= 15)
10649 IRTemp irt_regA
= newTemp(Ity_I32
);
10650 IRTemp irt_prod
= newTemp(Ity_I32
);
10656 isT
? getIRegT(regN
) : getIRegA(regN
),
10657 mkU8(bitN
? 0 : 16)),
10661 isT
? getIRegT(regM
) : getIRegA(regM
),
10662 mkU8(bitM
? 0 : 16)),
10665 assign( irt_regA
, isT
? getIRegT(regA
) : getIRegA(regA
) );
10667 IRExpr
* ire_result
= binop(Iop_Add32
, mkexpr(irt_prod
), mkexpr(irt_regA
));
10670 putIRegT( regD
, ire_result
, condT
);
10672 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10675 signed_overflow_after_Add32( ire_result
, irt_prod
, irt_regA
),
10679 DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n",
10680 bitN
? 't' : 'b', bitM
? 't' : 'b',
10681 nCC(conq
), regD
, regN
, regM
, regA
);
10687 /* ----- smlalbb, smlalbt, smlaltb, smlaltt <Rd>,<Rn>,<Rm>,<Ra> ----- */
10689 UInt regDHi
= 99, regN
= 99, regM
= 99, regDLo
= 99, bitM
= 99, bitN
= 99;
10693 if (INSNT0(15,4) == 0xFBC && INSNT1(7,6) == BITS2(1,0)) {
10694 regN
= INSNT0(3,0);
10695 regDHi
= INSNT1(11,8);
10696 regM
= INSNT1(3,0);
10697 regDLo
= INSNT1(15,12);
10698 bitM
= INSNT1(4,4);
10699 bitN
= INSNT1(5,5);
10700 if (!isBadRegT(regDHi
) && !isBadRegT(regN
) && !isBadRegT(regM
)
10701 && !isBadRegT(regDLo
) && regDHi
!= regDLo
)
10705 if (INSNA(27,20) == BITS8(0,0,0,1,0,1,0,0) &&
10706 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
10707 regDHi
= INSNA(19,16);
10709 regM
= INSNA(11,8);
10710 regDLo
= INSNA(15,12);
10713 if (regDHi
!= 15 && regN
!= 15 && regM
!= 15 && regDLo
!= 15 &&
10720 IRTemp irt_regD
= newTemp(Ity_I64
);
10721 IRTemp irt_prod
= newTemp(Ity_I64
);
10722 IRTemp irt_res
= newTemp(Ity_I64
);
10723 IRTemp irt_resHi
= newTemp(Ity_I32
);
10724 IRTemp irt_resLo
= newTemp(Ity_I32
);
10730 isT
? getIRegT(regN
) : getIRegA(regN
),
10731 mkU8(bitN
? 0 : 16)),
10735 isT
? getIRegT(regM
) : getIRegA(regM
),
10736 mkU8(bitM
? 0 : 16)),
10739 assign( irt_regD
, binop(Iop_32HLto64
,
10740 isT
? getIRegT(regDHi
) : getIRegA(regDHi
),
10741 isT
? getIRegT(regDLo
) : getIRegA(regDLo
)) );
10742 assign( irt_res
, binop(Iop_Add64
, mkexpr(irt_regD
), mkexpr(irt_prod
)) );
10743 assign( irt_resHi
, unop(Iop_64HIto32
, mkexpr(irt_res
)) );
10744 assign( irt_resLo
, unop(Iop_64to32
, mkexpr(irt_res
)) );
10747 putIRegT( regDHi
, mkexpr(irt_resHi
), condT
);
10748 putIRegT( regDLo
, mkexpr(irt_resLo
), condT
);
10750 putIRegA( regDHi
, mkexpr(irt_resHi
), condT
, Ijk_Boring
);
10751 putIRegA( regDLo
, mkexpr(irt_resLo
), condT
, Ijk_Boring
);
10754 DIP( "smlal%c%c%s r%u, r%u, r%u, r%u\n",
10755 bitN
? 't' : 'b', bitM
? 't' : 'b',
10756 nCC(conq
), regDHi
, regN
, regM
, regDLo
);
10762 /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */
10764 UInt regD
= 99, regN
= 99, regM
= 99, regA
= 99, bitM
= 99;
10768 if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) {
10769 regN
= INSNT0(3,0);
10770 regD
= INSNT1(11,8);
10771 regM
= INSNT1(3,0);
10772 regA
= INSNT1(15,12);
10773 bitM
= INSNT1(4,4);
10774 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
)
10775 && !isBadRegT(regA
))
10779 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
10780 (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) {
10781 regD
= INSNA(19,16);
10783 regM
= INSNA(11,8);
10784 regA
= INSNA(15,12);
10786 if (regD
!= 15 && regN
!= 15 && regM
!= 15 && regA
!= 15)
10792 IRTemp irt_regA
= newTemp(Ity_I32
);
10793 IRTemp irt_prod
= newTemp(Ity_I64
);
10797 isT
? getIRegT(regN
) : getIRegA(regN
),
10800 isT
? getIRegT(regM
) : getIRegA(regM
),
10801 mkU8(bitM
? 0 : 16)),
10804 assign( irt_regA
, isT
? getIRegT(regA
) : getIRegA(regA
) );
10806 IRTemp prod32
= newTemp(Ity_I32
);
10809 binop(Iop_Shl32
, unop(Iop_64HIto32
, mkexpr(irt_prod
)), mkU8(16)),
10810 binop(Iop_Shr32
, unop(Iop_64to32
, mkexpr(irt_prod
)), mkU8(16))
10813 IRExpr
* ire_result
= binop(Iop_Add32
, mkexpr(prod32
), mkexpr(irt_regA
));
10816 putIRegT( regD
, ire_result
, condT
);
10818 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10821 signed_overflow_after_Add32( ire_result
, prod32
, irt_regA
),
10825 DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n",
10827 nCC(conq
), regD
, regN
, regM
, regA
);
10833 /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */
10834 /* fixme: fix up the test in v6media.c so that we can pass the ge
10835 flags as part of the test. */
10837 UInt regD
= 99, regN
= 99, regM
= 99;
10841 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
10842 regN
= INSNT0(3,0);
10843 regD
= INSNT1(11,8);
10844 regM
= INSNT1(3,0);
10845 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10849 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
10850 INSNA(11,8) == BITS4(1,1,1,1) &&
10851 INSNA(7,4) == BITS4(1,0,1,1)) {
10852 regD
= INSNA(15,12);
10853 regN
= INSNA(19,16);
10855 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10861 IRTemp irt_ge_flag0
= newTemp(Ity_I32
);
10862 IRTemp irt_ge_flag1
= newTemp(Ity_I32
);
10863 IRTemp irt_ge_flag2
= newTemp(Ity_I32
);
10864 IRTemp irt_ge_flag3
= newTemp(Ity_I32
);
10866 assign( irt_ge_flag0
, get_GEFLAG32(0) );
10867 assign( irt_ge_flag1
, get_GEFLAG32(1) );
10868 assign( irt_ge_flag2
, get_GEFLAG32(2) );
10869 assign( irt_ge_flag3
, get_GEFLAG32(3) );
10871 IRExpr
* ire_ge_flag0_or
10872 = binop(Iop_Or32
, mkexpr(irt_ge_flag0
),
10873 binop(Iop_Sub32
, mkU32(0), mkexpr(irt_ge_flag0
)));
10874 IRExpr
* ire_ge_flag1_or
10875 = binop(Iop_Or32
, mkexpr(irt_ge_flag1
),
10876 binop(Iop_Sub32
, mkU32(0), mkexpr(irt_ge_flag1
)));
10877 IRExpr
* ire_ge_flag2_or
10878 = binop(Iop_Or32
, mkexpr(irt_ge_flag2
),
10879 binop(Iop_Sub32
, mkU32(0), mkexpr(irt_ge_flag2
)));
10880 IRExpr
* ire_ge_flag3_or
10881 = binop(Iop_Or32
, mkexpr(irt_ge_flag3
),
10882 binop(Iop_Sub32
, mkU32(0), mkexpr(irt_ge_flag3
)));
10884 IRExpr
* ire_ge_flags
10888 binop(Iop_Sar32
, ire_ge_flag0_or
, mkU8(31)),
10889 mkU32(0x000000ff)),
10891 binop(Iop_Sar32
, ire_ge_flag1_or
, mkU8(31)),
10892 mkU32(0x0000ff00))),
10895 binop(Iop_Sar32
, ire_ge_flag2_or
, mkU8(31)),
10896 mkU32(0x00ff0000)),
10898 binop(Iop_Sar32
, ire_ge_flag3_or
, mkU8(31)),
10899 mkU32(0xff000000))) );
10904 isT
? getIRegT(regN
) : getIRegA(regN
),
10907 isT
? getIRegT(regM
) : getIRegA(regM
),
10908 unop(Iop_Not32
, ire_ge_flags
)));
10911 putIRegT( regD
, ire_result
, condT
);
10913 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10915 DIP("sel%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
10921 /* ----------------- uxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
10923 UInt regD
= 99, regN
= 99, regM
= 99, rotate
= 99;
10927 if (INSNT0(15,4) == 0xFA3 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
10928 regN
= INSNT0(3,0);
10929 regD
= INSNT1(11,8);
10930 regM
= INSNT1(3,0);
10931 rotate
= INSNT1(5,4);
10932 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
10936 if (INSNA(27,20) == BITS8(0,1,1,0,1,1,0,0) &&
10937 INSNA(9,4) == BITS6(0,0,0,1,1,1) ) {
10938 regD
= INSNA(15,12);
10939 regN
= INSNA(19,16);
10941 rotate
= INSNA(11,10);
10942 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
10948 IRTemp irt_regN
= newTemp(Ity_I32
);
10949 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
10951 IRTemp irt_regM
= newTemp(Ity_I32
);
10952 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
10954 IRTemp irt_rot
= newTemp(Ity_I32
);
10955 assign( irt_rot
, binop(Iop_And32
,
10956 genROR32(irt_regM
, 8 * rotate
),
10957 mkU32(0x00FF00FF)) );
10961 binop(Iop_Add32
, mkexpr(irt_regN
), mkexpr(irt_rot
)),
10962 mkU32(0x0000FFFF));
10966 binop(Iop_And32
, mkexpr(irt_regN
), mkU32(0xFFFF0000)),
10967 binop(Iop_And32
, mkexpr(irt_rot
), mkU32(0xFFFF0000)));
10970 = binop( Iop_Or32
, resHi
, resLo
);
10973 putIRegT( regD
, ire_result
, condT
);
10975 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
10977 DIP( "uxtab16%s r%u, r%u, r%u, ROR #%u\n",
10978 nCC(conq
), regD
, regN
, regM
, 8 * rotate
);
10984 /* --------------- usad8 Rd,Rn,Rm ---------------- */
10985 /* --------------- usada8 Rd,Rn,Rm,Ra ---------------- */
10987 UInt rD
= 99, rN
= 99, rM
= 99, rA
= 99;
10991 if (INSNT0(15,4) == 0xFB7 && INSNT1(7,4) == BITS4(0,0,0,0)) {
10993 rA
= INSNT1(15,12);
10996 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
) && rA
!= 13)
11000 if (INSNA(27,20) == BITS8(0,1,1,1,1,0,0,0) &&
11001 INSNA(7,4) == BITS4(0,0,0,1) ) {
11006 if (rD
!= 15 && rN
!= 15 && rM
!= 15 /* but rA can be 15 */)
11010 /* We allow rA == 15, to denote the usad8 (no accumulator) case. */
11013 IRExpr
* rNe
= isT
? getIRegT(rN
) : getIRegA(rN
);
11014 IRExpr
* rMe
= isT
? getIRegT(rM
) : getIRegA(rM
);
11015 IRExpr
* rAe
= rA
== 15 ? mkU32(0)
11016 : (isT
? getIRegT(rA
) : getIRegA(rA
));
11017 IRExpr
* res
= binop(Iop_Add32
,
11018 binop(Iop_Sad8Ux4
, rNe
, rMe
),
11021 putIRegT( rD
, res
, condT
);
11023 putIRegA( rD
, res
, condT
, Ijk_Boring
);
11026 DIP( "usad8%s r%u, r%u, r%u\n",
11027 nCC(conq
), rD
, rN
, rM
);
11029 DIP( "usada8%s r%u, r%u, r%u, r%u\n",
11030 nCC(conq
), rD
, rN
, rM
, rA
);
11037 /* ------------------ qadd<c> <Rd>,<Rn>,<Rm> ------------------- */
11039 UInt regD
= 99, regN
= 99, regM
= 99;
11043 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
11044 regN
= INSNT0(3,0);
11045 regD
= INSNT1(11,8);
11046 regM
= INSNT1(3,0);
11047 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11051 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
11052 INSNA(11,8) == BITS4(0,0,0,0) &&
11053 INSNA(7,4) == BITS4(0,1,0,1)) {
11054 regD
= INSNA(15,12);
11055 regN
= INSNA(19,16);
11057 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11063 IRTemp rNt
= newTemp(Ity_I32
);
11064 IRTemp rMt
= newTemp(Ity_I32
);
11065 IRTemp res_q
= newTemp(Ity_I32
);
11067 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11068 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11070 assign(res_q
, binop(Iop_QAdd32S
, mkexpr(rMt
), mkexpr(rNt
)));
11072 putIRegT( regD
, mkexpr(res_q
), condT
);
11074 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11077 signed_overflow_after_Add32(
11078 binop(Iop_Add32
, mkexpr(rMt
), mkexpr(rNt
)), rMt
, rNt
),
11082 DIP("qadd%s r%u, r%u, r%u\n", nCC(conq
),regD
,regM
,regN
);
11088 /* ------------------ qdadd<c> <Rd>,<Rm>,<Rn> ------------------- */
11090 UInt regD
= 99, regN
= 99, regM
= 99;
11094 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF090) {
11095 regN
= INSNT0(3,0);
11096 regD
= INSNT1(11,8);
11097 regM
= INSNT1(3,0);
11098 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11102 if (INSNA(27,20) == BITS8(0,0,0,1,0,1,0,0) &&
11103 INSNA(11,8) == BITS4(0,0,0,0) &&
11104 INSNA(7,4) == BITS4(0,1,0,1)) {
11105 regD
= INSNA(15,12);
11106 regN
= INSNA(19,16);
11108 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11114 IRTemp rNt
= newTemp(Ity_I32
);
11115 IRTemp rMt
= newTemp(Ity_I32
);
11116 IRTemp rN_d
= newTemp(Ity_I32
);
11117 IRTemp res_q
= newTemp(Ity_I32
);
11119 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11120 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11123 signed_overflow_after_Add32(
11124 binop(Iop_Add32
, mkexpr(rNt
), mkexpr(rNt
)), rNt
, rNt
),
11128 assign(rN_d
, binop(Iop_QAdd32S
, mkexpr(rNt
), mkexpr(rNt
)));
11129 assign(res_q
, binop(Iop_QAdd32S
, mkexpr(rMt
), mkexpr(rN_d
)));
11131 putIRegT( regD
, mkexpr(res_q
), condT
);
11133 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11136 signed_overflow_after_Add32(
11137 binop(Iop_Add32
, mkexpr(rMt
), mkexpr(rN_d
)), rMt
, rN_d
),
11141 DIP("qdadd%s r%u, r%u, r%u\n", nCC(conq
),regD
,regM
,regN
);
11147 /* ------------------ qsub<c> <Rd>,<Rn>,<Rm> ------------------- */
11149 UInt regD
= 99, regN
= 99, regM
= 99;
11153 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0A0) {
11154 regN
= INSNT0(3,0);
11155 regD
= INSNT1(11,8);
11156 regM
= INSNT1(3,0);
11157 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11161 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
11162 INSNA(11,8) == BITS4(0,0,0,0) &&
11163 INSNA(7,4) == BITS4(0,1,0,1)) {
11164 regD
= INSNA(15,12);
11165 regN
= INSNA(19,16);
11167 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11173 IRTemp rNt
= newTemp(Ity_I32
);
11174 IRTemp rMt
= newTemp(Ity_I32
);
11175 IRTemp res_q
= newTemp(Ity_I32
);
11177 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11178 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11180 assign(res_q
, binop(Iop_QSub32S
, mkexpr(rMt
), mkexpr(rNt
)));
11182 putIRegT( regD
, mkexpr(res_q
), condT
);
11184 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11187 signed_overflow_after_Sub32(
11188 binop(Iop_Sub32
, mkexpr(rMt
), mkexpr(rNt
)), rMt
, rNt
),
11192 DIP("qsub%s r%u, r%u, r%u\n", nCC(conq
),regD
,regM
,regN
);
11198 /* ------------------ qdsub<c> <Rd>,<Rm>,<Rn> ------------------- */
11200 UInt regD
= 99, regN
= 99, regM
= 99;
11204 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0B0) {
11205 regN
= INSNT0(3,0);
11206 regD
= INSNT1(11,8);
11207 regM
= INSNT1(3,0);
11208 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11212 if (INSNA(27,20) == BITS8(0,0,0,1,0,1,1,0) &&
11213 INSNA(11,8) == BITS4(0,0,0,0) &&
11214 INSNA(7,4) == BITS4(0,1,0,1)) {
11215 regD
= INSNA(15,12);
11216 regN
= INSNA(19,16);
11218 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11224 IRTemp rNt
= newTemp(Ity_I32
);
11225 IRTemp rMt
= newTemp(Ity_I32
);
11226 IRTemp rN_d
= newTemp(Ity_I32
);
11227 IRTemp res_q
= newTemp(Ity_I32
);
11229 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11230 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11233 signed_overflow_after_Add32(
11234 binop(Iop_Add32
, mkexpr(rNt
), mkexpr(rNt
)), rNt
, rNt
),
11238 assign(rN_d
, binop(Iop_QAdd32S
, mkexpr(rNt
), mkexpr(rNt
)));
11239 assign(res_q
, binop(Iop_QSub32S
, mkexpr(rMt
), mkexpr(rN_d
)));
11241 putIRegT( regD
, mkexpr(res_q
), condT
);
11243 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11246 signed_overflow_after_Sub32(
11247 binop(Iop_Sub32
, mkexpr(rMt
), mkexpr(rN_d
)), rMt
, rN_d
),
11251 DIP("qdsub%s r%u, r%u, r%u\n", nCC(conq
),regD
,regM
,regN
);
11257 /* ------------------ uqsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
11259 UInt regD
= 99, regN
= 99, regM
= 99;
11263 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
11264 regN
= INSNT0(3,0);
11265 regD
= INSNT1(11,8);
11266 regM
= INSNT1(3,0);
11267 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11271 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
11272 INSNA(11,8) == BITS4(1,1,1,1) &&
11273 INSNA(7,4) == BITS4(0,1,1,1)) {
11274 regD
= INSNA(15,12);
11275 regN
= INSNA(19,16);
11277 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11283 IRTemp rNt
= newTemp(Ity_I32
);
11284 IRTemp rMt
= newTemp(Ity_I32
);
11285 IRTemp res_q
= newTemp(Ity_I32
);
11287 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11288 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11290 assign(res_q
, binop(Iop_QSub16Ux2
, mkexpr(rNt
), mkexpr(rMt
)));
11292 putIRegT( regD
, mkexpr(res_q
), condT
);
11294 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11296 DIP("uqsub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11302 /* ----------------- shadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
11304 UInt regD
= 99, regN
= 99, regM
= 99;
11308 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
11309 regN
= INSNT0(3,0);
11310 regD
= INSNT1(11,8);
11311 regM
= INSNT1(3,0);
11312 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11316 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
11317 INSNA(11,8) == BITS4(1,1,1,1) &&
11318 INSNA(7,4) == BITS4(0,0,0,1)) {
11319 regD
= INSNA(15,12);
11320 regN
= INSNA(19,16);
11322 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11328 IRTemp rNt
= newTemp(Ity_I32
);
11329 IRTemp rMt
= newTemp(Ity_I32
);
11330 IRTemp res_q
= newTemp(Ity_I32
);
11332 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11333 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11335 assign(res_q
, binop(Iop_HAdd16Sx2
, mkexpr(rNt
), mkexpr(rMt
)));
11337 putIRegT( regD
, mkexpr(res_q
), condT
);
11339 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11341 DIP("shadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11347 /* ----------------- uhsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
11349 UInt regD
= 99, regN
= 99, regM
= 99;
11353 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
11354 regN
= INSNT0(3,0);
11355 regD
= INSNT1(11,8);
11356 regM
= INSNT1(3,0);
11357 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11361 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
11362 INSNA(11,8) == BITS4(1,1,1,1) &&
11363 INSNA(7,4) == BITS4(1,1,1,1)) {
11364 regD
= INSNA(15,12);
11365 regN
= INSNA(19,16);
11367 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11373 IRTemp rNt
= newTemp(Ity_I32
);
11374 IRTemp rMt
= newTemp(Ity_I32
);
11375 IRTemp res_q
= newTemp(Ity_I32
);
11377 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11378 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11380 assign(res_q
, binop(Iop_HSub8Ux4
, mkexpr(rNt
), mkexpr(rMt
)));
11382 putIRegT( regD
, mkexpr(res_q
), condT
);
11384 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11386 DIP("uhsub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11392 /* ----------------- uhsub16<c> <Rd>,<Rn>,<Rm> ------------------- */
11394 UInt regD
= 99, regN
= 99, regM
= 99;
11398 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
11399 regN
= INSNT0(3,0);
11400 regD
= INSNT1(11,8);
11401 regM
= INSNT1(3,0);
11402 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11406 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
11407 INSNA(11,8) == BITS4(1,1,1,1) &&
11408 INSNA(7,4) == BITS4(0,1,1,1)) {
11409 regD
= INSNA(15,12);
11410 regN
= INSNA(19,16);
11412 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11418 IRTemp rNt
= newTemp(Ity_I32
);
11419 IRTemp rMt
= newTemp(Ity_I32
);
11420 IRTemp res_q
= newTemp(Ity_I32
);
11422 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11423 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11425 assign(res_q
, binop(Iop_HSub16Ux2
, mkexpr(rNt
), mkexpr(rMt
)));
11427 putIRegT( regD
, mkexpr(res_q
), condT
);
11429 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11431 DIP("uhsub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11437 /* ------------------ uqadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
11439 UInt regD
= 99, regN
= 99, regM
= 99;
11443 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
11444 regN
= INSNT0(3,0);
11445 regD
= INSNT1(11,8);
11446 regM
= INSNT1(3,0);
11447 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11451 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
11452 INSNA(11,8) == BITS4(1,1,1,1) &&
11453 INSNA(7,4) == BITS4(0,0,0,1)) {
11454 regD
= INSNA(15,12);
11455 regN
= INSNA(19,16);
11457 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11463 IRTemp rNt
= newTemp(Ity_I32
);
11464 IRTemp rMt
= newTemp(Ity_I32
);
11465 IRTemp res_q
= newTemp(Ity_I32
);
11467 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11468 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11470 assign(res_q
, binop(Iop_QAdd16Ux2
, mkexpr(rNt
), mkexpr(rMt
)));
11472 putIRegT( regD
, mkexpr(res_q
), condT
);
11474 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11476 DIP("uqadd16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11482 /* ------------------- uqsax<c> <Rd>,<Rn>,<Rm> ------------------- */
11484 UInt regD
= 99, regN
= 99, regM
= 99;
11488 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
11489 regN
= INSNT0(3,0);
11490 regD
= INSNT1(11,8);
11491 regM
= INSNT1(3,0);
11492 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11496 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
11497 INSNA(11,8) == BITS4(1,1,1,1) &&
11498 INSNA(7,4) == BITS4(0,1,0,1)) {
11499 regD
= INSNA(15,12);
11500 regN
= INSNA(19,16);
11502 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11508 IRTemp irt_regN
= newTemp(Ity_I32
);
11509 IRTemp irt_regM
= newTemp(Ity_I32
);
11510 IRTemp irt_sum
= newTemp(Ity_I32
);
11511 IRTemp irt_diff
= newTemp(Ity_I32
);
11512 IRTemp irt_sum_res
= newTemp(Ity_I32
);
11513 IRTemp irt_diff_res
= newTemp(Ity_I32
);
11515 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11516 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11520 binop( Iop_Shr32
, mkexpr(irt_regN
), mkU8(16) ),
11522 binop(Iop_Shl32
, mkexpr(irt_regM
), mkU8(16)),
11524 armUnsignedSatQ( &irt_diff_res
, NULL
, irt_diff
, 0x10);
11529 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
11531 binop( Iop_Shr32
, mkexpr(irt_regM
), mkU8(16) )) );
11532 armUnsignedSatQ( &irt_sum_res
, NULL
, irt_sum
, 0x10 );
11534 IRExpr
* ire_result
= binop( Iop_Or32
,
11535 binop( Iop_Shl32
, mkexpr(irt_diff_res
),
11537 binop( Iop_And32
, mkexpr(irt_sum_res
),
11541 putIRegT( regD
, ire_result
, condT
);
11543 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11545 DIP( "uqsax%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
11551 /* ------------------- uqasx<c> <Rd>,<Rn>,<Rm> ------------------- */
11553 UInt regD
= 99, regN
= 99, regM
= 99;
11557 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
11558 regN
= INSNT0(3,0);
11559 regD
= INSNT1(11,8);
11560 regM
= INSNT1(3,0);
11561 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11565 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
11566 INSNA(11,8) == BITS4(1,1,1,1) &&
11567 INSNA(7,4) == BITS4(0,0,1,1)) {
11568 regD
= INSNA(15,12);
11569 regN
= INSNA(19,16);
11571 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11577 IRTemp irt_regN
= newTemp(Ity_I32
);
11578 IRTemp irt_regM
= newTemp(Ity_I32
);
11579 IRTemp irt_sum
= newTemp(Ity_I32
);
11580 IRTemp irt_diff
= newTemp(Ity_I32
);
11581 IRTemp irt_res_sum
= newTemp(Ity_I32
);
11582 IRTemp irt_res_diff
= newTemp(Ity_I32
);
11584 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11585 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11590 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
11592 binop( Iop_Shr32
, mkexpr(irt_regM
), mkU8(16) ) ) );
11593 armUnsignedSatQ( &irt_res_diff
, NULL
, irt_diff
, 0x10 );
11597 binop( Iop_Shr32
, mkexpr(irt_regN
), mkU8(16) ),
11599 binop( Iop_Shl32
, mkexpr(irt_regM
), mkU8(16) ),
11601 armUnsignedSatQ( &irt_res_sum
, NULL
, irt_sum
, 0x10 );
11605 binop( Iop_Shl32
, mkexpr(irt_res_sum
), mkU8(16) ),
11606 binop( Iop_And32
, mkexpr(irt_res_diff
), mkU32(0xFFFF) ) );
11609 putIRegT( regD
, ire_result
, condT
);
11611 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11613 DIP( "uqasx%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
11619 /* ------------------- usax<c> <Rd>,<Rn>,<Rm> ------------------- */
11621 UInt regD
= 99, regN
= 99, regM
= 99;
11625 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
11626 regN
= INSNT0(3,0);
11627 regD
= INSNT1(11,8);
11628 regM
= INSNT1(3,0);
11629 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11633 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
11634 INSNA(11,8) == BITS4(1,1,1,1) &&
11635 INSNA(7,4) == BITS4(0,1,0,1)) {
11636 regD
= INSNA(15,12);
11637 regN
= INSNA(19,16);
11639 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11645 IRTemp irt_regN
= newTemp(Ity_I32
);
11646 IRTemp irt_regM
= newTemp(Ity_I32
);
11647 IRTemp irt_sum
= newTemp(Ity_I32
);
11648 IRTemp irt_diff
= newTemp(Ity_I32
);
11650 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11651 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11656 unop( Iop_32to16
, mkexpr(irt_regN
) )
11658 binop( Iop_Shr32
, mkexpr(irt_regM
), mkU8(16) ) ) );
11662 binop( Iop_Shr32
, mkexpr(irt_regN
), mkU8(16) ),
11664 unop( Iop_32to16
, mkexpr(irt_regM
) )
11671 binop( Iop_Shl32
, mkexpr(irt_diff
), mkU8(16) ),
11672 binop( Iop_And32
, mkexpr(irt_sum
), mkU32(0xFFFF) ) );
11674 IRTemp ge10
= newTemp(Ity_I32
);
11675 assign( ge10
, IRExpr_ITE( binop( Iop_CmpLE32U
,
11676 mkU32(0x10000), mkexpr(irt_sum
) ),
11677 mkU32(1), mkU32(0) ) );
11678 put_GEFLAG32( 0, 0, mkexpr(ge10
), condT
);
11679 put_GEFLAG32( 1, 0, mkexpr(ge10
), condT
);
11681 IRTemp ge32
= newTemp(Ity_I32
);
11682 assign(ge32
, unop(Iop_Not32
, mkexpr(irt_diff
)));
11683 put_GEFLAG32( 2, 31, mkexpr(ge32
), condT
);
11684 put_GEFLAG32( 3, 31, mkexpr(ge32
), condT
);
11687 putIRegT( regD
, ire_result
, condT
);
11689 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11691 DIP( "usax%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
11697 /* ------------------- uasx<c> <Rd>,<Rn>,<Rm> ------------------- */
11699 UInt regD
= 99, regN
= 99, regM
= 99;
11703 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
11704 regN
= INSNT0(3,0);
11705 regD
= INSNT1(11,8);
11706 regM
= INSNT1(3,0);
11707 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11711 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
11712 INSNA(11,8) == BITS4(1,1,1,1) &&
11713 INSNA(7,4) == BITS4(0,0,1,1)) {
11714 regD
= INSNA(15,12);
11715 regN
= INSNA(19,16);
11717 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11723 IRTemp irt_regN
= newTemp(Ity_I32
);
11724 IRTemp irt_regM
= newTemp(Ity_I32
);
11725 IRTemp irt_sum
= newTemp(Ity_I32
);
11726 IRTemp irt_diff
= newTemp(Ity_I32
);
11728 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11729 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11734 unop( Iop_32to16
, mkexpr(irt_regN
) )
11736 binop( Iop_Shr32
, mkexpr(irt_regM
), mkU8(16) ) ) );
11740 binop( Iop_Shr32
, mkexpr(irt_regN
), mkU8(16) ),
11742 unop( Iop_32to16
, mkexpr(irt_regM
) )
11747 binop( Iop_Shl32
, mkexpr(irt_sum
), mkU8(16) ),
11748 binop( Iop_And32
, mkexpr(irt_diff
), mkU32(0xFFFF) ) );
11750 IRTemp ge10
= newTemp(Ity_I32
);
11751 assign(ge10
, unop(Iop_Not32
, mkexpr(irt_diff
)));
11752 put_GEFLAG32( 0, 31, mkexpr(ge10
), condT
);
11753 put_GEFLAG32( 1, 31, mkexpr(ge10
), condT
);
11755 IRTemp ge32
= newTemp(Ity_I32
);
11756 assign( ge32
, IRExpr_ITE( binop( Iop_CmpLE32U
,
11757 mkU32(0x10000), mkexpr(irt_sum
) ),
11758 mkU32(1), mkU32(0) ) );
11759 put_GEFLAG32( 2, 0, mkexpr(ge32
), condT
);
11760 put_GEFLAG32( 3, 0, mkexpr(ge32
), condT
);
11763 putIRegT( regD
, ire_result
, condT
);
11765 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11767 DIP( "uasx%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
11773 /* ------------------- ssax<c> <Rd>,<Rn>,<Rm> ------------------- */
11775 UInt regD
= 99, regN
= 99, regM
= 99;
11779 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
11780 regN
= INSNT0(3,0);
11781 regD
= INSNT1(11,8);
11782 regM
= INSNT1(3,0);
11783 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11787 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
11788 INSNA(11,8) == BITS4(1,1,1,1) &&
11789 INSNA(7,4) == BITS4(0,1,0,1)) {
11790 regD
= INSNA(15,12);
11791 regN
= INSNA(19,16);
11793 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11799 IRTemp irt_regN
= newTemp(Ity_I32
);
11800 IRTemp irt_regM
= newTemp(Ity_I32
);
11801 IRTemp irt_sum
= newTemp(Ity_I32
);
11802 IRTemp irt_diff
= newTemp(Ity_I32
);
11804 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11805 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11810 binop( Iop_Shl32
, mkexpr(irt_regN
), mkU8(16) ),
11812 binop( Iop_Sar32
, mkexpr(irt_regM
), mkU8(16) ) ) );
11816 binop( Iop_Sar32
, mkexpr(irt_regN
), mkU8(16) ),
11818 binop( Iop_Shl32
, mkexpr(irt_regM
), mkU8(16) ),
11823 binop( Iop_Shl32
, mkexpr(irt_diff
), mkU8(16) ),
11824 binop( Iop_And32
, mkexpr(irt_sum
), mkU32(0xFFFF) ) );
11826 IRTemp ge10
= newTemp(Ity_I32
);
11827 assign(ge10
, unop(Iop_Not32
, mkexpr(irt_sum
)));
11828 put_GEFLAG32( 0, 31, mkexpr(ge10
), condT
);
11829 put_GEFLAG32( 1, 31, mkexpr(ge10
), condT
);
11831 IRTemp ge32
= newTemp(Ity_I32
);
11832 assign(ge32
, unop(Iop_Not32
, mkexpr(irt_diff
)));
11833 put_GEFLAG32( 2, 31, mkexpr(ge32
), condT
);
11834 put_GEFLAG32( 3, 31, mkexpr(ge32
), condT
);
11837 putIRegT( regD
, ire_result
, condT
);
11839 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11841 DIP( "ssax%s r%u, r%u, r%u\n", nCC(conq
), regD
, regN
, regM
);
11847 /* ----------------- shsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
11849 UInt regD
= 99, regN
= 99, regM
= 99;
11853 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
11854 regN
= INSNT0(3,0);
11855 regD
= INSNT1(11,8);
11856 regM
= INSNT1(3,0);
11857 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11861 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
11862 INSNA(11,8) == BITS4(1,1,1,1) &&
11863 INSNA(7,4) == BITS4(1,1,1,1)) {
11864 regD
= INSNA(15,12);
11865 regN
= INSNA(19,16);
11867 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11873 IRTemp rNt
= newTemp(Ity_I32
);
11874 IRTemp rMt
= newTemp(Ity_I32
);
11875 IRTemp res_q
= newTemp(Ity_I32
);
11877 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11878 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11880 assign(res_q
, binop(Iop_HSub8Sx4
, mkexpr(rNt
), mkexpr(rMt
)));
11882 putIRegT( regD
, mkexpr(res_q
), condT
);
11884 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
11886 DIP("shsub8%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
11892 /* ----------------- sxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
11894 UInt regD
= 99, regN
= 99, regM
= 99, rotate
= 99;
11898 if (INSNT0(15,4) == 0xFA2 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
11899 regN
= INSNT0(3,0);
11900 regD
= INSNT1(11,8);
11901 regM
= INSNT1(3,0);
11902 rotate
= INSNT1(5,4);
11903 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11907 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
11908 INSNA(9,4) == BITS6(0,0,0,1,1,1) ) {
11909 regD
= INSNA(15,12);
11910 regN
= INSNA(19,16);
11912 rotate
= INSNA(11,10);
11913 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11919 IRTemp irt_regN
= newTemp(Ity_I32
);
11920 assign( irt_regN
, isT
? getIRegT(regN
) : getIRegA(regN
) );
11922 IRTemp irt_regM
= newTemp(Ity_I32
);
11923 assign( irt_regM
, isT
? getIRegT(regM
) : getIRegA(regM
) );
11925 IRTemp irt_rot
= newTemp(Ity_I32
);
11926 assign( irt_rot
, genROR32(irt_regM
, 8 * rotate
) );
11928 /* FIXME Maybe we can write this arithmetic in shorter form. */
11935 unop(Iop_32to8
, mkexpr(irt_rot
))))),
11936 mkU32(0x0000FFFF));
11950 mkU32(0xFFFF0000));
11953 = binop( Iop_Or32
, resHi
, resLo
);
11956 putIRegT( regD
, ire_result
, condT
);
11958 putIRegA( regD
, ire_result
, condT
, Ijk_Boring
);
11960 DIP( "sxtab16%s r%u, r%u, r%u, ROR #%u\n",
11961 nCC(conq
), regD
, regN
, regM
, 8 * rotate
);
11967 /* ----------------- shasx<c> <Rd>,<Rn>,<Rm> ------------------- */
11969 UInt regD
= 99, regN
= 99, regM
= 99;
11973 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
11974 regN
= INSNT0(3,0);
11975 regD
= INSNT1(11,8);
11976 regM
= INSNT1(3,0);
11977 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
11981 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
11982 INSNA(11,8) == BITS4(1,1,1,1) &&
11983 INSNA(7,4) == BITS4(0,0,1,1)) {
11984 regD
= INSNA(15,12);
11985 regN
= INSNA(19,16);
11987 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
11993 IRTemp rNt
= newTemp(Ity_I32
);
11994 IRTemp rMt
= newTemp(Ity_I32
);
11995 IRTemp irt_diff
= newTemp(Ity_I32
);
11996 IRTemp irt_sum
= newTemp(Ity_I32
);
11997 IRTemp res_q
= newTemp(Ity_I32
);
11999 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
12000 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
12012 mkexpr(rMt
), mkU8(16)
12024 mkexpr(rNt
), mkU8(16)
12029 unop(Iop_32to16
, mkexpr(rMt
)
12040 mkexpr(irt_diff
), mkU8(1)
12046 mkexpr(irt_sum
), mkU8(1)
12054 putIRegT( regD
, mkexpr(res_q
), condT
);
12056 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
12058 DIP("shasx%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
12064 /* ----------------- uhasx<c> <Rd>,<Rn>,<Rm> ------------------- */
12066 UInt regD
= 99, regN
= 99, regM
= 99;
12070 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
12071 regN
= INSNT0(3,0);
12072 regD
= INSNT1(11,8);
12073 regM
= INSNT1(3,0);
12074 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
12078 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
12079 INSNA(11,8) == BITS4(1,1,1,1) &&
12080 INSNA(7,4) == BITS4(0,0,1,1)) {
12081 regD
= INSNA(15,12);
12082 regN
= INSNA(19,16);
12084 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
12090 IRTemp rNt
= newTemp(Ity_I32
);
12091 IRTemp rMt
= newTemp(Ity_I32
);
12092 IRTemp irt_diff
= newTemp(Ity_I32
);
12093 IRTemp irt_sum
= newTemp(Ity_I32
);
12094 IRTemp res_q
= newTemp(Ity_I32
);
12096 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
12097 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
12109 mkexpr(rMt
), mkU8(16)
12121 mkexpr(rNt
), mkU8(16)
12126 unop(Iop_32to16
, mkexpr(rMt
)
12137 mkexpr(irt_diff
), mkU8(1)
12143 mkexpr(irt_sum
), mkU8(1)
12151 putIRegT( regD
, mkexpr(res_q
), condT
);
12153 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
12155 DIP("uhasx%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
12161 /* ----------------- shsax<c> <Rd>,<Rn>,<Rm> ------------------- */
12163 UInt regD
= 99, regN
= 99, regM
= 99;
12167 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
12168 regN
= INSNT0(3,0);
12169 regD
= INSNT1(11,8);
12170 regM
= INSNT1(3,0);
12171 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
12175 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
12176 INSNA(11,8) == BITS4(1,1,1,1) &&
12177 INSNA(7,4) == BITS4(0,1,0,1)) {
12178 regD
= INSNA(15,12);
12179 regN
= INSNA(19,16);
12181 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
12187 IRTemp rNt
= newTemp(Ity_I32
);
12188 IRTemp rMt
= newTemp(Ity_I32
);
12189 IRTemp irt_diff
= newTemp(Ity_I32
);
12190 IRTemp irt_sum
= newTemp(Ity_I32
);
12191 IRTemp res_q
= newTemp(Ity_I32
);
12193 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
12194 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
12206 mkexpr(rMt
), mkU8(16)
12218 mkexpr(rNt
), mkU8(16)
12223 unop(Iop_32to16
, mkexpr(rMt
)
12234 mkexpr(irt_sum
), mkU8(1)
12240 mkexpr(irt_diff
), mkU8(1)
12248 putIRegT( regD
, mkexpr(res_q
), condT
);
12250 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
12252 DIP("shsax%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
12258 /* ----------------- uhsax<c> <Rd>,<Rn>,<Rm> ------------------- */
12260 UInt regD
= 99, regN
= 99, regM
= 99;
12264 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
12265 regN
= INSNT0(3,0);
12266 regD
= INSNT1(11,8);
12267 regM
= INSNT1(3,0);
12268 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
12272 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
12273 INSNA(11,8) == BITS4(1,1,1,1) &&
12274 INSNA(7,4) == BITS4(0,1,0,1)) {
12275 regD
= INSNA(15,12);
12276 regN
= INSNA(19,16);
12278 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
12284 IRTemp rNt
= newTemp(Ity_I32
);
12285 IRTemp rMt
= newTemp(Ity_I32
);
12286 IRTemp irt_diff
= newTemp(Ity_I32
);
12287 IRTemp irt_sum
= newTemp(Ity_I32
);
12288 IRTemp res_q
= newTemp(Ity_I32
);
12290 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
12291 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
12303 mkexpr(rMt
), mkU8(16)
12315 mkexpr(rNt
), mkU8(16)
12320 unop(Iop_32to16
, mkexpr(rMt
)
12331 mkexpr(irt_sum
), mkU8(1)
12337 mkexpr(irt_diff
), mkU8(1)
12345 putIRegT( regD
, mkexpr(res_q
), condT
);
12347 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
12349 DIP("uhsax%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
12355 /* ----------------- shsub16<c> <Rd>,<Rn>,<Rm> ------------------- */
12357 UInt regD
= 99, regN
= 99, regM
= 99;
12361 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
12362 regN
= INSNT0(3,0);
12363 regD
= INSNT1(11,8);
12364 regM
= INSNT1(3,0);
12365 if (!isBadRegT(regD
) && !isBadRegT(regN
) && !isBadRegT(regM
))
12369 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
12370 INSNA(11,8) == BITS4(1,1,1,1) &&
12371 INSNA(7,4) == BITS4(0,1,1,1)) {
12372 regD
= INSNA(15,12);
12373 regN
= INSNA(19,16);
12375 if (regD
!= 15 && regN
!= 15 && regM
!= 15)
12381 IRTemp rNt
= newTemp(Ity_I32
);
12382 IRTemp rMt
= newTemp(Ity_I32
);
12383 IRTemp res_q
= newTemp(Ity_I32
);
12385 assign( rNt
, isT
? getIRegT(regN
) : getIRegA(regN
) );
12386 assign( rMt
, isT
? getIRegT(regM
) : getIRegA(regM
) );
12388 assign(res_q
, binop(Iop_HSub16Sx2
, mkexpr(rNt
), mkexpr(rMt
)));
12390 putIRegT( regD
, mkexpr(res_q
), condT
);
12392 putIRegA( regD
, mkexpr(res_q
), condT
, Ijk_Boring
);
12394 DIP("shsub16%s r%u, r%u, r%u\n", nCC(conq
),regD
,regN
,regM
);
12400 /* ----------------- smmls{r}<c> <Rd>,<Rn>,<Rm>,<Ra> ------------------- */
12402 UInt rD
= 99, rN
= 99, rM
= 99, rA
= 99;
12403 Bool round
= False
;
12407 if (INSNT0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
12408 && INSNT0(6,4) == BITS3(1,1,0)
12409 && INSNT1(7,5) == BITS3(0,0,0)) {
12410 round
= INSNT1(4,4);
12411 rA
= INSNT1(15,12);
12416 && !isBadRegT(rN
) && !isBadRegT(rM
) && !isBadRegT(rA
))
12420 if (INSNA(27,20) == BITS8(0,1,1,1,0,1,0,1)
12421 && INSNA(15,12) != BITS4(1,1,1,1)
12422 && (INSNA(7,4) & BITS4(1,1,0,1)) == BITS4(1,1,0,1)) {
12423 round
= INSNA(5,5);
12428 if (rD
!= 15 && rM
!= 15 && rN
!= 15)
12433 IRTemp irt_rA
= newTemp(Ity_I32
);
12434 IRTemp irt_rN
= newTemp(Ity_I32
);
12435 IRTemp irt_rM
= newTemp(Ity_I32
);
12436 assign( irt_rA
, isT
? getIRegT(rA
) : getIRegA(rA
) );
12437 assign( irt_rN
, isT
? getIRegT(rN
) : getIRegA(rN
) );
12438 assign( irt_rM
, isT
? getIRegT(rM
) : getIRegA(rM
) );
12440 = unop(Iop_64HIto32
,
12443 binop(Iop_32HLto64
, mkexpr(irt_rA
), mkU32(0)),
12444 binop(Iop_MullS32
, mkexpr(irt_rN
), mkexpr(irt_rM
))),
12445 mkU64(round
? 0x80000000ULL
: 0ULL)));
12447 putIRegT( rD
, res
, condT
);
12449 putIRegA(rD
, res
, condT
, Ijk_Boring
);
12450 DIP("smmls%s%s r%u, r%u, r%u, r%u\n",
12451 round
? "r" : "", nCC(conq
), rD
, rN
, rM
, rA
);
12457 /* -------------- smlald{x}<c> <RdLo>,<RdHi>,<Rn>,<Rm> ---------------- */
12459 UInt rN
= 99, rDlo
= 99, rDhi
= 99, rM
= 99;
12460 Bool m_swap
= False
;
12464 if (INSNT0(15,4) == 0xFBC &&
12465 (INSNT1(7,4) & BITS4(1,1,1,0)) == BITS4(1,1,0,0)) {
12467 rDlo
= INSNT1(15,12);
12468 rDhi
= INSNT1(11,8);
12470 m_swap
= (INSNT1(4,4) & 1) == 1;
12471 if (!isBadRegT(rDlo
) && !isBadRegT(rDhi
) && !isBadRegT(rN
)
12472 && !isBadRegT(rM
) && rDhi
!= rDlo
)
12476 if (INSNA(27,20) == BITS8(0,1,1,1,0,1,0,0)
12477 && (INSNA(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
12479 rDlo
= INSNA(15,12);
12480 rDhi
= INSNA(19,16);
12482 m_swap
= ( INSNA(5,5) & 1 ) == 1;
12483 if (rDlo
!= 15 && rDhi
!= 15
12484 && rN
!= 15 && rM
!= 15 && rDlo
!= rDhi
)
12490 IRTemp irt_rM
= newTemp(Ity_I32
);
12491 IRTemp irt_rN
= newTemp(Ity_I32
);
12492 IRTemp irt_rDhi
= newTemp(Ity_I32
);
12493 IRTemp irt_rDlo
= newTemp(Ity_I32
);
12494 IRTemp op_2
= newTemp(Ity_I32
);
12495 IRTemp pr_1
= newTemp(Ity_I64
);
12496 IRTemp pr_2
= newTemp(Ity_I64
);
12497 IRTemp result
= newTemp(Ity_I64
);
12498 IRTemp resHi
= newTemp(Ity_I32
);
12499 IRTemp resLo
= newTemp(Ity_I32
);
12500 assign( irt_rM
, isT
? getIRegT(rM
) : getIRegA(rM
));
12501 assign( irt_rN
, isT
? getIRegT(rN
) : getIRegA(rN
));
12502 assign( irt_rDhi
, isT
? getIRegT(rDhi
) : getIRegA(rDhi
));
12503 assign( irt_rDlo
, isT
? getIRegT(rDlo
) : getIRegA(rDlo
));
12504 assign( op_2
, genROR32(irt_rM
, m_swap
? 16 : 0) );
12505 assign( pr_1
, binop(Iop_MullS32
,
12507 unop(Iop_32to16
, mkexpr(irt_rN
))
12510 unop(Iop_32to16
, mkexpr(op_2
))
12514 assign( pr_2
, binop(Iop_MullS32
,
12515 binop(Iop_Sar32
, mkexpr(irt_rN
), mkU8(16)),
12516 binop(Iop_Sar32
, mkexpr(op_2
), mkU8(16))
12519 assign( result
, binop(Iop_Add64
,
12524 binop(Iop_32HLto64
,
12530 assign( resHi
, unop(Iop_64HIto32
, mkexpr(result
)) );
12531 assign( resLo
, unop(Iop_64to32
, mkexpr(result
)) );
12533 putIRegT( rDhi
, mkexpr(resHi
), condT
);
12534 putIRegT( rDlo
, mkexpr(resLo
), condT
);
12536 putIRegA( rDhi
, mkexpr(resHi
), condT
, Ijk_Boring
);
12537 putIRegA( rDlo
, mkexpr(resLo
), condT
, Ijk_Boring
);
12539 DIP("smlald%c%s r%u, r%u, r%u, r%u\n",
12540 m_swap
? 'x' : ' ', nCC(conq
), rDlo
, rDhi
, rN
, rM
);
12546 /* -------------- smlsld{x}<c> <RdLo>,<RdHi>,<Rn>,<Rm> ---------------- */
12548 UInt rN
= 99, rDlo
= 99, rDhi
= 99, rM
= 99;
12549 Bool m_swap
= False
;
12553 if ((INSNT0(15,4) == 0xFBD &&
12554 (INSNT1(7,4) & BITS4(1,1,1,0)) == BITS4(1,1,0,0))) {
12556 rDlo
= INSNT1(15,12);
12557 rDhi
= INSNT1(11,8);
12559 m_swap
= (INSNT1(4,4) & 1) == 1;
12560 if (!isBadRegT(rDlo
) && !isBadRegT(rDhi
) && !isBadRegT(rN
) &&
12561 !isBadRegT(rM
) && rDhi
!= rDlo
)
12565 if (INSNA(27,20) == BITS8(0,1,1,1,0,1,0,0) &&
12566 (INSNA(7,4) & BITS4(1,1,0,1)) == BITS4(0,1,0,1)) {
12568 rDlo
= INSNA(15,12);
12569 rDhi
= INSNA(19,16);
12571 m_swap
= (INSNA(5,5) & 1) == 1;
12572 if (rDlo
!= 15 && rDhi
!= 15 &&
12573 rN
!= 15 && rM
!= 15 && rDlo
!= rDhi
)
12578 IRTemp irt_rM
= newTemp(Ity_I32
);
12579 IRTemp irt_rN
= newTemp(Ity_I32
);
12580 IRTemp irt_rDhi
= newTemp(Ity_I32
);
12581 IRTemp irt_rDlo
= newTemp(Ity_I32
);
12582 IRTemp op_2
= newTemp(Ity_I32
);
12583 IRTemp pr_1
= newTemp(Ity_I64
);
12584 IRTemp pr_2
= newTemp(Ity_I64
);
12585 IRTemp result
= newTemp(Ity_I64
);
12586 IRTemp resHi
= newTemp(Ity_I32
);
12587 IRTemp resLo
= newTemp(Ity_I32
);
12588 assign( irt_rM
, isT
? getIRegT(rM
) : getIRegA(rM
) );
12589 assign( irt_rN
, isT
? getIRegT(rN
) : getIRegA(rN
) );
12590 assign( irt_rDhi
, isT
? getIRegT(rDhi
) : getIRegA(rDhi
) );
12591 assign( irt_rDlo
, isT
? getIRegT(rDlo
) : getIRegA(rDlo
) );
12592 assign( op_2
, genROR32(irt_rM
, m_swap
? 16 : 0) );
12593 assign( pr_1
, binop(Iop_MullS32
,
12595 unop(Iop_32to16
, mkexpr(irt_rN
))
12598 unop(Iop_32to16
, mkexpr(op_2
))
12602 assign( pr_2
, binop(Iop_MullS32
,
12603 binop(Iop_Sar32
, mkexpr(irt_rN
), mkU8(16)),
12604 binop(Iop_Sar32
, mkexpr(op_2
), mkU8(16))
12607 assign( result
, binop(Iop_Add64
,
12612 binop(Iop_32HLto64
,
12618 assign( resHi
, unop(Iop_64HIto32
, mkexpr(result
)) );
12619 assign( resLo
, unop(Iop_64to32
, mkexpr(result
)) );
12621 putIRegT( rDhi
, mkexpr(resHi
), condT
);
12622 putIRegT( rDlo
, mkexpr(resLo
), condT
);
12624 putIRegA( rDhi
, mkexpr(resHi
), condT
, Ijk_Boring
);
12625 putIRegA( rDlo
, mkexpr(resLo
), condT
, Ijk_Boring
);
12627 DIP("smlsld%c%s r%u, r%u, r%u, r%u\n",
12628 m_swap
? 'x' : ' ', nCC(conq
), rDlo
, rDhi
, rN
, rM
);
12634 /* ---------- Doesn't match anything. ---------- */
12643 /*------------------------------------------------------------*/
12644 /*--- V8 instructions ---*/
12645 /*------------------------------------------------------------*/
12647 /* Break a V128-bit value up into four 32-bit ints. */
12649 static void breakupV128to32s ( IRTemp t128
,
12651 IRTemp
* t3
, IRTemp
* t2
,
12652 IRTemp
* t1
, IRTemp
* t0
)
12654 IRTemp hi64
= newTemp(Ity_I64
);
12655 IRTemp lo64
= newTemp(Ity_I64
);
12656 assign( hi64
, unop(Iop_V128HIto64
, mkexpr(t128
)) );
12657 assign( lo64
, unop(Iop_V128to64
, mkexpr(t128
)) );
12659 vassert(t0
&& *t0
== IRTemp_INVALID
);
12660 vassert(t1
&& *t1
== IRTemp_INVALID
);
12661 vassert(t2
&& *t2
== IRTemp_INVALID
);
12662 vassert(t3
&& *t3
== IRTemp_INVALID
);
12664 *t0
= newTemp(Ity_I32
);
12665 *t1
= newTemp(Ity_I32
);
12666 *t2
= newTemp(Ity_I32
);
12667 *t3
= newTemp(Ity_I32
);
12668 assign( *t0
, unop(Iop_64to32
, mkexpr(lo64
)) );
12669 assign( *t1
, unop(Iop_64HIto32
, mkexpr(lo64
)) );
12670 assign( *t2
, unop(Iop_64to32
, mkexpr(hi64
)) );
12671 assign( *t3
, unop(Iop_64HIto32
, mkexpr(hi64
)) );
12675 /* Both ARM and Thumb */
12677 /* Translate a V8 instruction. If successful, returns True and *dres
12678 may or may not be updated. If unsuccessful, returns False and
12679 doesn't change *dres nor create any IR.
12681 The Thumb and ARM encodings are potentially different. In both
12682 ARM and Thumb mode, the caller must pass the entire 32 bits of
12683 the instruction. Callers may pass any instruction; this function
12684 ignores anything it doesn't recognise.
12686 Caller must supply an IRTemp 'condT' holding the gating condition,
12687 or IRTemp_INVALID indicating the insn is always executed.
12689 If we are decoding an ARM instruction which is in the NV space
12690 then it is expected that condT will be IRTemp_INVALID, and that is
12691 asserted for. That condition is ensured by the logic near the top
12692 of disInstr_ARM_WRK, that sets up condT.
12694 When decoding for Thumb, the caller must pass the ITState pre/post
12695 this instruction, so that we can generate a SIGILL in the cases where
12696 the instruction may not be in an IT block. When decoding for ARM,
12697 both of these must be IRTemp_INVALID.
12699 Finally, the caller must indicate whether this occurs in ARM or in
12702 static Bool
decode_V8_instruction (
12703 /*MOD*/DisResult
* dres
,
12707 IRTemp old_itstate
,
12711 # define INSN(_bMax,_bMin) SLICE_UInt(insnv8, (_bMax), (_bMin))
12714 vassert(old_itstate
!= IRTemp_INVALID
);
12715 vassert(new_itstate
!= IRTemp_INVALID
);
12717 vassert(old_itstate
== IRTemp_INVALID
);
12718 vassert(new_itstate
== IRTemp_INVALID
);
12721 /* ARMCondcode 'conq' is only used for debug printing and for no other
12722 purpose. For ARM, this is simply the top 4 bits of the instruction.
12723 For Thumb, the condition is not (really) known until run time, and so
12724 we set it to ARMCondAL in order that printing of these instructions
12725 does not show any condition. */
12730 conq
= (ARMCondcode
)INSN(31,28);
12731 if (conq
== ARMCondNV
|| conq
== ARMCondAL
) {
12732 vassert(condT
== IRTemp_INVALID
);
12734 vassert(condT
!= IRTemp_INVALID
);
12736 vassert(conq
>= ARMCondEQ
&& conq
<= ARMCondNV
);
12739 /* ----------- {AESD, AESE, AESMC, AESIMC}.8 q_q ----------- */
12740 /* 31 27 23 21 19 17 15 11 7 3
12741 T1: 1111 1111 1 D 11 sz 00 d 0011 00 M 0 m AESE Qd, Qm
12742 A1: 1111 0011 1 D 11 sz 00 d 0011 00 M 0 m AESE Qd, Qm
12744 T1: 1111 1111 1 D 11 sz 00 d 0011 01 M 0 m AESD Qd, Qm
12745 A1: 1111 0011 1 D 11 sz 00 d 0011 01 M 0 m AESD Qd, Qm
12747 T1: 1111 1111 1 D 11 sz 00 d 0011 10 M 0 m AESMC Qd, Qm
12748 A1: 1111 0011 1 D 11 sz 00 d 0011 10 M 0 m AESMC Qd, Qm
12750 T1: 1111 1111 1 D 11 sz 00 d 0011 11 M 0 m AESIMC Qd, Qm
12751 A1: 1111 0011 1 D 11 sz 00 d 0011 11 M 0 m AESIMC Qd, Qm
12754 ARM encoding is in NV space.
12755 In Thumb mode, we must not be in an IT block.
12758 UInt regD
= 99, regM
= 99, opc
= 4/*invalid*/;
12761 UInt high9
= isT
? BITS9(1,1,1,1,1,1,1,1,1) : BITS9(1,1,1,1,0,0,1,1,1);
12762 if (INSN(31,23) == high9
&& INSN(21,16) == BITS6(1,1,0,0,0,0)
12763 && INSN(11,8) == BITS4(0,0,1,1) && INSN(4,4) == 0) {
12764 UInt bitD
= INSN(22,22);
12765 UInt fldD
= INSN(15,12);
12766 UInt bitM
= INSN(5,5);
12767 UInt fldM
= INSN(3,0);
12769 regD
= (bitD
<< 4) | fldD
;
12770 regM
= (bitM
<< 4) | fldM
;
12772 if ((regD
& 1) == 1 || (regM
& 1) == 1)
12777 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
12779 /* In ARM mode, this is statically unconditional. In Thumb mode,
12780 this must be dynamically unconditional, and we've SIGILLd if not.
12781 In either case we can create unconditional IR. */
12782 IRTemp op1
= newTemp(Ity_V128
);
12783 IRTemp op2
= newTemp(Ity_V128
);
12784 IRTemp src
= newTemp(Ity_V128
);
12785 IRTemp res
= newTemp(Ity_V128
);
12786 assign(op1
, getQReg(regD
>> 1));
12787 assign(op2
, getQReg(regM
>> 1));
12788 assign(src
, opc
== BITS2(0,0) || opc
== BITS2(0,1)
12789 ? binop(Iop_XorV128
, mkexpr(op1
), mkexpr(op2
))
12793 = { &armg_dirtyhelper_AESE
, &armg_dirtyhelper_AESD
,
12794 &armg_dirtyhelper_AESMC
, &armg_dirtyhelper_AESIMC
};
12795 const HChar
* hNames
[4]
12796 = { "armg_dirtyhelper_AESE", "armg_dirtyhelper_AESD",
12797 "armg_dirtyhelper_AESMC", "armg_dirtyhelper_AESIMC" };
12798 const HChar
* iNames
[4]
12799 = { "aese", "aesd", "aesmc", "aesimc" };
12801 vassert(opc
>= 0 && opc
<= 3);
12802 void* helper
= helpers
[opc
];
12803 const HChar
* hname
= hNames
[opc
];
12805 IRTemp w32_3
, w32_2
, w32_1
, w32_0
;
12806 w32_3
= w32_2
= w32_1
= w32_0
= IRTemp_INVALID
;
12807 breakupV128to32s( src
, &w32_3
, &w32_2
, &w32_1
, &w32_0
);
12810 = unsafeIRDirty_1_N( res
, 0/*regparms*/, hname
, helper
,
12813 mkexpr(w32_3
), mkexpr(w32_2
),
12814 mkexpr(w32_1
), mkexpr(w32_0
)) );
12815 stmt(IRStmt_Dirty(di
));
12817 putQReg(regD
>> 1, mkexpr(res
), IRTemp_INVALID
);
12818 DIP("%s.8 q%u, q%u\n", iNames
[opc
], regD
>> 1, regM
>> 1);
12824 /* ----------- SHA 3-reg insns q_q_q ----------- */
12826 31 27 23 19 15 11 7 3
12827 T1: 1110 1111 0 D 00 n d 1100 N Q M 0 m SHA1C Qd, Qn, Qm ix=0
12828 A1: 1111 0010 ----------------------------
12830 T1: 1110 1111 0 D 01 n d 1100 N Q M 0 m SHA1P Qd, Qn, Qm ix=1
12831 A1: 1111 0010 ----------------------------
12833 T1: 1110 1111 0 D 10 n d 1100 N Q M 0 m SHA1M Qd, Qn, Qm ix=2
12834 A1: 1111 0010 ----------------------------
12836 T1: 1110 1111 0 D 11 n d 1100 N Q M 0 m SHA1SU0 Qd, Qn, Qm ix=3
12837 A1: 1111 0010 ----------------------------
12838 (that's a complete set of 4, based on insn[21,20])
12840 T1: 1111 1111 0 D 00 n d 1100 N Q M 0 m SHA256H Qd, Qn, Qm ix=4
12841 A1: 1111 0011 ----------------------------
12843 T1: 1111 1111 0 D 01 n d 1100 N Q M 0 m SHA256H2 Qd, Qn, Qm ix=5
12844 A1: 1111 0011 ----------------------------
12846 T1: 1111 1111 0 D 10 n d 1100 N Q M 0 m SHA256SU1 Qd, Qn, Qm ix=6
12847 A1: 1111 0011 ----------------------------
12848 (3/4 of a complete set of 4, based on insn[21,20])
12850 Q must be 1. Same comments about conditionalisation as for the AES
12854 UInt ix
= 8; /* invalid */
12857 UInt hi9_sha1
= isT
? BITS9(1,1,1,0,1,1,1,1,0)
12858 : BITS9(1,1,1,1,0,0,1,0,0);
12859 UInt hi9_sha256
= isT
? BITS9(1,1,1,1,1,1,1,1,0)
12860 : BITS9(1,1,1,1,0,0,1,1,0);
12861 if ((INSN(31,23) == hi9_sha1
|| INSN(31,23) == hi9_sha256
)
12862 && INSN(11,8) == BITS4(1,1,0,0)
12863 && INSN(6,6) == 1 && INSN(4,4) == 0) {
12865 if (INSN(31,23) == hi9_sha256
)
12871 UInt regN
= (INSN(7,7) << 4) | INSN(19,16);
12872 UInt regD
= (INSN(22,22) << 4) | INSN(15,12);
12873 UInt regM
= (INSN(5,5) << 4) | INSN(3,0);
12874 if ((regD
& 1) == 1 || (regM
& 1) == 1 || (regN
& 1) == 1)
12878 vassert(ix
>= 0 && ix
< 7);
12879 const HChar
* inames
[7]
12880 = { "sha1c", "sha1p", "sha1m", "sha1su0",
12881 "sha256h", "sha256h2", "sha256su1" };
12882 void(*helpers
[7])(V128
*,UInt
,UInt
,UInt
,UInt
,UInt
,UInt
,
12883 UInt
,UInt
,UInt
,UInt
,UInt
,UInt
)
12884 = { &armg_dirtyhelper_SHA1C
, &armg_dirtyhelper_SHA1P
,
12885 &armg_dirtyhelper_SHA1M
, &armg_dirtyhelper_SHA1SU0
,
12886 &armg_dirtyhelper_SHA256H
, &armg_dirtyhelper_SHA256H2
,
12887 &armg_dirtyhelper_SHA256SU1
};
12888 const HChar
* hnames
[7]
12889 = { "armg_dirtyhelper_SHA1C", "armg_dirtyhelper_SHA1P",
12890 "armg_dirtyhelper_SHA1M", "armg_dirtyhelper_SHA1SU0",
12891 "armg_dirtyhelper_SHA256H", "armg_dirtyhelper_SHA256H2",
12892 "armg_dirtyhelper_SHA256SU1" };
12894 /* This is a really lame way to implement this, even worse than
12895 the arm64 version. But at least it works. */
12898 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
12901 IRTemp vD
= newTemp(Ity_V128
);
12902 IRTemp vN
= newTemp(Ity_V128
);
12903 IRTemp vM
= newTemp(Ity_V128
);
12904 assign(vD
, getQReg(regD
>> 1));
12905 assign(vN
, getQReg(regN
>> 1));
12906 assign(vM
, getQReg(regM
>> 1));
12908 IRTemp d32_3
, d32_2
, d32_1
, d32_0
;
12909 d32_3
= d32_2
= d32_1
= d32_0
= IRTemp_INVALID
;
12910 breakupV128to32s( vD
, &d32_3
, &d32_2
, &d32_1
, &d32_0
);
12912 IRTemp n32_3_pre
, n32_2_pre
, n32_1_pre
, n32_0_pre
;
12913 n32_3_pre
= n32_2_pre
= n32_1_pre
= n32_0_pre
= IRTemp_INVALID
;
12914 breakupV128to32s( vN
, &n32_3_pre
, &n32_2_pre
, &n32_1_pre
, &n32_0_pre
);
12916 IRTemp m32_3
, m32_2
, m32_1
, m32_0
;
12917 m32_3
= m32_2
= m32_1
= m32_0
= IRTemp_INVALID
;
12918 breakupV128to32s( vM
, &m32_3
, &m32_2
, &m32_1
, &m32_0
);
12920 IRTemp n32_3
= newTemp(Ity_I32
);
12921 IRTemp n32_2
= newTemp(Ity_I32
);
12922 IRTemp n32_1
= newTemp(Ity_I32
);
12923 IRTemp n32_0
= newTemp(Ity_I32
);
12925 /* Mask off any bits of the N register operand that aren't actually
12926 needed, so that Memcheck doesn't complain unnecessarily. */
12928 case 0: case 1: case 2:
12929 assign(n32_3
, mkU32(0));
12930 assign(n32_2
, mkU32(0));
12931 assign(n32_1
, mkU32(0));
12932 assign(n32_0
, mkexpr(n32_0_pre
));
12934 case 3: case 4: case 5: case 6:
12935 assign(n32_3
, mkexpr(n32_3_pre
));
12936 assign(n32_2
, mkexpr(n32_2_pre
));
12937 assign(n32_1
, mkexpr(n32_1_pre
));
12938 assign(n32_0
, mkexpr(n32_0_pre
));
12947 mkexpr(d32_3
), mkexpr(d32_2
), mkexpr(d32_1
), mkexpr(d32_0
),
12948 mkexpr(n32_3
), mkexpr(n32_2
), mkexpr(n32_1
), mkexpr(n32_0
),
12949 mkexpr(m32_3
), mkexpr(m32_2
), mkexpr(m32_1
), mkexpr(m32_0
)
12952 IRTemp res
= newTemp(Ity_V128
);
12953 IRDirty
* di
= unsafeIRDirty_1_N( res
, 0/*regparms*/,
12954 hnames
[ix
], helpers
[ix
], argvec
);
12955 stmt(IRStmt_Dirty(di
));
12956 putQReg(regD
>> 1, mkexpr(res
), IRTemp_INVALID
);
12958 DIP("%s.8 q%u, q%u, q%u\n",
12959 inames
[ix
], regD
>> 1, regN
>> 1, regM
>> 1);
12965 /* ----------- SHA1SU1, SHA256SU0 ----------- */
12967 31 27 23 21 19 15 11 7 3
12968 T1: 1111 1111 1 D 11 1010 d 0011 10 M 0 m SHA1SU1 Qd, Qm
12969 A1: 1111 0011 ----------------------------
12971 T1: 1111 1111 1 D 11 1010 d 0011 11 M 0 m SHA256SU0 Qd, Qm
12972 A1: 1111 0011 ----------------------------
12974 Same comments about conditionalisation as for the AES group above apply.
12979 UInt hi9
= isT
? BITS9(1,1,1,1,1,1,1,1,1) : BITS9(1,1,1,1,0,0,1,1,1);
12980 if (INSN(31,23) == hi9
&& INSN(21,16) == BITS6(1,1,1,0,1,0)
12981 && INSN(11,7) == BITS5(0,0,1,1,1) && INSN(4,4) == 0) {
12985 UInt regD
= (INSN(22,22) << 4) | INSN(15,12);
12986 UInt regM
= (INSN(5,5) << 4) | INSN(3,0);
12987 if ((regD
& 1) == 1 || (regM
& 1) == 1)
12990 Bool is_1SU1
= INSN(6,6) == 0;
12994 = is_1SU1
? "sha1su1" : "sha256su0";
12995 void (*helper
)(V128
*,UInt
,UInt
,UInt
,UInt
,UInt
,UInt
,UInt
,UInt
)
12996 = is_1SU1
? &armg_dirtyhelper_SHA1SU1
12997 : *armg_dirtyhelper_SHA256SU0
;
12999 = is_1SU1
? "armg_dirtyhelper_SHA1SU1"
13000 : "armg_dirtyhelper_SHA256SU0";
13003 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13006 IRTemp vD
= newTemp(Ity_V128
);
13007 IRTemp vM
= newTemp(Ity_V128
);
13008 assign(vD
, getQReg(regD
>> 1));
13009 assign(vM
, getQReg(regM
>> 1));
13011 IRTemp d32_3
, d32_2
, d32_1
, d32_0
;
13012 d32_3
= d32_2
= d32_1
= d32_0
= IRTemp_INVALID
;
13013 breakupV128to32s( vD
, &d32_3
, &d32_2
, &d32_1
, &d32_0
);
13015 IRTemp m32_3
, m32_2
, m32_1
, m32_0
;
13016 m32_3
= m32_2
= m32_1
= m32_0
= IRTemp_INVALID
;
13017 breakupV128to32s( vM
, &m32_3
, &m32_2
, &m32_1
, &m32_0
);
13022 mkexpr(d32_3
), mkexpr(d32_2
), mkexpr(d32_1
), mkexpr(d32_0
),
13023 mkexpr(m32_3
), mkexpr(m32_2
), mkexpr(m32_1
), mkexpr(m32_0
)
13026 IRTemp res
= newTemp(Ity_V128
);
13027 IRDirty
* di
= unsafeIRDirty_1_N( res
, 0/*regparms*/,
13028 hname
, helper
, argvec
);
13029 stmt(IRStmt_Dirty(di
));
13030 putQReg(regD
>> 1, mkexpr(res
), IRTemp_INVALID
);
13032 DIP("%s.8 q%u, q%u\n", iname
, regD
>> 1, regM
>> 1);
13038 /* ----------- SHA1H ----------- */
13040 31 27 23 21 19 15 11 7 3
13041 T1: 1111 1111 1 D 11 1001 d 0010 11 M 0 m SHA1H Qd, Qm
13042 A1: 1111 0011 ----------------------------
13044 Same comments about conditionalisation as for the AES group above apply.
13049 UInt hi9
= isT
? BITS9(1,1,1,1,1,1,1,1,1) : BITS9(1,1,1,1,0,0,1,1,1);
13050 if (INSN(31,23) == hi9
&& INSN(21,16) == BITS6(1,1,1,0,0,1)
13051 && INSN(11,6) == BITS6(0,0,1,0,1,1) && INSN(4,4) == 0) {
13055 UInt regD
= (INSN(22,22) << 4) | INSN(15,12);
13056 UInt regM
= (INSN(5,5) << 4) | INSN(3,0);
13057 if ((regD
& 1) == 1 || (regM
& 1) == 1)
13061 const HChar
* iname
= "sha1h";
13062 void (*helper
)(V128
*,UInt
,UInt
,UInt
,UInt
) = &armg_dirtyhelper_SHA1H
;
13063 const HChar
* hname
= "armg_dirtyhelper_SHA1H";
13066 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13069 IRTemp vM
= newTemp(Ity_V128
);
13070 assign(vM
, getQReg(regM
>> 1));
13072 IRTemp m32_3
, m32_2
, m32_1
, m32_0
;
13073 m32_3
= m32_2
= m32_1
= m32_0
= IRTemp_INVALID
;
13074 breakupV128to32s( vM
, &m32_3
, &m32_2
, &m32_1
, &m32_0
);
13075 /* m32_3, m32_2, m32_1 are just abandoned. No harm; iropt will
13078 IRExpr
* zero
= mkU32(0);
13079 IRExpr
** argvec
= mkIRExprVec_5(IRExpr_VECRET(),
13080 zero
, zero
, zero
, mkexpr(m32_0
));
13082 IRTemp res
= newTemp(Ity_V128
);
13083 IRDirty
* di
= unsafeIRDirty_1_N( res
, 0/*regparms*/,
13084 hname
, helper
, argvec
);
13085 stmt(IRStmt_Dirty(di
));
13086 putQReg(regD
>> 1, mkexpr(res
), IRTemp_INVALID
);
13088 DIP("%s.8 q%u, q%u\n", iname
, regD
>> 1, regM
>> 1);
13094 /* ----------- VMULL.P64 ----------- */
13096 31 27 23 21 19 15 11 7 3
13097 T2: 1110 1111 1 D 10 n d 1110 N 0 M 0 m
13098 A2: 1111 0010 -------------------------
13100 The ARM documentation is pretty difficult to follow here.
13101 Same comments about conditionalisation as for the AES group above apply.
13106 UInt hi9
= isT
? BITS9(1,1,1,0,1,1,1,1,1) : BITS9(1,1,1,1,0,0,1,0,1);
13107 if (INSN(31,23) == hi9
&& INSN(21,20) == BITS2(1,0)
13108 && INSN(11,8) == BITS4(1,1,1,0)
13109 && INSN(6,6) == 0 && INSN(4,4) == 0) {
13113 UInt regN
= (INSN(7,7) << 4) | INSN(19,16);
13114 UInt regD
= (INSN(22,22) << 4) | INSN(15,12);
13115 UInt regM
= (INSN(5,5) << 4) | INSN(3,0);
13117 if ((regD
& 1) == 1)
13121 const HChar
* iname
= "vmull";
13122 void (*helper
)(V128
*,UInt
,UInt
,UInt
,UInt
) = &armg_dirtyhelper_VMULLP64
;
13123 const HChar
* hname
= "armg_dirtyhelper_VMULLP64";
13126 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13129 IRTemp srcN
= newTemp(Ity_I64
);
13130 IRTemp srcM
= newTemp(Ity_I64
);
13131 assign(srcN
, getDRegI64(regN
));
13132 assign(srcM
, getDRegI64(regM
));
13134 IRExpr
** argvec
= mkIRExprVec_5(IRExpr_VECRET(),
13135 unop(Iop_64HIto32
, mkexpr(srcN
)),
13136 unop(Iop_64to32
, mkexpr(srcN
)),
13137 unop(Iop_64HIto32
, mkexpr(srcM
)),
13138 unop(Iop_64to32
, mkexpr(srcM
)));
13140 IRTemp res
= newTemp(Ity_V128
);
13141 IRDirty
* di
= unsafeIRDirty_1_N( res
, 0/*regparms*/,
13142 hname
, helper
, argvec
);
13143 stmt(IRStmt_Dirty(di
));
13144 putQReg(regD
>> 1, mkexpr(res
), IRTemp_INVALID
);
13146 DIP("%s.p64 q%u, q%u, w%u\n", iname
, regD
>> 1, regN
, regM
);
13152 /* ----------- LDA{,B,H}, STL{,B,H} ----------- */
13153 /* 31 27 23 19 15 11 7 3
13154 A1: cond 0001 1001 n t 1100 1001 1111 LDA Rt, [Rn]
13155 A1: cond 0001 1111 n t 1100 1001 1111 LDAH Rt, [Rn]
13156 A1: cond 0001 1101 n t 1100 1001 1111 LDAB Rt, [Rn]
13158 A1: cond 0001 1000 n 1111 1100 1001 t STL Rt, [Rn]
13159 A1: cond 0001 1110 n 1111 1100 1001 t STLH Rt, [Rn]
13160 A1: cond 0001 1100 n 1111 1100 1001 t STLB Rt, [Rn]
13162 T1: 1110 1000 1101 n t 1111 1010 1111 LDA Rt, [Rn]
13163 T1: 1110 1000 1101 n t 1111 1001 1111 LDAH Rt, [Rn]
13164 T1: 1110 1000 1101 n t 1111 1000 1111 LDAB Rt, [Rn]
13166 T1: 1110 1000 1100 n t 1111 1010 1111 STL Rt, [Rn]
13167 T1: 1110 1000 1100 n t 1111 1001 1111 STLH Rt, [Rn]
13168 T1: 1110 1000 1100 n t 1111 1000 1111 STLB Rt, [Rn]
13171 UInt nn
= 16; // invalid
13172 UInt tt
= 16; // invalid
13173 UInt szBlg2
= 4; // invalid
13174 Bool isLoad
= False
;
13177 if (INSN(31,21) == BITS11(1,1,1,0,1,0,0,0,1,1,0)
13178 && INSN(11,6) == BITS6(1,1,1,1,1,0)
13179 && INSN(3,0) == BITS4(1,1,1,1)) {
13182 isLoad
= INSN(20,20) == 1;
13183 szBlg2
= INSN(5,4); // 00:B 01:H 10:W 11:invalid
13184 gate
= szBlg2
!= BITS2(1,1) && tt
!= 15 && nn
!= 15;
13187 if (INSN(27,23) == BITS5(0,0,0,1,1) && INSN(20,20) == 1
13188 && INSN(11,0) == BITS12(1,1,0,0,1,0,0,1,1,1,1,1)) {
13192 szBlg2
= INSN(22,21); // 10:B 11:H 00:W 01:invalid
13193 gate
= szBlg2
!= BITS2(0,1) && tt
!= 15 && nn
!= 15;
13196 if (INSN(27,23) == BITS5(0,0,0,1,1) && INSN(20,20) == 0
13197 && INSN(15,4) == BITS12(1,1,1,1,1,1,0,0,1,0,0,1)) {
13201 szBlg2
= INSN(22,21); // 10:B 11:H 00:W 01:invalid
13202 gate
= szBlg2
!= BITS2(0,1) && tt
!= 15 && nn
!= 15;
13205 // Rearrange szBlg2 bits to be the same as the Thumb case
13207 case 2: szBlg2
= 0; break;
13208 case 3: szBlg2
= 1; break;
13209 case 0: szBlg2
= 2; break;
13210 default: /*NOTREACHED*/vassert(0);
13214 // For both encodings, the instruction is guarded by condT, which
13215 // is passed in by the caller. Note that the the loads and stores
13216 // are conditional, so we don't have to truncate the IRSB at this
13217 // point, but the fence is unconditional. There's no way to
13218 // represent a conditional fence without a side exit, but it
13219 // doesn't matter from a correctness standpoint that it is
13220 // unconditional -- it just loses a bit of performance in the
13221 // case where the condition doesn't hold.
13223 vassert(szBlg2
<= 2 && nn
<= 14 && tt
<= 14);
13224 IRExpr
* ea
= llGetIReg(nn
);
13226 static IRLoadGOp cvt
[3]
13227 = { ILGop_8Uto32
, ILGop_16Uto32
, ILGop_Ident32
};
13228 IRTemp data
= newTemp(Ity_I32
);
13229 loadGuardedLE(data
, cvt
[szBlg2
], ea
, mkU32(0)/*alt*/, condT
);
13231 putIRegT(tt
, mkexpr(data
), condT
);
13233 putIRegA(tt
, mkexpr(data
), condT
, Ijk_INVALID
);
13235 stmt(IRStmt_MBE(Imbe_Fence
));
13237 stmt(IRStmt_MBE(Imbe_Fence
));
13238 IRExpr
* data
= llGetIReg(tt
);
13240 case 0: data
= unop(Iop_32to8
, data
); break;
13241 case 1: data
= unop(Iop_32to16
, data
); break;
13243 default: vassert(0);
13245 storeGuardedLE(ea
, data
, condT
);
13247 const HChar
* ldNames
[3] = { "ldab", "ldah", "lda" };
13248 const HChar
* stNames
[3] = { "stlb", "stlh", "stl" };
13249 DIP("%s r%u, [r%u]", (isLoad
? ldNames
: stNames
)[szBlg2
], tt
, nn
);
13252 /* else fall through */
13255 /* ----------- LDAEX{,B,H,D}, STLEX{,B,H,D} ----------- */
13256 /* 31 27 23 19 15 11 7 3
13257 A1: cond 0001 1101 n t 1110 1001 1111 LDAEXB Rt, [Rn]
13258 A1: cond 0001 1111 n t 1110 1001 1111 LDAEXH Rt, [Rn]
13259 A1: cond 0001 1001 n t 1110 1001 1111 LDAEX Rt, [Rn]
13260 A1: cond 0001 1011 n t 1110 1001 1111 LDAEXD Rt, Rt+1, [Rn]
13262 A1: cond 0001 1100 n d 1110 1001 t STLEXB Rd, Rt, [Rn]
13263 A1: cond 0001 1110 n d 1110 1001 t STLEXH Rd, Rt, [Rn]
13264 A1: cond 0001 1000 n d 1110 1001 t STLEX Rd, Rt, [Rn]
13265 A1: cond 0001 1010 n d 1110 1001 t STLEXD Rd, Rt, Rt+1, [Rn]
13267 31 28 24 19 15 11 7 3
13268 T1: 111 0100 01101 n t 1111 1100 1111 LDAEXB Rt, [Rn]
13269 T1: 111 0100 01101 n t 1111 1101 1111 LDAEXH Rt, [Rn]
13270 T1: 111 0100 01101 n t 1111 1110 1111 LDAEX Rt, [Rn]
13271 T1: 111 0100 01101 n t t2 1111 1111 LDAEXD Rt, Rt2, [Rn]
13273 T1: 111 0100 01100 n t 1111 1100 d STLEXB Rd, Rt, [Rn]
13274 T1: 111 0100 01100 n t 1111 1101 d STLEXH Rd, Rt, [Rn]
13275 T1: 111 0100 01100 n t 1111 1110 d STLEX Rd, Rt, [Rn]
13276 T1: 111 0100 01100 n t t2 1111 d STLEXD Rd, Rt, Rt2, [Rn]
13279 UInt nn
= 16; // invalid
13280 UInt tt
= 16; // invalid
13281 UInt tt2
= 16; // invalid
13282 UInt dd
= 16; // invalid
13283 UInt szBlg2
= 4; // invalid
13284 Bool isLoad
= False
;
13287 if (INSN(31,21) == BITS11(1,1,1,0,1,0,0,0,1,1,0)
13288 && INSN(7,6) == BITS2(1,1)) {
13289 isLoad
= INSN(20,20) == 1;
13293 szBlg2
= INSN(5,4);
13296 if (szBlg2
< BITS2(1,1) && tt2
!= BITS4(1,1,1,1)) gate
= False
;
13297 if (isLoad
&& dd
!= BITS4(1,1,1,1)) gate
= False
;
13298 // re-set not-used register values to invalid
13299 if (szBlg2
< BITS2(1,1)) tt2
= 16;
13300 if (isLoad
) dd
= 16;
13303 /* ARM encoding. Do the load and store cases separately as
13304 the register numbers are in different places and a combined decode
13305 is too confusing. */
13306 if (INSN(27,23) == BITS5(0,0,0,1,1) && INSN(20,20) == 1
13307 && INSN(11,0) == BITS12(1,1,1,0,1,0,0,1,1,1,1,1)) {
13308 szBlg2
= INSN(22,21);
13315 if (INSN(27,23) == BITS5(0,0,0,1,1) && INSN(20,20) == 0
13316 && INSN(11,4) == BITS8(1,1,1,0,1,0,0,1)) {
13317 szBlg2
= INSN(22,21);
13325 // Rearrange szBlg2 bits to be the same as the Thumb case
13327 case 2: szBlg2
= 0; break;
13328 case 3: szBlg2
= 1; break;
13329 case 0: szBlg2
= 2; break;
13330 case 1: szBlg2
= 3; break;
13331 default: /*NOTREACHED*/vassert(0);
13335 // Perform further checks on register numbers
13337 /**/ if (isT
&& isLoad
) {
13340 if (! (tt
!= 13 && tt
!= 15 && nn
!= 15)) gate
= False
;
13342 if (! (tt
!= 13 && tt
!= 15 && tt2
!= 13 && tt2
!= 15
13343 && tt
!= tt2
&& nn
!= 15)) gate
= False
;
13346 else if (isT
&& !isLoad
) {
13349 if (! (dd
!= 13 && dd
!= 15 && tt
!= 13 && tt
!= 15
13350 && nn
!= 15 && dd
!= nn
&& dd
!= tt
)) gate
= False
;
13352 if (! (dd
!= 13 && dd
!= 15 && tt
!= 13 && tt
!= 15
13353 && tt2
!= 13 && tt2
!= 15 && nn
!= 15 && dd
!= nn
13354 && dd
!= tt
&& dd
!= tt2
)) gate
= False
;
13357 else if (!isT
&& isLoad
) {
13360 if (! (tt
!= 15 && nn
!= 15)) gate
= False
;
13362 if (! ((tt
& 1) == 0 && tt
!= 14 && nn
!= 15)) gate
= False
;
13363 vassert(tt2
== 16/*invalid*/);
13367 else if (!isT
&& !isLoad
) {
13370 if (! (dd
!= 15 && tt
!= 15 && nn
!= 15
13371 && dd
!= nn
&& dd
!= tt
)) gate
= False
;
13373 if (! (dd
!= 15 && (tt
& 1) == 0 && tt
!= 14 && nn
!= 15
13374 && dd
!= nn
&& dd
!= tt
&& dd
!= tt
+1)) gate
= False
;
13375 vassert(tt2
== 16/*invalid*/);
13379 else /*NOTREACHED*/vassert(0);
13383 vassert(szBlg2
<= 3);
13384 if (szBlg2
< 3) { vassert(tt2
== 16/*invalid*/); }
13385 else { vassert(tt2
<= 14); }
13386 if (isLoad
) { vassert(dd
== 16/*invalid*/); }
13387 else { vassert(dd
<= 14); }
13389 // If we're still good even after all that, generate the IR.
13391 /* First, go unconditional. Staying in-line is too complex. */
13393 vassert(condT
!= IRTemp_INVALID
);
13394 mk_skip_over_T32_if_cond_is_false( condT
);
13396 if (condT
!= IRTemp_INVALID
) {
13397 mk_skip_over_A32_if_cond_is_false( condT
);
13398 condT
= IRTemp_INVALID
;
13401 /* Now the load or store. */
13402 IRType ty
= Ity_INVALID
; /* the type of the transferred data */
13403 const HChar
* nm
= NULL
;
13405 case 0: nm
= "b"; ty
= Ity_I8
; break;
13406 case 1: nm
= "h"; ty
= Ity_I16
; break;
13407 case 2: nm
= ""; ty
= Ity_I32
; break;
13408 case 3: nm
= "d"; ty
= Ity_I64
; break;
13409 default: vassert(0);
13411 IRExpr
* ea
= isT
? getIRegT(nn
) : getIRegA(nn
);
13413 // LOAD. Transaction, then fence.
13414 IROp widen
= Iop_INVALID
;
13416 case 0: widen
= Iop_8Uto32
; break;
13417 case 1: widen
= Iop_16Uto32
; break;
13418 case 2: case 3: break;
13419 default: vassert(0);
13421 IRTemp res
= newTemp(ty
);
13422 // FIXME: assumes little-endian guest
13423 stmt( IRStmt_LLSC(Iend_LE
, res
, ea
, NULL
/*this is a load*/) );
13425 # define PUT_IREG(_nnz, _eez) \
13426 do { vassert((_nnz) <= 14); /* no writes to the PC */ \
13427 if (isT) { putIRegT((_nnz), (_eez), IRTemp_INVALID); } \
13428 else { putIRegA((_nnz), (_eez), \
13429 IRTemp_INVALID, Ijk_Boring); } } while(0)
13430 if (ty
== Ity_I64
) {
13431 // FIXME: assumes little-endian guest
13432 PUT_IREG(tt
, unop(Iop_64to32
, mkexpr(res
)));
13433 PUT_IREG(tt2
, unop(Iop_64HIto32
, mkexpr(res
)));
13435 PUT_IREG(tt
, widen
== Iop_INVALID
13436 ? mkexpr(res
) : unop(widen
, mkexpr(res
)));
13438 stmt(IRStmt_MBE(Imbe_Fence
));
13439 if (ty
== Ity_I64
) {
13440 DIP("ldrex%s%s r%u, r%u, [r%u]\n",
13441 nm
, isT
? "" : nCC(conq
), tt
, tt2
, nn
);
13443 DIP("ldrex%s%s r%u, [r%u]\n", nm
, isT
? "" : nCC(conq
), tt
, nn
);
13447 // STORE. Fence, then transaction.
13448 IRTemp resSC1
, resSC32
, data
;
13449 IROp narrow
= Iop_INVALID
;
13451 case 0: narrow
= Iop_32to8
; break;
13452 case 1: narrow
= Iop_32to16
; break;
13453 case 2: case 3: break;
13454 default: vassert(0);
13456 stmt(IRStmt_MBE(Imbe_Fence
));
13457 data
= newTemp(ty
);
13458 # define GET_IREG(_nnz) (isT ? getIRegT(_nnz) : getIRegA(_nnz))
13461 // FIXME: assumes little-endian guest
13462 ? binop(Iop_32HLto64
, GET_IREG(tt2
), GET_IREG(tt
))
13463 : narrow
== Iop_INVALID
13465 : unop(narrow
, GET_IREG(tt
)));
13467 resSC1
= newTemp(Ity_I1
);
13468 // FIXME: assumes little-endian guest
13469 stmt( IRStmt_LLSC(Iend_LE
, resSC1
, ea
, mkexpr(data
)) );
13471 /* Set rDD to 1 on failure, 0 on success. Currently we have
13472 resSC1 == 0 on failure, 1 on success. */
13473 resSC32
= newTemp(Ity_I32
);
13475 unop(Iop_1Uto32
, unop(Iop_Not1
, mkexpr(resSC1
))));
13476 vassert(dd
<= 14); /* no writes to the PC */
13478 putIRegT(dd
, mkexpr(resSC32
), IRTemp_INVALID
);
13480 putIRegA(dd
, mkexpr(resSC32
), IRTemp_INVALID
, Ijk_Boring
);
13482 if (ty
== Ity_I64
) {
13483 DIP("strex%s%s r%u, r%u, r%u, [r%u]\n",
13484 nm
, isT
? "" : nCC(conq
), dd
, tt
, tt2
, nn
);
13486 DIP("strex%s%s r%u, r%u, [r%u]\n",
13487 nm
, isT
? "" : nCC(conq
), dd
, tt
, nn
);
13489 } /* if (isLoad) */
13492 /* else fall through */
13495 /* ----------- VSEL<c>.F64 d_d_d, VSEL<c>.F32 s_s_s ----------- */
13496 /* 31 27 22 21 19 15 11 8 7 6 5 4 3
13497 T1/A1: 1111 11100 D cc n d 101 1 N 0 M 0 m VSEL<c>.F64 Dd, Dn, Dm
13498 T1/A1: 1111 11100 D cc n d 101 0 N 0 M 0 m VSEL<c>.F32 Sd, Sn, Sm
13500 ARM encoding is in NV space.
13501 In Thumb mode, we must not be in an IT block.
13503 if (INSN(31,23) == BITS9(1,1,1,1,1,1,1,0,0) && INSN(11,9) == BITS3(1,0,1)
13504 && INSN(6,6) == 0 && INSN(4,4) == 0) {
13505 UInt bit_D
= INSN(22,22);
13506 UInt fld_cc
= INSN(21,20);
13507 UInt fld_n
= INSN(19,16);
13508 UInt fld_d
= INSN(15,12);
13509 Bool isF64
= INSN(8,8) == 1;
13510 UInt bit_N
= INSN(7,7);
13511 UInt bit_M
= INSN(5,5);
13512 UInt fld_m
= INSN(3,0);
13514 UInt dd
= isF64
? ((bit_D
<< 4) | fld_d
) : ((fld_d
<< 1) | bit_D
);
13515 UInt nn
= isF64
? ((bit_N
<< 4) | fld_n
) : ((fld_n
<< 1) | bit_N
);
13516 UInt mm
= isF64
? ((bit_M
<< 4) | fld_m
) : ((fld_m
<< 1) | bit_M
);
13518 UInt cc_1
= (fld_cc
>> 1) & 1;
13519 UInt cc_0
= (fld_cc
>> 0) & 1;
13520 UInt cond
= (fld_cc
<< 2) | ((cc_1
^ cc_0
) << 1) | 0;
13523 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13525 /* In ARM mode, this is statically unconditional. In Thumb mode,
13526 this must be dynamically unconditional, and we've SIGILLd if not.
13527 In either case we can create unconditional IR. */
13529 IRTemp guard
= newTemp(Ity_I32
);
13530 assign(guard
, mk_armg_calculate_condition(cond
));
13531 IRExpr
* srcN
= (isF64
? llGetDReg
: llGetFReg
)(nn
);
13532 IRExpr
* srcM
= (isF64
? llGetDReg
: llGetFReg
)(mm
);
13533 IRExpr
* res
= IRExpr_ITE(unop(Iop_32to1
, mkexpr(guard
)), srcN
, srcM
);
13534 (isF64
? llPutDReg
: llPutFReg
)(dd
, res
);
13536 UChar rch
= isF64
? 'd' : 'f';
13537 DIP("vsel%s.%s %c%u, %c%u, %c%u\n",
13538 nCC(cond
), isF64
? "f64" : "f32", rch
, dd
, rch
, nn
, rch
, mm
);
13542 /* -------- VRINT{A,N,P,M}.F64 d_d, VRINT{A,N,P,M}.F32 s_s -------- */
13543 /* 31 22 21 17 15 11 8 7 5 4 3
13544 T1/A1: 111111101 D 1110 rm Vd 101 1 01 M 0 Vm VRINT{A,N,P,M}.F64 Dd, Dm
13545 T1/A1: 111111101 D 1110 rm Vd 101 0 01 M 0 Vm VRINT{A,N,P,M}.F32 Sd, Sm
13547 ARM encoding is in NV space.
13548 In Thumb mode, we must not be in an IT block.
13550 if (INSN(31,23) == BITS9(1,1,1,1,1,1,1,0,1)
13551 && INSN(21,18) == BITS4(1,1,1,0) && INSN(11,9) == BITS3(1,0,1)
13552 && INSN(7,6) == BITS2(0,1) && INSN(4,4) == 0) {
13553 UInt bit_D
= INSN(22,22);
13554 UInt fld_rm
= INSN(17,16);
13555 UInt fld_d
= INSN(15,12);
13556 Bool isF64
= INSN(8,8) == 1;
13557 UInt bit_M
= INSN(5,5);
13558 UInt fld_m
= INSN(3,0);
13560 UInt dd
= isF64
? ((bit_D
<< 4) | fld_d
) : ((fld_d
<< 1) | bit_D
);
13561 UInt mm
= isF64
? ((bit_M
<< 4) | fld_m
) : ((fld_m
<< 1) | bit_M
);
13564 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13566 /* In ARM mode, this is statically unconditional. In Thumb mode,
13567 this must be dynamically unconditional, and we've SIGILLd if not.
13568 In either case we can create unconditional IR. */
13571 IRRoundingMode rm
= Irrm_NEAREST
;
13573 /* The use of NEAREST for both the 'a' and 'n' cases is a bit of a
13574 kludge since it doesn't take into account the nearest-even vs
13575 nearest-away semantics. */
13576 case BITS2(0,0): c
= 'a'; rm
= Irrm_NEAREST
; break;
13577 case BITS2(0,1): c
= 'n'; rm
= Irrm_NEAREST
; break;
13578 case BITS2(1,0): c
= 'p'; rm
= Irrm_PosINF
; break;
13579 case BITS2(1,1): c
= 'm'; rm
= Irrm_NegINF
; break;
13580 default: vassert(0);
13583 IRExpr
* srcM
= (isF64
? llGetDReg
: llGetFReg
)(mm
);
13584 IRExpr
* res
= binop(isF64
? Iop_RoundF64toInt
: Iop_RoundF32toInt
,
13585 mkU32((UInt
)rm
), srcM
);
13586 (isF64
? llPutDReg
: llPutFReg
)(dd
, res
);
13588 UChar rch
= isF64
? 'd' : 'f';
13589 DIP("vrint%c.%s.%s %c%u, %c%u\n",
13590 c
, isF64
? "f64" : "f32", isF64
? "f64" : "f32", rch
, dd
, rch
, mm
);
13594 /* -------- VRINT{Z,R}.F64.F64 d_d, VRINT{Z,R}.F32.F32 s_s -------- */
13595 /* 31 27 22 21 15 11 7 6 5 4 3
13596 T1: 1110 11101 D 110110 Vd 1011 op 1 M 0 Vm VRINT<r><c>.F64.F64 Dd, Dm
13597 A1: cond 11101 D 110110 Vd 1011 op 1 M 0 Vm
13599 T1: 1110 11101 D 110110 Vd 1010 op 1 M 0 Vm VRINT<r><c>.F32.F32 Sd, Sm
13600 A1: cond 11101 D 110110 Vd 1010 op 1 M 0 Vm
13602 In contrast to the VRINT variants just above, this can be conditional.
13604 if ((isT
? (INSN(31,28) == BITS4(1,1,1,0)) : True
)
13605 && INSN(27,23) == BITS5(1,1,1,0,1) && INSN(21,16) == BITS6(1,1,0,1,1,0)
13606 && INSN(11,9) == BITS3(1,0,1) && INSN(6,6) == 1 && INSN(4,4) == 0) {
13607 UInt bit_D
= INSN(22,22);
13608 UInt fld_Vd
= INSN(15,12);
13609 Bool isF64
= INSN(8,8) == 1;
13610 Bool rToZero
= INSN(7,7) == 1;
13611 UInt bit_M
= INSN(5,5);
13612 UInt fld_Vm
= INSN(3,0);
13613 UInt dd
= isF64
? ((bit_D
<< 4) | fld_Vd
) : ((fld_Vd
<< 1) | bit_D
);
13614 UInt mm
= isF64
? ((bit_M
<< 4) | fld_Vm
) : ((fld_Vm
<< 1) | bit_M
);
13616 if (isT
) vassert(condT
!= IRTemp_INVALID
);
13617 IRType ty
= isF64
? Ity_F64
: Ity_F32
;
13618 IRTemp src
= newTemp(ty
);
13619 IRTemp res
= newTemp(ty
);
13620 assign(src
, (isF64
? getDReg
: getFReg
)(mm
));
13622 IRTemp rm
= newTemp(Ity_I32
);
13623 assign(rm
, rToZero
? mkU32(Irrm_ZERO
)
13624 : mkexpr(mk_get_IR_rounding_mode()));
13625 assign(res
, binop(isF64
? Iop_RoundF64toInt
: Iop_RoundF32toInt
,
13626 mkexpr(rm
), mkexpr(src
)));
13627 (isF64
? putDReg
: putFReg
)(dd
, mkexpr(res
), condT
);
13629 UChar rch
= isF64
? 'd' : 'f';
13630 DIP("vrint%c.%s.%s %c%u, %c%u\n",
13631 rToZero
? 'z' : 'r',
13632 isF64
? "f64" : "f32", isF64
? "f64" : "f32", rch
, dd
, rch
, mm
);
13636 /* ----------- VCVT{A,N,P,M}{.S32,.U32}{.F64,.F32} ----------- */
13637 /* 31 27 22 21 17 15 11 8 7 6 5 4 3
13638 T1/A1: 1111 11101 D 1111 rm Vd 101 sz op 1 M 0 Vm
13639 VCVT{A,N,P,M}{.S32,.U32}.F64 Sd, Dm
13640 VCVT{A,N,P,M}{.S32,.U32}.F32 Sd, Sm
13642 ARM encoding is in NV space.
13643 In Thumb mode, we must not be in an IT block.
13645 if (INSN(31,23) == BITS9(1,1,1,1,1,1,1,0,1) && INSN(21,18) == BITS4(1,1,1,1)
13646 && INSN(11,9) == BITS3(1,0,1) && INSN(6,6) == 1 && INSN(4,4) == 0) {
13647 UInt bit_D
= INSN(22,22);
13648 UInt fld_rm
= INSN(17,16);
13649 UInt fld_Vd
= INSN(15,12);
13650 Bool isF64
= INSN(8,8) == 1;
13651 Bool isU
= INSN(7,7) == 0;
13652 UInt bit_M
= INSN(5,5);
13653 UInt fld_Vm
= INSN(3,0);
13655 UInt dd
= (fld_Vd
<< 1) | bit_D
;
13656 UInt mm
= isF64
? ((bit_M
<< 4) | fld_Vm
) : ((fld_Vm
<< 1) | bit_M
);
13659 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13661 /* In ARM mode, this is statically unconditional. In Thumb mode,
13662 this must be dynamically unconditional, and we've SIGILLd if not.
13663 In either case we can create unconditional IR. */
13666 IRRoundingMode rm
= Irrm_NEAREST
;
13668 /* The use of NEAREST for both the 'a' and 'n' cases is a bit of a
13669 kludge since it doesn't take into account the nearest-even vs
13670 nearest-away semantics. */
13671 case BITS2(0,0): c
= 'a'; rm
= Irrm_NEAREST
; break;
13672 case BITS2(0,1): c
= 'n'; rm
= Irrm_NEAREST
; break;
13673 case BITS2(1,0): c
= 'p'; rm
= Irrm_PosINF
; break;
13674 case BITS2(1,1): c
= 'm'; rm
= Irrm_NegINF
; break;
13675 default: vassert(0);
13678 IRExpr
* srcM
= (isF64
? llGetDReg
: llGetFReg
)(mm
);
13679 IRTemp res
= newTemp(Ity_I32
);
13681 /* The arm back end doesn't support use of Iop_F32toI32U or
13682 Iop_F32toI32S, so for those cases we widen the F32 to F64
13683 and then follow the F64 route. */
13685 srcM
= unop(Iop_F32toF64
, srcM
);
13687 assign(res
, binop(isU
? Iop_F64toI32U
: Iop_F64toI32S
,
13688 mkU32((UInt
)rm
), srcM
));
13690 llPutFReg(dd
, unop(Iop_ReinterpI32asF32
, mkexpr(res
)));
13692 UChar rch
= isF64
? 'd' : 'f';
13693 DIP("vcvt%c.%s.%s %c%u, %c%u\n",
13694 c
, isU
? "u32" : "s32", isF64
? "f64" : "f32", 's', dd
, rch
, mm
);
13698 /* ----------- V{MAX,MIN}NM{.F64 d_d_d, .F32 s_s_s} ----------- */
13699 /* 31 27 22 21 19 15 11 8 7 6 5 4 3
13700 1111 11101 D 00 Vn Vd 101 1 N op M 0 Vm V{MIN,MAX}NM.F64 Dd, Dn, Dm
13701 1111 11101 D 00 Vn Vd 101 0 N op M 0 Vm V{MIN,MAX}NM.F32 Sd, Sn, Sm
13703 ARM encoding is in NV space.
13704 In Thumb mode, we must not be in an IT block.
13706 if (INSN(31,23) == BITS9(1,1,1,1,1,1,1,0,1) && INSN(21,20) == BITS2(0,0)
13707 && INSN(11,9) == BITS3(1,0,1) && INSN(4,4) == 0) {
13708 UInt bit_D
= INSN(22,22);
13709 UInt fld_Vn
= INSN(19,16);
13710 UInt fld_Vd
= INSN(15,12);
13711 Bool isF64
= INSN(8,8) == 1;
13712 UInt bit_N
= INSN(7,7);
13713 Bool isMAX
= INSN(6,6) == 0;
13714 UInt bit_M
= INSN(5,5);
13715 UInt fld_Vm
= INSN(3,0);
13717 UInt dd
= isF64
? ((bit_D
<< 4) | fld_Vd
) : ((fld_Vd
<< 1) | bit_D
);
13718 UInt nn
= isF64
? ((bit_N
<< 4) | fld_Vn
) : ((fld_Vn
<< 1) | bit_N
);
13719 UInt mm
= isF64
? ((bit_M
<< 4) | fld_Vm
) : ((fld_Vm
<< 1) | bit_M
);
13722 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13724 /* In ARM mode, this is statically unconditional. In Thumb mode,
13725 this must be dynamically unconditional, and we've SIGILLd if not.
13726 In either case we can create unconditional IR. */
13728 IROp op
= isF64
? (isMAX
? Iop_MaxNumF64
: Iop_MinNumF64
)
13729 : (isMAX
? Iop_MaxNumF32
: Iop_MinNumF32
);
13730 IRExpr
* srcN
= (isF64
? llGetDReg
: llGetFReg
)(nn
);
13731 IRExpr
* srcM
= (isF64
? llGetDReg
: llGetFReg
)(mm
);
13732 IRExpr
* res
= binop(op
, srcN
, srcM
);
13733 (isF64
? llPutDReg
: llPutFReg
)(dd
, res
);
13735 UChar rch
= isF64
? 'd' : 'f';
13736 DIP("v%snm.%s %c%u, %c%u, %c%u\n",
13737 isMAX
? "max" : "min", isF64
? "f64" : "f32",
13738 rch
, dd
, rch
, nn
, rch
, mm
);
13742 /* ----------- VRINTX.F64.F64 d_d, VRINTX.F32.F32 s_s ----------- */
13743 /* 31 27 22 21 15 11 8 7 5 4 3
13744 T1: 1110 11101 D 110111 Vd 101 1 01 M 0 Vm VRINTX<c>.F64.F64 Dd, Dm
13745 A1: cond 11101 D 110111 Vd 101 1 01 M 0 Vm
13747 T1: 1110 11101 D 110111 Vd 101 0 01 M 0 Vm VRINTX<c>.F32.F32 Dd, Dm
13748 A1: cond 11101 D 110111 Vd 101 0 01 M 0 Vm
13750 Like VRINT{Z,R}{.F64.F64, .F32.F32} just above, this can be conditional.
13751 This produces the same code as the VRINTR case since we ignore the
13752 requirement to signal inexactness.
13754 if ((isT
? (INSN(31,28) == BITS4(1,1,1,0)) : True
)
13755 && INSN(27,23) == BITS5(1,1,1,0,1) && INSN(21,16) == BITS6(1,1,0,1,1,1)
13756 && INSN(11,9) == BITS3(1,0,1) && INSN(7,6) == BITS2(0,1)
13757 && INSN(4,4) == 0) {
13758 UInt bit_D
= INSN(22,22);
13759 UInt fld_Vd
= INSN(15,12);
13760 Bool isF64
= INSN(8,8) == 1;
13761 UInt bit_M
= INSN(5,5);
13762 UInt fld_Vm
= INSN(3,0);
13763 UInt dd
= isF64
? ((bit_D
<< 4) | fld_Vd
) : ((fld_Vd
<< 1) | bit_D
);
13764 UInt mm
= isF64
? ((bit_M
<< 4) | fld_Vm
) : ((fld_Vm
<< 1) | bit_M
);
13766 if (isT
) vassert(condT
!= IRTemp_INVALID
);
13767 IRType ty
= isF64
? Ity_F64
: Ity_F32
;
13768 IRTemp src
= newTemp(ty
);
13769 IRTemp res
= newTemp(ty
);
13770 assign(src
, (isF64
? getDReg
: getFReg
)(mm
));
13772 IRTemp rm
= newTemp(Ity_I32
);
13773 assign(rm
, mkexpr(mk_get_IR_rounding_mode()));
13774 assign(res
, binop(isF64
? Iop_RoundF64toInt
: Iop_RoundF32toInt
,
13775 mkexpr(rm
), mkexpr(src
)));
13776 (isF64
? putDReg
: putFReg
)(dd
, mkexpr(res
), condT
);
13778 UChar rch
= isF64
? 'd' : 'f';
13779 DIP("vrint%c.%s.%s %c%u, %c%u\n",
13781 isF64
? "f64" : "f32", isF64
? "f64" : "f32", rch
, dd
, rch
, mm
);
13785 /* ----------- V{MAX,MIN}NM{.F32 d_d_d, .F32 q_q_q} ----------- */
13786 /* 31 27 22 21 20 19 15 11 7 6 5 4 3
13787 T1: 1111 11110 D op 0 Vn Vd 1111 N 1 M 1 Vm V{MIN,MAX}NM.F32 Qd,Qn,Qm
13788 A1: 1111 00110 D op 0 Vn Vd 1111 N 1 M 1 Vm
13790 T1: 1111 11110 D op 0 Vn Vd 1111 N 0 M 1 Vm V{MIN,MAX}NM.F32 Dd,Dn,Dm
13791 A1: 1111 00110 D op 0 Vn Vd 1111 N 0 M 1 Vm
13793 ARM encoding is in NV space.
13794 In Thumb mode, we must not be in an IT block.
13796 if (INSN(31,23) == (isT
? BITS9(1,1,1,1,1,1,1,1,0)
13797 : BITS9(1,1,1,1,0,0,1,1,0))
13798 && INSN(20,20) == 0 && INSN(11,8) == BITS4(1,1,1,1) && INSN(4,4) == 1) {
13799 UInt bit_D
= INSN(22,22);
13800 Bool isMax
= INSN(21,21) == 0;
13801 UInt fld_Vn
= INSN(19,16);
13802 UInt fld_Vd
= INSN(15,12);
13803 UInt bit_N
= INSN(7,7);
13804 Bool isQ
= INSN(6,6) == 1;
13805 UInt bit_M
= INSN(5,5);
13806 UInt fld_Vm
= INSN(3,0);
13808 /* dd, nn, mm are D-register numbers. */
13809 UInt dd
= (bit_D
<< 4) | fld_Vd
;
13810 UInt nn
= (bit_N
<< 4) | fld_Vn
;
13811 UInt mm
= (bit_M
<< 4) | fld_Vm
;
13813 if (! (isQ
&& ((dd
& 1) == 1 || (nn
& 1) == 1 || (mm
& 1) == 1))) {
13814 /* Do this piecewise on f regs. This is a bit tricky
13815 though because we are dealing with the full 16 x Q == 32 x D
13816 register set, so the implied F reg numbers are 0 to 63. But
13817 ll{Get,Put}FReg only allow the 0 .. 31 as those are the only
13818 architected F regs. */
13819 UInt ddF
= dd
<< 1;
13820 UInt nnF
= nn
<< 1;
13821 UInt mmF
= mm
<< 1;
13824 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13826 /* In ARM mode, this is statically unconditional. In Thumb mode,
13827 this must be dynamically unconditional, and we've SIGILLd if not.
13828 In either case we can create unconditional IR. */
13830 IROp op
= isMax
? Iop_MaxNumF32
: Iop_MinNumF32
;
13832 IRTemp r0
= newTemp(Ity_F32
);
13833 IRTemp r1
= newTemp(Ity_F32
);
13834 IRTemp r2
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
13835 IRTemp r3
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
13837 assign(r0
, binop(op
, llGetFReg_up_to_64(nnF
+0),
13838 llGetFReg_up_to_64(mmF
+0)));
13839 assign(r1
, binop(op
, llGetFReg_up_to_64(nnF
+1),
13840 llGetFReg_up_to_64(mmF
+1)));
13842 assign(r2
, binop(op
, llGetFReg_up_to_64(nnF
+2),
13843 llGetFReg_up_to_64(mmF
+2)));
13844 assign(r3
, binop(op
, llGetFReg_up_to_64(nnF
+3),
13845 llGetFReg_up_to_64(mmF
+3)));
13847 llPutFReg_up_to_64(ddF
+0, mkexpr(r0
));
13848 llPutFReg_up_to_64(ddF
+1, mkexpr(r1
));
13850 llPutFReg_up_to_64(ddF
+2, mkexpr(r2
));
13851 llPutFReg_up_to_64(ddF
+3, mkexpr(r3
));
13854 HChar rch
= isQ
? 'q' : 'd';
13855 UInt sh
= isQ
? 1 : 0;
13856 DIP("v%snm.f32 %c%u, %c%u, %c%u\n",
13857 isMax
? "max" : "min", rch
,
13858 dd
>> sh
, rch
, nn
>> sh
, rch
, mm
>> sh
);
13861 /* else fall through */
13864 /* ----------- VCVT{A,N,P,M}{.F32 d_d, .F32 q_q} ----------- */
13865 /* 31 27 22 21 15 11 9 7 6 5 4 3
13866 T1: 1111 11111 D 111011 Vd 00 rm op Q M 0 Vm
13867 A1: 1111 00111 D 111011 Vd 00 rm op Q M 0 Vm
13869 ARM encoding is in NV space.
13870 In Thumb mode, we must not be in an IT block.
13872 if (INSN(31,23) == (isT
? BITS9(1,1,1,1,1,1,1,1,1)
13873 : BITS9(1,1,1,1,0,0,1,1,1))
13874 && INSN(21,16) == BITS6(1,1,1,0,1,1) && INSN(11,10) == BITS2(0,0)
13875 && INSN(4,4) == 0) {
13876 UInt bit_D
= INSN(22,22);
13877 UInt fld_Vd
= INSN(15,12);
13878 UInt fld_rm
= INSN(9,8);
13879 Bool isU
= INSN(7,7) == 1;
13880 Bool isQ
= INSN(6,6) == 1;
13881 UInt bit_M
= INSN(5,5);
13882 UInt fld_Vm
= INSN(3,0);
13884 /* dd, nn, mm are D-register numbers. */
13885 UInt dd
= (bit_D
<< 4) | fld_Vd
;
13886 UInt mm
= (bit_M
<< 4) | fld_Vm
;
13888 if (! (isQ
&& ((dd
& 1) == 1 || (mm
& 1) == 1))) {
13889 /* Do this piecewise on f regs. */
13890 UInt ddF
= dd
<< 1;
13891 UInt mmF
= mm
<< 1;
13894 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13896 /* In ARM mode, this is statically unconditional. In Thumb mode,
13897 this must be dynamically unconditional, and we've SIGILLd if not.
13898 In either case we can create unconditional IR. */
13901 IRRoundingMode rm
= Irrm_NEAREST
;
13903 /* The use of NEAREST for both the 'a' and 'n' cases is a bit of a
13904 kludge since it doesn't take into account the nearest-even vs
13905 nearest-away semantics. */
13906 case BITS2(0,0): cvtc
= 'a'; rm
= Irrm_NEAREST
; break;
13907 case BITS2(0,1): cvtc
= 'n'; rm
= Irrm_NEAREST
; break;
13908 case BITS2(1,0): cvtc
= 'p'; rm
= Irrm_PosINF
; break;
13909 case BITS2(1,1): cvtc
= 'm'; rm
= Irrm_NegINF
; break;
13910 default: vassert(0);
13913 IROp cvt
= isU
? Iop_F64toI32U
: Iop_F64toI32S
;
13915 IRTemp r0
= newTemp(Ity_F32
);
13916 IRTemp r1
= newTemp(Ity_F32
);
13917 IRTemp r2
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
13918 IRTemp r3
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
13920 IRExpr
* rmE
= mkU32((UInt
)rm
);
13922 assign(r0
, unop(Iop_ReinterpI32asF32
,
13923 binop(cvt
, rmE
, unop(Iop_F32toF64
,
13924 llGetFReg_up_to_64(mmF
+0)))));
13925 assign(r1
, unop(Iop_ReinterpI32asF32
,
13926 binop(cvt
, rmE
, unop(Iop_F32toF64
,
13927 llGetFReg_up_to_64(mmF
+1)))));
13929 assign(r2
, unop(Iop_ReinterpI32asF32
,
13930 binop(cvt
, rmE
, unop(Iop_F32toF64
,
13931 llGetFReg_up_to_64(mmF
+2)))));
13932 assign(r3
, unop(Iop_ReinterpI32asF32
,
13933 binop(cvt
, rmE
, unop(Iop_F32toF64
,
13934 llGetFReg_up_to_64(mmF
+3)))));
13937 llPutFReg_up_to_64(ddF
+0, mkexpr(r0
));
13938 llPutFReg_up_to_64(ddF
+1, mkexpr(r1
));
13940 llPutFReg_up_to_64(ddF
+2, mkexpr(r2
));
13941 llPutFReg_up_to_64(ddF
+3, mkexpr(r3
));
13944 HChar rch
= isQ
? 'q' : 'd';
13945 UInt sh
= isQ
? 1 : 0;
13946 DIP("vcvt%c.%c32.f32 %c%u, %c%u\n",
13947 cvtc
, isU
? 'u' : 's', rch
, dd
>> sh
, rch
, mm
>> sh
);
13950 /* else fall through */
13953 /* ----------- VRINT{A,N,P,M,X,Z}{.F32 d_d, .F32 q_q} ----------- */
13954 /* 31 27 22 21 15 11 9 6 5 4 3
13955 T1: 1111 11111 D 111010 Vd 01 op Q M 0 Vm
13956 A1: 1111 00111 D 111010 Vd 01 op Q M 0 Vm
13958 ARM encoding is in NV space.
13959 In Thumb mode, we must not be in an IT block.
13961 if (INSN(31,23) == (isT
? BITS9(1,1,1,1,1,1,1,1,1)
13962 : BITS9(1,1,1,1,0,0,1,1,1))
13963 && INSN(21,16) == BITS6(1,1,1,0,1,0) && INSN(11,10) == BITS2(0,1)
13964 && INSN(4,4) == 0) {
13965 UInt bit_D
= INSN(22,22);
13966 UInt fld_Vd
= INSN(15,12);
13967 UInt fld_op
= INSN(9,7);
13968 Bool isQ
= INSN(6,6) == 1;
13969 UInt bit_M
= INSN(5,5);
13970 UInt fld_Vm
= INSN(3,0);
13972 /* dd, nn, mm are D-register numbers. */
13973 UInt dd
= (bit_D
<< 4) | fld_Vd
;
13974 UInt mm
= (bit_M
<< 4) | fld_Vm
;
13976 if (! (fld_op
== BITS3(1,0,0) || fld_op
== BITS3(1,1,0))
13977 && ! (isQ
&& ((dd
& 1) == 1 || (mm
& 1) == 1))) {
13978 /* Do this piecewise on f regs. */
13979 UInt ddF
= dd
<< 1;
13980 UInt mmF
= mm
<< 1;
13983 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
13985 /* In ARM mode, this is statically unconditional. In Thumb mode,
13986 this must be dynamically unconditional, and we've SIGILLd if not.
13987 In either case we can create unconditional IR. */
13990 IRRoundingMode rm
= Irrm_NEAREST
;
13992 /* Various kludges:
13993 - The use of NEAREST for both the 'a' and 'n' cases,
13994 since it doesn't take into account the nearest-even vs
13995 nearest-away semantics.
13996 - For the 'x' case, we don't signal inexactness.
13998 case BITS3(0,1,0): cvtc
= 'a'; rm
= Irrm_NEAREST
; break;
13999 case BITS3(0,0,0): cvtc
= 'n'; rm
= Irrm_NEAREST
; break;
14000 case BITS3(1,1,1): cvtc
= 'p'; rm
= Irrm_PosINF
; break;
14001 case BITS3(1,0,1): cvtc
= 'm'; rm
= Irrm_NegINF
; break;
14002 case BITS3(0,1,1): cvtc
= 'z'; rm
= Irrm_ZERO
; break;
14003 case BITS3(0,0,1): cvtc
= 'x'; rm
= Irrm_NEAREST
; break;
14006 default: vassert(0);
14009 IRTemp r0
= newTemp(Ity_F32
);
14010 IRTemp r1
= newTemp(Ity_F32
);
14011 IRTemp r2
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
14012 IRTemp r3
= isQ
? newTemp(Ity_F32
) : IRTemp_INVALID
;
14014 IRExpr
* rmE
= mkU32((UInt
)rm
);
14015 IROp rnd
= Iop_RoundF32toInt
;
14017 assign(r0
, binop(rnd
, rmE
, llGetFReg_up_to_64(mmF
+0)));
14018 assign(r1
, binop(rnd
, rmE
, llGetFReg_up_to_64(mmF
+1)));
14020 assign(r2
, binop(rnd
, rmE
, llGetFReg_up_to_64(mmF
+2)));
14021 assign(r3
, binop(rnd
, rmE
, llGetFReg_up_to_64(mmF
+3)));
14024 llPutFReg_up_to_64(ddF
+0, mkexpr(r0
));
14025 llPutFReg_up_to_64(ddF
+1, mkexpr(r1
));
14027 llPutFReg_up_to_64(ddF
+2, mkexpr(r2
));
14028 llPutFReg_up_to_64(ddF
+3, mkexpr(r3
));
14031 HChar rch
= isQ
? 'q' : 'd';
14032 UInt sh
= isQ
? 1 : 0;
14033 DIP("vrint%c.f32.f32 %c%u, %c%u\n",
14034 cvtc
, rch
, dd
>> sh
, rch
, mm
>> sh
);
14037 /* else fall through */
14040 /* ---------- Doesn't match anything. ---------- */
14047 /*------------------------------------------------------------*/
14048 /*--- LDMxx/STMxx helper (both ARM and Thumb32) ---*/
14049 /*------------------------------------------------------------*/
14051 /* Generate IR for LDMxx and STMxx. This is complex. Assumes it's
14052 unconditional, so the caller must produce a jump-around before
14053 calling this, if the insn is to be conditional. Caller is
14054 responsible for all validation of parameters. For LDMxx, if PC is
14055 amongst the values loaded, caller is also responsible for
14056 generating the jump. */
14057 static void mk_ldm_stm ( Bool arm
, /* True: ARM, False: Thumb */
14058 UInt rN
, /* base reg */
14059 UInt bINC
, /* 1: inc, 0: dec */
14060 UInt bBEFORE
, /* 1: inc/dec before, 0: after */
14061 UInt bW
, /* 1: writeback to Rn */
14062 UInt bL
, /* 1: load, 0: store */
14065 Int i
, r
, m
, nRegs
;
14066 IRTemp jk
= Ijk_Boring
;
14068 /* Get hold of the old Rn value. We might need to write its value
14069 to memory during a store, and if it's also the writeback
14070 register then we need to get its value now. We can't treat it
14071 exactly like the other registers we're going to transfer,
14072 because for xxMDA and xxMDB writeback forms, the generated IR
14073 updates Rn in the guest state before any transfers take place.
14074 We have to do this as per comments below, in order that if Rn is
14075 the stack pointer then it always has a value is below or equal
14076 to any of the transfer addresses. Ick. */
14077 IRTemp oldRnT
= newTemp(Ity_I32
);
14078 assign(oldRnT
, arm
? getIRegA(rN
) : getIRegT(rN
));
14080 IRTemp anchorT
= newTemp(Ity_I32
);
14081 /* The old (Addison-Wesley) ARM ARM seems to say that LDMxx/STMxx
14082 ignore the bottom two bits of the address. However, Cortex-A8
14083 doesn't seem to care. Hence: */
14084 /* No .. don't force alignment .. */
14085 /* assign(anchorT, binop(Iop_And32, mkexpr(oldRnT), mkU32(~3U))); */
14086 /* Instead, use the potentially misaligned address directly. */
14087 assign(anchorT
, mkexpr(oldRnT
));
14089 IROp opADDorSUB
= bINC
? Iop_Add32
: Iop_Sub32
;
14090 // bINC == 1: xxMIA, xxMIB
14091 // bINC == 0: xxMDA, xxMDB
14093 // For xxMDA and xxMDB, update Rn first if necessary. We have
14094 // to do this first so that, for the common idiom of the transfers
14095 // faulting because we're pushing stuff onto a stack and the stack
14096 // is growing down onto allocate-on-fault pages (as Valgrind simulates),
14097 // we need to have the SP up-to-date "covering" (pointing below) the
14098 // transfer area. For the same reason, if we are doing xxMIA or xxMIB,
14099 // do the transfer first, and then update rN afterwards.
14101 for (i
= 0; i
< 16; i
++) {
14102 if ((regList
& (1 << i
)) != 0)
14105 if (bW
== 1 && !bINC
) {
14106 IRExpr
* e
= binop(opADDorSUB
, mkexpr(oldRnT
), mkU32(4*nRegs
));
14108 putIRegA( rN
, e
, IRTemp_INVALID
, Ijk_Boring
);
14110 putIRegT( rN
, e
, IRTemp_INVALID
);
14113 // Make up a list of the registers to transfer, and their offsets
14114 // in memory relative to the anchor. If the base reg (Rn) is part
14115 // of the transfer, then do it last for a load and first for a store.
14116 UInt xReg
[16], xOff
[16];
14119 for (i
= 0; i
< 16; i
++) {
14120 r
= bINC
? i
: (15-i
);
14121 if (0 == (regList
& (1<<r
)))
14125 /* paranoia: check we aren't transferring the writeback
14126 register during a load. Should be assured by decode-point
14128 if (bW
== 1 && bL
== 1)
14138 vassert(m
== nRegs
);
14139 vassert(nX
== nRegs
);
14142 if (bW
== 0 && (regList
& (1<<rN
)) != 0) {
14143 /* Non-writeback, and basereg is to be transferred. Do its
14144 transfer last for a load and first for a store. Requires
14145 reordering xOff/xReg. */
14147 vex_printf("\nREG_LIST_PRE: (rN=%u)\n", rN
);
14148 for (i
= 0; i
< nX
; i
++)
14149 vex_printf("reg %u off %u\n", xReg
[i
], xOff
[i
]);
14154 for (i
= 0; i
< nX
; i
++) {
14158 vassert(i
< nX
); /* else we didn't find it! */
14159 UInt tReg
= xReg
[i
];
14160 UInt tOff
= xOff
[i
];
14162 /* load; make this transfer happen last */
14164 for (m
= i
+1; m
< nX
; m
++) {
14165 xReg
[m
-1] = xReg
[m
];
14166 xOff
[m
-1] = xOff
[m
];
14173 /* store; make this transfer happen first */
14175 for (m
= i
-1; m
>= 0; m
--) {
14176 xReg
[m
+1] = xReg
[m
];
14177 xOff
[m
+1] = xOff
[m
];
14186 vex_printf("REG_LIST_POST:\n");
14187 for (i
= 0; i
< nX
; i
++)
14188 vex_printf("reg %u off %u\n", xReg
[i
], xOff
[i
]);
14193 /* According to the Cortex A8 TRM Sec. 5.2.1, LDM(1) with r13 as the base
14194 register and PC in the register list is a return for purposes of branch
14196 The ARM ARM Sec. C9.10.1 further specifies that writeback must be enabled
14197 to be counted in event 0x0E (Procedure return).*/
14198 if (rN
== 13 && bL
== 1 && bINC
&& !bBEFORE
&& bW
== 1) {
14202 /* Actually generate the transfers */
14203 for (i
= 0; i
< nX
; i
++) {
14206 IRExpr
* e
= loadLE(Ity_I32
,
14207 binop(opADDorSUB
, mkexpr(anchorT
),
14210 putIRegA( r
, e
, IRTemp_INVALID
, jk
);
14212 // no: putIRegT( r, e, IRTemp_INVALID );
14213 // putIRegT refuses to write to R15. But that might happen.
14214 // Since this is uncond, and we need to be able to
14215 // write the PC, just use the low level put:
14219 /* if we're storing Rn, make sure we use the correct
14220 value, as per extensive comments above */
14221 storeLE( binop(opADDorSUB
, mkexpr(anchorT
), mkU32(xOff
[i
])),
14222 r
== rN
? mkexpr(oldRnT
)
14223 : (arm
? getIRegA(r
) : getIRegT(r
) ) );
14227 // If we are doing xxMIA or xxMIB,
14228 // do the transfer first, and then update rN afterwards.
14229 if (bW
== 1 && bINC
) {
14230 IRExpr
* e
= binop(opADDorSUB
, mkexpr(oldRnT
), mkU32(4*nRegs
));
14232 putIRegA( rN
, e
, IRTemp_INVALID
, Ijk_Boring
);
14234 putIRegT( rN
, e
, IRTemp_INVALID
);
14239 /*------------------------------------------------------------*/
14240 /*--- VFP (CP 10 and 11) instructions ---*/
14241 /*------------------------------------------------------------*/
14243 /* Both ARM and Thumb */
14245 /* Translate a CP10 or CP11 instruction. If successful, returns
14246 True and *dres may or may not be updated. If failure, returns
14247 False and doesn't change *dres nor create any IR.
14249 The ARM and Thumb encodings are identical for the low 28 bits of
14250 the insn (yay!) and that's what the caller must supply, iow, imm28
14251 has the top 4 bits masked out. Caller is responsible for
14252 determining whether the masked-out bits are valid for a CP10/11
14253 insn. The rules for the top 4 bits are:
14255 ARM: 0000 to 1110 allowed, and this is the gating condition.
14256 1111 (NV) is not allowed.
14258 Thumb: must be 1110. The gating condition is taken from
14259 ITSTATE in the normal way.
14261 Conditionalisation:
14263 Caller must supply an IRTemp 'condT' holding the gating condition,
14264 or IRTemp_INVALID indicating the insn is always executed.
14266 Caller must also supply an ARMCondcode 'cond'. This is only used
14267 for debug printing, no other purpose. For ARM, this is simply the
14268 top 4 bits of the original instruction. For Thumb, the condition
14269 is not (really) known until run time, and so ARMCondAL should be
14270 passed, only so that printing of these instructions does not show
14273 Finally, the caller must indicate whether this occurs in ARM or
14276 static Bool
decode_CP10_CP11_instruction (
14277 /*MOD*/DisResult
* dres
,
14284 # define INSN(_bMax,_bMin) SLICE_UInt(insn28, (_bMax), (_bMin))
14286 vassert(INSN(31,28) == BITS4(0,0,0,0)); // caller's obligation
14289 vassert(conq
== ARMCondAL
);
14291 vassert(conq
>= ARMCondEQ
&& conq
<= ARMCondAL
);
14294 /* ----------------------------------------------------------- */
14295 /* -- VFP instructions -- double precision (mostly) -- */
14296 /* ----------------------------------------------------------- */
14298 /* --------------------- fldmx, fstmx --------------------- */
14300 31 27 23 19 15 11 7 0
14302 C4-100, C5-26 1 FSTMX cond 1100 1000 Rn Dd 1011 offset
14303 C4-100, C5-28 2 FSTMIAX cond 1100 1010 Rn Dd 1011 offset
14304 C4-100, C5-30 3 FSTMDBX cond 1101 0010 Rn Dd 1011 offset
14306 C4-42, C5-26 1 FLDMX cond 1100 1001 Rn Dd 1011 offset
14307 C4-42, C5-28 2 FLDMIAX cond 1100 1011 Rn Dd 1011 offset
14308 C4-42, C5-30 3 FLDMDBX cond 1101 0011 Rn Dd 1011 offset
14310 Regs transferred: Dd .. D(d + (offset-3)/2)
14311 offset must be odd, must not imply a reg > 15
14312 IA/DB: Rn is changed by (4 + 8 x # regs transferred)
14315 1 at-Rn (access at Rn)
14316 2 ia-Rn (access at Rn, then Rn += 4+8n)
14317 3 db-Rn (Rn -= 4+8n, then access at Rn)
14319 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
14320 && INSN(11,8) == BITS4(1,0,1,1)) {
14321 UInt bP
= (insn28
>> 24) & 1;
14322 UInt bU
= (insn28
>> 23) & 1;
14323 UInt bW
= (insn28
>> 21) & 1;
14324 UInt bL
= (insn28
>> 20) & 1;
14325 UInt offset
= (insn28
>> 0) & 0xFF;
14326 UInt rN
= INSN(19,16);
14327 UInt dD
= (INSN(22,22) << 4) | INSN(15,12);
14328 UInt nRegs
= (offset
- 1) / 2;
14332 /**/ if (bP
== 0 && bU
== 1 && bW
== 0) {
14335 else if (bP
== 0 && bU
== 1 && bW
== 1) {
14338 else if (bP
== 1 && bU
== 0 && bW
== 1) {
14341 else goto after_vfp_fldmx_fstmx
;
14343 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */
14344 if (rN
== 15 && (summary
== 2 || summary
== 3 || isT
))
14345 goto after_vfp_fldmx_fstmx
;
14347 /* offset must be odd, and specify at least one register */
14348 if (0 == (offset
& 1) || offset
< 3)
14349 goto after_vfp_fldmx_fstmx
;
14351 /* can't transfer regs after D15 */
14352 if (dD
+ nRegs
- 1 >= 32)
14353 goto after_vfp_fldmx_fstmx
;
14355 /* Now, we can't do a conditional load or store, since that very
14356 likely will generate an exception. So we have to take a side
14357 exit at this point if the condition is false. */
14358 if (condT
!= IRTemp_INVALID
) {
14360 mk_skip_over_T32_if_cond_is_false( condT
);
14362 mk_skip_over_A32_if_cond_is_false( condT
);
14363 condT
= IRTemp_INVALID
;
14365 /* Ok, now we're unconditional. Do the load or store. */
14367 /* get the old Rn value */
14368 IRTemp rnT
= newTemp(Ity_I32
);
14369 assign(rnT
, align4if(isT
? getIRegT(rN
) : getIRegA(rN
),
14372 /* make a new value for Rn, post-insn */
14373 IRTemp rnTnew
= IRTemp_INVALID
;
14374 if (summary
== 2 || summary
== 3) {
14375 rnTnew
= newTemp(Ity_I32
);
14376 assign(rnTnew
, binop(summary
== 2 ? Iop_Add32
: Iop_Sub32
,
14378 mkU32(4 + 8 * nRegs
)));
14381 /* decide on the base transfer address */
14382 IRTemp taT
= newTemp(Ity_I32
);
14383 assign(taT
, summary
== 3 ? mkexpr(rnTnew
) : mkexpr(rnT
));
14385 /* update Rn if necessary -- in case 3, we're moving it down, so
14386 update before any memory reference, in order to keep Memcheck
14387 and V's stack-extending logic (on linux) happy */
14388 if (summary
== 3) {
14390 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
14392 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
14395 /* generate the transfers */
14396 for (i
= 0; i
< nRegs
; i
++) {
14397 IRExpr
* addr
= binop(Iop_Add32
, mkexpr(taT
), mkU32(8*i
));
14399 putDReg(dD
+ i
, loadLE(Ity_F64
, addr
), IRTemp_INVALID
);
14401 storeLE(addr
, getDReg(dD
+ i
));
14405 /* update Rn if necessary -- in case 2, we're moving it up, so
14406 update after any memory reference, in order to keep Memcheck
14407 and V's stack-extending logic (on linux) happy */
14408 if (summary
== 2) {
14410 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
14412 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
14415 const HChar
* nm
= bL
==1 ? "ld" : "st";
14417 case 1: DIP("f%smx%s r%u, {d%u-d%u}\n",
14418 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14420 case 2: DIP("f%smiax%s r%u!, {d%u-d%u}\n",
14421 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14423 case 3: DIP("f%smdbx%s r%u!, {d%u-d%u}\n",
14424 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14426 default: vassert(0);
14429 goto decode_success_vfp
;
14430 /* FIXME alignment constraints? */
14433 after_vfp_fldmx_fstmx
:
14435 /* --------------------- fldmd, fstmd --------------------- */
14437 31 27 23 19 15 11 7 0
14439 C4-96, C5-26 1 FSTMD cond 1100 1000 Rn Dd 1011 offset
14440 C4-96, C5-28 2 FSTMDIA cond 1100 1010 Rn Dd 1011 offset
14441 C4-96, C5-30 3 FSTMDDB cond 1101 0010 Rn Dd 1011 offset
14443 C4-38, C5-26 1 FLDMD cond 1100 1001 Rn Dd 1011 offset
14444 C4-38, C5-28 2 FLDMIAD cond 1100 1011 Rn Dd 1011 offset
14445 C4-38, C5-30 3 FLDMDBD cond 1101 0011 Rn Dd 1011 offset
14447 Regs transferred: Dd .. D(d + (offset-2)/2)
14448 offset must be even, must not imply a reg > 15
14449 IA/DB: Rn is changed by (8 x # regs transferred)
14452 1 at-Rn (access at Rn)
14453 2 ia-Rn (access at Rn, then Rn += 8n)
14454 3 db-Rn (Rn -= 8n, then access at Rn)
14456 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
14457 && INSN(11,8) == BITS4(1,0,1,1)) {
14458 UInt bP
= (insn28
>> 24) & 1;
14459 UInt bU
= (insn28
>> 23) & 1;
14460 UInt bW
= (insn28
>> 21) & 1;
14461 UInt bL
= (insn28
>> 20) & 1;
14462 UInt offset
= (insn28
>> 0) & 0xFF;
14463 UInt rN
= INSN(19,16);
14464 UInt dD
= (INSN(22,22) << 4) | INSN(15,12);
14465 UInt nRegs
= offset
/ 2;
14469 /**/ if (bP
== 0 && bU
== 1 && bW
== 0) {
14472 else if (bP
== 0 && bU
== 1 && bW
== 1) {
14475 else if (bP
== 1 && bU
== 0 && bW
== 1) {
14478 else goto after_vfp_fldmd_fstmd
;
14480 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */
14481 if (rN
== 15 && (summary
== 2 || summary
== 3 || isT
))
14482 goto after_vfp_fldmd_fstmd
;
14484 /* offset must be even, and specify at least one register */
14485 if (1 == (offset
& 1) || offset
< 2)
14486 goto after_vfp_fldmd_fstmd
;
14488 /* can't transfer regs after D15 */
14489 if (dD
+ nRegs
- 1 >= 32)
14490 goto after_vfp_fldmd_fstmd
;
14492 /* Now, we can't do a conditional load or store, since that very
14493 likely will generate an exception. So we have to take a side
14494 exit at this point if the condition is false. */
14495 if (condT
!= IRTemp_INVALID
) {
14497 mk_skip_over_T32_if_cond_is_false( condT
);
14499 mk_skip_over_A32_if_cond_is_false( condT
);
14500 condT
= IRTemp_INVALID
;
14502 /* Ok, now we're unconditional. Do the load or store. */
14504 /* get the old Rn value */
14505 IRTemp rnT
= newTemp(Ity_I32
);
14506 assign(rnT
, align4if(isT
? getIRegT(rN
) : getIRegA(rN
),
14509 /* make a new value for Rn, post-insn */
14510 IRTemp rnTnew
= IRTemp_INVALID
;
14511 if (summary
== 2 || summary
== 3) {
14512 rnTnew
= newTemp(Ity_I32
);
14513 assign(rnTnew
, binop(summary
== 2 ? Iop_Add32
: Iop_Sub32
,
14515 mkU32(8 * nRegs
)));
14518 /* decide on the base transfer address */
14519 IRTemp taT
= newTemp(Ity_I32
);
14520 assign(taT
, summary
== 3 ? mkexpr(rnTnew
) : mkexpr(rnT
));
14522 /* update Rn if necessary -- in case 3, we're moving it down, so
14523 update before any memory reference, in order to keep Memcheck
14524 and V's stack-extending logic (on linux) happy */
14525 if (summary
== 3) {
14527 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
14529 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
14532 /* generate the transfers */
14533 for (i
= 0; i
< nRegs
; i
++) {
14534 IRExpr
* addr
= binop(Iop_Add32
, mkexpr(taT
), mkU32(8*i
));
14536 putDReg(dD
+ i
, loadLE(Ity_F64
, addr
), IRTemp_INVALID
);
14538 storeLE(addr
, getDReg(dD
+ i
));
14542 /* update Rn if necessary -- in case 2, we're moving it up, so
14543 update after any memory reference, in order to keep Memcheck
14544 and V's stack-extending logic (on linux) happy */
14545 if (summary
== 2) {
14547 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
14549 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
14552 const HChar
* nm
= bL
==1 ? "ld" : "st";
14554 case 1: DIP("f%smd%s r%u, {d%u-d%u}\n",
14555 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14557 case 2: DIP("f%smiad%s r%u!, {d%u-d%u}\n",
14558 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14560 case 3: DIP("f%smdbd%s r%u!, {d%u-d%u}\n",
14561 nm
, nCC(conq
), rN
, dD
, dD
+ nRegs
- 1);
14563 default: vassert(0);
14566 goto decode_success_vfp
;
14567 /* FIXME alignment constraints? */
14570 after_vfp_fldmd_fstmd
:
14572 /* ------------------- fmrx, fmxr ------------------- */
14573 if (BITS8(1,1,1,0,1,1,1,1) == INSN(27,20)
14574 && BITS4(1,0,1,0) == INSN(11,8)
14575 && BITS8(0,0,0,1,0,0,0,0) == (insn28
& 0xFF)) {
14576 UInt rD
= INSN(15,12);
14577 UInt reg
= INSN(19,16);
14578 if (reg
== BITS4(0,0,0,1)) {
14580 IRTemp nzcvT
= newTemp(Ity_I32
);
14581 /* When rD is 15, we are copying the top 4 bits of FPSCR
14582 into CPSR. That is, set the flags thunk to COPY and
14583 install FPSCR[31:28] as the value to copy. */
14584 assign(nzcvT
, binop(Iop_And32
,
14585 IRExpr_Get(OFFB_FPSCR
, Ity_I32
),
14586 mkU32(0xF0000000)));
14587 setFlags_D1(ARMG_CC_OP_COPY
, nzcvT
, condT
);
14588 DIP("fmstat%s\n", nCC(conq
));
14590 /* Otherwise, merely transfer FPSCR to r0 .. r14. */
14591 IRExpr
* e
= IRExpr_Get(OFFB_FPSCR
, Ity_I32
);
14593 putIRegT(rD
, e
, condT
);
14595 putIRegA(rD
, e
, condT
, Ijk_Boring
);
14596 DIP("fmrx%s r%u, fpscr\n", nCC(conq
), rD
);
14598 goto decode_success_vfp
;
14603 if (BITS8(1,1,1,0,1,1,1,0) == INSN(27,20)
14604 && BITS4(1,0,1,0) == INSN(11,8)
14605 && BITS8(0,0,0,1,0,0,0,0) == (insn28
& 0xFF)) {
14606 UInt rD
= INSN(15,12);
14607 UInt reg
= INSN(19,16);
14608 if (reg
== BITS4(0,0,0,1)) {
14609 putMiscReg32(OFFB_FPSCR
,
14610 isT
? getIRegT(rD
) : getIRegA(rD
), condT
);
14611 DIP("fmxr%s fpscr, r%u\n", nCC(conq
), rD
);
14612 goto decode_success_vfp
;
14617 /* --------------------- vmov --------------------- */
14619 if (0x0C400B10 == (insn28
& 0x0FF00FD0)) {
14620 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
14621 UInt rD
= INSN(15,12); /* lo32 */
14622 UInt rN
= INSN(19,16); /* hi32 */
14623 if (rD
== 15 || rN
== 15 || (isT
&& (rD
== 13 || rN
== 13))) {
14627 unop(Iop_ReinterpI64asF64
,
14628 binop(Iop_32HLto64
,
14629 isT
? getIRegT(rN
) : getIRegA(rN
),
14630 isT
? getIRegT(rD
) : getIRegA(rD
))),
14632 DIP("vmov%s d%u, r%u, r%u\n", nCC(conq
), dM
, rD
, rN
);
14633 goto decode_success_vfp
;
14639 if (0x0C500B10 == (insn28
& 0x0FF00FD0)) {
14640 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
14641 UInt rD
= INSN(15,12); /* lo32 */
14642 UInt rN
= INSN(19,16); /* hi32 */
14643 if (rD
== 15 || rN
== 15 || (isT
&& (rD
== 13 || rN
== 13))
14647 IRTemp i64
= newTemp(Ity_I64
);
14648 assign(i64
, unop(Iop_ReinterpF64asI64
, getDReg(dM
)));
14649 IRExpr
* hi32
= unop(Iop_64HIto32
, mkexpr(i64
));
14650 IRExpr
* lo32
= unop(Iop_64to32
, mkexpr(i64
));
14652 putIRegT(rN
, hi32
, condT
);
14653 putIRegT(rD
, lo32
, condT
);
14655 putIRegA(rN
, hi32
, condT
, Ijk_Boring
);
14656 putIRegA(rD
, lo32
, condT
, Ijk_Boring
);
14658 DIP("vmov%s r%u, r%u, d%u\n", nCC(conq
), rD
, rN
, dM
);
14659 goto decode_success_vfp
;
14664 // VMOV sD, sD+1, rN, rM
14665 if (0x0C400A10 == (insn28
& 0x0FF00FD0)) {
14666 UInt sD
= (INSN(3,0) << 1) | INSN(5,5);
14667 UInt rN
= INSN(15,12);
14668 UInt rM
= INSN(19,16);
14669 if (rM
== 15 || rN
== 15 || (isT
&& (rM
== 13 || rN
== 13))
14674 unop(Iop_ReinterpI32asF32
, isT
? getIRegT(rN
) : getIRegA(rN
)),
14677 unop(Iop_ReinterpI32asF32
, isT
? getIRegT(rM
) : getIRegA(rM
)),
14679 DIP("vmov%s, s%u, s%u, r%u, r%u\n",
14680 nCC(conq
), sD
, sD
+ 1, rN
, rM
);
14681 goto decode_success_vfp
;
14685 // VMOV rN, rM, sD, sD+1
14686 if (0x0C500A10 == (insn28
& 0x0FF00FD0)) {
14687 UInt sD
= (INSN(3,0) << 1) | INSN(5,5);
14688 UInt rN
= INSN(15,12);
14689 UInt rM
= INSN(19,16);
14690 if (rM
== 15 || rN
== 15 || (isT
&& (rM
== 13 || rN
== 13))
14691 || sD
== 31 || rN
== rM
) {
14694 IRExpr
* res0
= unop(Iop_ReinterpF32asI32
, getFReg(sD
));
14695 IRExpr
* res1
= unop(Iop_ReinterpF32asI32
, getFReg(sD
+1));
14697 putIRegT(rN
, res0
, condT
);
14698 putIRegT(rM
, res1
, condT
);
14700 putIRegA(rN
, res0
, condT
, Ijk_Boring
);
14701 putIRegA(rM
, res1
, condT
, Ijk_Boring
);
14703 DIP("vmov%s, r%u, r%u, s%u, s%u\n",
14704 nCC(conq
), rN
, rM
, sD
, sD
+ 1);
14705 goto decode_success_vfp
;
14709 // VMOV rD[x], rT (ARM core register to scalar)
14710 if (0x0E000B10 == (insn28
& 0x0F900F1F)) {
14711 UInt rD
= (INSN(7,7) << 4) | INSN(19,16);
14712 UInt rT
= INSN(15,12);
14713 UInt opc
= (INSN(22,21) << 2) | INSN(6,5);
14715 if (rT
== 15 || (isT
&& rT
== 13)) {
14718 if ((opc
& BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
14720 putDRegI64(rD
, triop(Iop_SetElem8x8
,
14724 isT
? getIRegT(rT
) : getIRegA(rT
))),
14726 DIP("vmov%s.8 d%u[%u], r%u\n", nCC(conq
), rD
, index
, rT
);
14727 goto decode_success_vfp
;
14729 else if ((opc
& BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
14730 index
= (opc
>> 1) & 3;
14731 putDRegI64(rD
, triop(Iop_SetElem16x4
,
14735 isT
? getIRegT(rT
) : getIRegA(rT
))),
14737 DIP("vmov%s.16 d%u[%u], r%u\n", nCC(conq
), rD
, index
, rT
);
14738 goto decode_success_vfp
;
14740 else if ((opc
& BITS4(1,0,1,1)) == BITS4(0,0,0,0)) {
14741 index
= (opc
>> 2) & 1;
14742 putDRegI64(rD
, triop(Iop_SetElem32x2
,
14745 isT
? getIRegT(rT
) : getIRegA(rT
)),
14747 DIP("vmov%s.32 d%u[%u], r%u\n", nCC(conq
), rD
, index
, rT
);
14748 goto decode_success_vfp
;
14755 // VMOV (scalar to ARM core register)
14757 if (0x0E100B10 == (insn28
& 0x0F100F1F)) {
14758 UInt rN
= (INSN(7,7) << 4) | INSN(19,16);
14759 UInt rT
= INSN(15,12);
14760 UInt U
= INSN(23,23);
14761 UInt opc
= (INSN(22,21) << 2) | INSN(6,5);
14763 if (rT
== 15 || (isT
&& rT
== 13)) {
14766 if ((opc
& BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
14768 IRExpr
* e
= unop(U
? Iop_8Uto32
: Iop_8Sto32
,
14769 binop(Iop_GetElem8x8
,
14773 putIRegT(rT
, e
, condT
);
14775 putIRegA(rT
, e
, condT
, Ijk_Boring
);
14776 DIP("vmov%s.%c8 r%u, d%u[%u]\n", nCC(conq
), U
? 'u' : 's',
14778 goto decode_success_vfp
;
14780 else if ((opc
& BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
14781 index
= (opc
>> 1) & 3;
14782 IRExpr
* e
= unop(U
? Iop_16Uto32
: Iop_16Sto32
,
14783 binop(Iop_GetElem16x4
,
14787 putIRegT(rT
, e
, condT
);
14789 putIRegA(rT
, e
, condT
, Ijk_Boring
);
14790 DIP("vmov%s.%c16 r%u, d%u[%u]\n", nCC(conq
), U
? 'u' : 's',
14792 goto decode_success_vfp
;
14794 else if ((opc
& BITS4(1,0,1,1)) == BITS4(0,0,0,0) && U
== 0) {
14795 index
= (opc
>> 2) & 1;
14796 IRExpr
* e
= binop(Iop_GetElem32x2
, getDRegI64(rN
), mkU8(index
));
14798 putIRegT(rT
, e
, condT
);
14800 putIRegA(rT
, e
, condT
, Ijk_Boring
);
14801 DIP("vmov%s.32 r%u, d%u[%u]\n", nCC(conq
), rT
, rN
, index
);
14802 goto decode_success_vfp
;
14809 // VMOV.F32 sD, #imm
14810 // FCONSTS sD, #imm
14811 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
14812 && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,0)) {
14813 UInt rD
= (INSN(15,12) << 1) | INSN(22,22);
14814 UInt imm8
= (INSN(19,16) << 4) | INSN(3,0);
14815 UInt b
= (imm8
>> 6) & 1;
14817 imm
= (BITS8((imm8
>> 7) & 1,(~b
) & 1,b
,b
,b
,b
,b
,(imm8
>> 5) & 1) << 8)
14818 | ((imm8
& 0x1f) << 3);
14820 putFReg(rD
, unop(Iop_ReinterpI32asF32
, mkU32(imm
)), condT
);
14821 DIP("fconsts%s s%u #%u", nCC(conq
), rD
, imm8
);
14822 goto decode_success_vfp
;
14825 // VMOV.F64 dD, #imm
14826 // FCONSTD dD, #imm
14827 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
14828 && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,1)) {
14829 UInt rD
= INSN(15,12) | (INSN(22,22) << 4);
14830 UInt imm8
= (INSN(19,16) << 4) | INSN(3,0);
14831 UInt b
= (imm8
>> 6) & 1;
14833 imm
= (BITS8((imm8
>> 7) & 1,(~b
) & 1,b
,b
,b
,b
,b
,b
) << 8)
14834 | BITS8(b
,b
,0,0,0,0,0,0) | (imm8
& 0x3f);
14836 putDReg(rD
, unop(Iop_ReinterpI64asF64
, mkU64(imm
)), condT
);
14837 DIP("fconstd%s d%u #%u", nCC(conq
), rD
, imm8
);
14838 goto decode_success_vfp
;
14841 /* ---------------------- vdup ------------------------- */
14844 if (BITS8(1,1,1,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,1))
14845 && BITS4(1,0,1,1) == INSN(11,8) && INSN(6,6) == 0 && INSN(4,4) == 1) {
14846 UInt rD
= (INSN(7,7) << 4) | INSN(19,16);
14847 UInt rT
= INSN(15,12);
14848 UInt Q
= INSN(21,21);
14849 UInt size
= (INSN(22,22) << 1) | INSN(5,5);
14850 if (rT
== 15 || (isT
&& rT
== 13) || size
== 3 || (Q
&& (rD
& 1))) {
14853 IRExpr
* e
= isT
? getIRegT(rT
) : getIRegA(rT
);
14858 putQReg(rD
, unop(Iop_Dup32x4
, e
), condT
);
14861 putQReg(rD
, unop(Iop_Dup16x8
, unop(Iop_32to16
, e
)),
14865 putQReg(rD
, unop(Iop_Dup8x16
, unop(Iop_32to8
, e
)),
14871 DIP("vdup.%d q%u, r%u\n", 32 / (1<<size
), rD
, rT
);
14875 putDRegI64(rD
, unop(Iop_Dup32x2
, e
), condT
);
14878 putDRegI64(rD
, unop(Iop_Dup16x4
, unop(Iop_32to16
, e
)),
14882 putDRegI64(rD
, unop(Iop_Dup8x8
, unop(Iop_32to8
, e
)),
14888 DIP("vdup.%d d%u, r%u\n", 32 / (1<<size
), rD
, rT
);
14890 goto decode_success_vfp
;
14894 /* --------------------- f{ld,st}d --------------------- */
14896 if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
14897 && BITS4(1,0,1,1) == INSN(11,8)) {
14898 UInt dD
= INSN(15,12) | (INSN(22,22) << 4);
14899 UInt rN
= INSN(19,16);
14900 UInt offset
= (insn28
& 0xFF) << 2;
14901 UInt bU
= (insn28
>> 23) & 1; /* 1: +offset 0: -offset */
14902 UInt bL
= (insn28
>> 20) & 1; /* 1: load 0: store */
14903 /* make unconditional */
14904 if (condT
!= IRTemp_INVALID
) {
14906 mk_skip_over_T32_if_cond_is_false( condT
);
14908 mk_skip_over_A32_if_cond_is_false( condT
);
14909 condT
= IRTemp_INVALID
;
14911 IRTemp ea
= newTemp(Ity_I32
);
14912 assign(ea
, binop(bU
? Iop_Add32
: Iop_Sub32
,
14913 align4if(isT
? getIRegT(rN
) : getIRegA(rN
),
14917 putDReg(dD
, loadLE(Ity_F64
,mkexpr(ea
)), IRTemp_INVALID
);
14919 storeLE(mkexpr(ea
), getDReg(dD
));
14921 DIP("f%sd%s d%u, [r%u, %c#%u]\n",
14922 bL
? "ld" : "st", nCC(conq
), dD
, rN
,
14923 bU
? '+' : '-', offset
);
14924 goto decode_success_vfp
;
14927 /* --------------------- dp insns (D) --------------------- */
14928 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
14929 && BITS4(1,0,1,1) == INSN(11,8)
14930 && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
14931 UInt dM
= INSN(3,0) | (INSN(5,5) << 4); /* argR */
14932 UInt dD
= INSN(15,12) | (INSN(22,22) << 4); /* dst/acc */
14933 UInt dN
= INSN(19,16) | (INSN(7,7) << 4); /* argL */
14934 UInt bP
= (insn28
>> 23) & 1;
14935 UInt bQ
= (insn28
>> 21) & 1;
14936 UInt bR
= (insn28
>> 20) & 1;
14937 UInt bS
= (insn28
>> 6) & 1;
14938 UInt opc
= (bP
<< 3) | (bQ
<< 2) | (bR
<< 1) | bS
;
14939 IRExpr
* rm
= get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
14941 case BITS4(0,0,0,0): /* MAC: d + n * m */
14942 putDReg(dD
, triop(Iop_AddF64
, rm
,
14944 triop(Iop_MulF64
, rm
, getDReg(dN
),
14947 DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14948 goto decode_success_vfp
;
14949 case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
14950 putDReg(dD
, triop(Iop_AddF64
, rm
,
14953 triop(Iop_MulF64
, rm
, getDReg(dN
),
14956 DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14957 goto decode_success_vfp
;
14958 case BITS4(0,0,1,0): /* MSC: - d + n * m */
14959 putDReg(dD
, triop(Iop_AddF64
, rm
,
14960 unop(Iop_NegF64
, getDReg(dD
)),
14961 triop(Iop_MulF64
, rm
, getDReg(dN
),
14964 DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14965 goto decode_success_vfp
;
14966 case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
14967 putDReg(dD
, triop(Iop_AddF64
, rm
,
14968 unop(Iop_NegF64
, getDReg(dD
)),
14970 triop(Iop_MulF64
, rm
, getDReg(dN
),
14973 DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14974 goto decode_success_vfp
;
14975 case BITS4(0,1,0,0): /* MUL: n * m */
14976 putDReg(dD
, triop(Iop_MulF64
, rm
, getDReg(dN
), getDReg(dM
)),
14978 DIP("fmuld%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14979 goto decode_success_vfp
;
14980 case BITS4(0,1,0,1): /* NMUL: - n * m */
14981 putDReg(dD
, unop(Iop_NegF64
,
14982 triop(Iop_MulF64
, rm
, getDReg(dN
),
14985 DIP("fnmuld%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14986 goto decode_success_vfp
;
14987 case BITS4(0,1,1,0): /* ADD: n + m */
14988 putDReg(dD
, triop(Iop_AddF64
, rm
, getDReg(dN
), getDReg(dM
)),
14990 DIP("faddd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14991 goto decode_success_vfp
;
14992 case BITS4(0,1,1,1): /* SUB: n - m */
14993 putDReg(dD
, triop(Iop_SubF64
, rm
, getDReg(dN
), getDReg(dM
)),
14995 DIP("fsubd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
14996 goto decode_success_vfp
;
14997 case BITS4(1,0,0,0): /* DIV: n / m */
14998 putDReg(dD
, triop(Iop_DivF64
, rm
, getDReg(dN
), getDReg(dM
)),
15000 DIP("fdivd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
15001 goto decode_success_vfp
;
15002 case BITS4(1,0,1,0): /* VNFMS: -(d - n * m) (fused) */
15003 /* XXXROUNDINGFIXME look up ARM reference for fused
15004 multiply-add rounding */
15005 putDReg(dD
, triop(Iop_AddF64
, rm
,
15006 unop(Iop_NegF64
, getDReg(dD
)),
15007 triop(Iop_MulF64
, rm
,
15011 DIP("vfnmsd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
15012 goto decode_success_vfp
;
15013 case BITS4(1,0,1,1): /* VNFMA: -(d + n * m) (fused) */
15014 /* XXXROUNDINGFIXME look up ARM reference for fused
15015 multiply-add rounding */
15016 putDReg(dD
, triop(Iop_AddF64
, rm
,
15017 unop(Iop_NegF64
, getDReg(dD
)),
15018 triop(Iop_MulF64
, rm
,
15019 unop(Iop_NegF64
, getDReg(dN
)),
15022 DIP("vfnmad%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
15023 goto decode_success_vfp
;
15024 case BITS4(1,1,0,0): /* VFMA: d + n * m (fused) */
15025 /* XXXROUNDINGFIXME look up ARM reference for fused
15026 multiply-add rounding */
15027 putDReg(dD
, triop(Iop_AddF64
, rm
,
15029 triop(Iop_MulF64
, rm
, getDReg(dN
),
15032 DIP("vfmad%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
15033 goto decode_success_vfp
;
15034 case BITS4(1,1,0,1): /* VFMS: d + (-n * m) (fused) */
15035 /* XXXROUNDINGFIXME look up ARM reference for fused
15036 multiply-add rounding */
15037 putDReg(dD
, triop(Iop_AddF64
, rm
,
15039 triop(Iop_MulF64
, rm
,
15040 unop(Iop_NegF64
, getDReg(dN
)),
15043 DIP("vfmsd%s d%u, d%u, d%u\n", nCC(conq
), dD
, dN
, dM
);
15044 goto decode_success_vfp
;
15050 /* --------------------- compares (D) --------------------- */
15051 /* 31 27 23 19 15 11 7 3
15052 28 24 20 16 12 8 4 0
15053 FCMPD cond 1110 1D11 0100 Dd 1011 0100 Dm
15054 FCMPED cond 1110 1D11 0100 Dd 1011 1100 Dm
15055 FCMPZD cond 1110 1D11 0101 Dd 1011 0100 0000
15056 FCMPZED cond 1110 1D11 0101 Dd 1011 1100 0000
15059 Z=0 Compare Dd vs Dm and set FPSCR 31:28 accordingly
15060 Z=1 Compare Dd vs zero
15062 N=1 generates Invalid Operation exn if either arg is any kind of NaN
15063 N=0 generates Invalid Operation exn if either arg is a signalling NaN
15064 (Not that we pay any attention to N here)
15066 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15067 && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15068 && BITS4(1,0,1,1) == INSN(11,8)
15069 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15070 UInt bZ
= (insn28
>> 16) & 1;
15071 UInt bN
= (insn28
>> 7) & 1;
15072 UInt dD
= INSN(15,12) | (INSN(22,22) << 4);
15073 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
15074 if (bZ
&& INSN(3,0) != 0) {
15075 /* does not decode; fall through */
15077 IRTemp argL
= newTemp(Ity_F64
);
15078 IRTemp argR
= newTemp(Ity_F64
);
15079 IRTemp irRes
= newTemp(Ity_I32
);
15080 assign(argL
, getDReg(dD
));
15081 assign(argR
, bZ
? IRExpr_Const(IRConst_F64i(0)) : getDReg(dM
));
15082 assign(irRes
, binop(Iop_CmpF64
, mkexpr(argL
), mkexpr(argR
)));
15084 IRTemp nzcv
= IRTemp_INVALID
;
15085 IRTemp oldFPSCR
= newTemp(Ity_I32
);
15086 IRTemp newFPSCR
= newTemp(Ity_I32
);
15088 /* This is where the fun starts. We have to convert 'irRes'
15089 from an IR-convention return result (IRCmpF64Result) to an
15090 ARM-encoded (N,Z,C,V) group. The final result is in the
15091 bottom 4 bits of 'nzcv'. */
15092 /* Map compare result from IR to ARM(nzcv) */
15094 FP cmp result | IR | ARM(nzcv)
15095 --------------------------------
15101 nzcv
= mk_convert_IRCmpF64Result_to_NZCV(irRes
);
15103 /* And update FPSCR accordingly */
15104 assign(oldFPSCR
, IRExpr_Get(OFFB_FPSCR
, Ity_I32
));
15107 binop(Iop_And32
, mkexpr(oldFPSCR
), mkU32(0x0FFFFFFF)),
15108 binop(Iop_Shl32
, mkexpr(nzcv
), mkU8(28))));
15110 putMiscReg32(OFFB_FPSCR
, mkexpr(newFPSCR
), condT
);
15113 DIP("fcmpz%sd%s d%u\n", bN
? "e" : "", nCC(conq
), dD
);
15115 DIP("fcmp%sd%s d%u, d%u\n", bN
? "e" : "", nCC(conq
), dD
, dM
);
15117 goto decode_success_vfp
;
15122 /* --------------------- unary (D) --------------------- */
15123 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15124 && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15125 && BITS4(1,0,1,1) == INSN(11,8)
15126 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15127 UInt dD
= INSN(15,12) | (INSN(22,22) << 4);
15128 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
15129 UInt b16
= (insn28
>> 16) & 1;
15130 UInt b7
= (insn28
>> 7) & 1;
15131 /**/ if (b16
== 0 && b7
== 0) {
15133 putDReg(dD
, getDReg(dM
), condT
);
15134 DIP("fcpyd%s d%u, d%u\n", nCC(conq
), dD
, dM
);
15135 goto decode_success_vfp
;
15137 else if (b16
== 0 && b7
== 1) {
15139 putDReg(dD
, unop(Iop_AbsF64
, getDReg(dM
)), condT
);
15140 DIP("fabsd%s d%u, d%u\n", nCC(conq
), dD
, dM
);
15141 goto decode_success_vfp
;
15143 else if (b16
== 1 && b7
== 0) {
15145 putDReg(dD
, unop(Iop_NegF64
, getDReg(dM
)), condT
);
15146 DIP("fnegd%s d%u, d%u\n", nCC(conq
), dD
, dM
);
15147 goto decode_success_vfp
;
15149 else if (b16
== 1 && b7
== 1) {
15151 IRExpr
* rm
= get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
15152 putDReg(dD
, binop(Iop_SqrtF64
, rm
, getDReg(dM
)), condT
);
15153 DIP("fsqrtd%s d%u, d%u\n", nCC(conq
), dD
, dM
);
15154 goto decode_success_vfp
;
15162 /* ----------------- I <-> D conversions ----------------- */
15164 // F{S,U}ITOD dD, fM
15165 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15166 && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1))
15167 && BITS4(1,0,1,1) == INSN(11,8)
15168 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15169 UInt bM
= (insn28
>> 5) & 1;
15170 UInt fM
= (INSN(3,0) << 1) | bM
;
15171 UInt dD
= INSN(15,12) | (INSN(22,22) << 4);
15172 UInt syned
= (insn28
>> 7) & 1;
15175 putDReg(dD
, unop(Iop_I32StoF64
,
15176 unop(Iop_ReinterpF32asI32
, getFReg(fM
))),
15178 DIP("fsitod%s d%u, s%u\n", nCC(conq
), dD
, fM
);
15181 putDReg(dD
, unop(Iop_I32UtoF64
,
15182 unop(Iop_ReinterpF32asI32
, getFReg(fM
))),
15184 DIP("fuitod%s d%u, s%u\n", nCC(conq
), dD
, fM
);
15186 goto decode_success_vfp
;
15189 // FTO{S,U}ID fD, dM
15190 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15191 && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15192 && BITS4(1,0,1,1) == INSN(11,8)
15193 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15194 UInt bD
= (insn28
>> 22) & 1;
15195 UInt fD
= (INSN(15,12) << 1) | bD
;
15196 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
15197 UInt bZ
= (insn28
>> 7) & 1;
15198 UInt syned
= (insn28
>> 16) & 1;
15199 IRTemp rmode
= newTemp(Ity_I32
);
15200 assign(rmode
, bZ
? mkU32(Irrm_ZERO
)
15201 : mkexpr(mk_get_IR_rounding_mode()));
15204 putFReg(fD
, unop(Iop_ReinterpI32asF32
,
15205 binop(Iop_F64toI32S
, mkexpr(rmode
),
15208 DIP("ftosi%sd%s s%u, d%u\n", bZ
? "z" : "",
15209 nCC(conq
), fD
, dM
);
15212 putFReg(fD
, unop(Iop_ReinterpI32asF32
,
15213 binop(Iop_F64toI32U
, mkexpr(rmode
),
15216 DIP("ftoui%sd%s s%u, d%u\n", bZ
? "z" : "",
15217 nCC(conq
), fD
, dM
);
15219 goto decode_success_vfp
;
15222 /* ----------------------------------------------------------- */
15223 /* -- VFP instructions -- single precision -- */
15224 /* ----------------------------------------------------------- */
15226 /* --------------------- fldms, fstms --------------------- */
15228 31 27 23 19 15 11 7 0
15230 C4-98, C5-26 1 FSTMD cond 1100 1x00 Rn Fd 1010 offset
15231 C4-98, C5-28 2 FSTMDIA cond 1100 1x10 Rn Fd 1010 offset
15232 C4-98, C5-30 3 FSTMDDB cond 1101 0x10 Rn Fd 1010 offset
15234 C4-40, C5-26 1 FLDMD cond 1100 1x01 Rn Fd 1010 offset
15235 C4-40, C5-26 2 FLDMIAD cond 1100 1x11 Rn Fd 1010 offset
15236 C4-40, C5-26 3 FLDMDBD cond 1101 0x11 Rn Fd 1010 offset
15238 Regs transferred: F(Fd:D) .. F(Fd:d + offset)
15239 offset must not imply a reg > 15
15240 IA/DB: Rn is changed by (4 x # regs transferred)
15243 1 at-Rn (access at Rn)
15244 2 ia-Rn (access at Rn, then Rn += 4n)
15245 3 db-Rn (Rn -= 4n, then access at Rn)
15247 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
15248 && INSN(11,8) == BITS4(1,0,1,0)) {
15249 UInt bP
= (insn28
>> 24) & 1;
15250 UInt bU
= (insn28
>> 23) & 1;
15251 UInt bW
= (insn28
>> 21) & 1;
15252 UInt bL
= (insn28
>> 20) & 1;
15253 UInt bD
= (insn28
>> 22) & 1;
15254 UInt offset
= (insn28
>> 0) & 0xFF;
15255 UInt rN
= INSN(19,16);
15256 UInt fD
= (INSN(15,12) << 1) | bD
;
15257 UInt nRegs
= offset
;
15261 /**/ if (bP
== 0 && bU
== 1 && bW
== 0) {
15264 else if (bP
== 0 && bU
== 1 && bW
== 1) {
15267 else if (bP
== 1 && bU
== 0 && bW
== 1) {
15270 else goto after_vfp_fldms_fstms
;
15272 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */
15273 if (rN
== 15 && (summary
== 2 || summary
== 3 || isT
))
15274 goto after_vfp_fldms_fstms
;
15276 /* offset must specify at least one register */
15278 goto after_vfp_fldms_fstms
;
15280 /* can't transfer regs after S31 */
15281 if (fD
+ nRegs
- 1 >= 32)
15282 goto after_vfp_fldms_fstms
;
15284 /* Now, we can't do a conditional load or store, since that very
15285 likely will generate an exception. So we have to take a side
15286 exit at this point if the condition is false. */
15287 if (condT
!= IRTemp_INVALID
) {
15289 mk_skip_over_T32_if_cond_is_false( condT
);
15291 mk_skip_over_A32_if_cond_is_false( condT
);
15292 condT
= IRTemp_INVALID
;
15294 /* Ok, now we're unconditional. Do the load or store. */
15296 /* get the old Rn value */
15297 IRTemp rnT
= newTemp(Ity_I32
);
15298 assign(rnT
, align4if(isT
? getIRegT(rN
) : getIRegA(rN
),
15301 /* make a new value for Rn, post-insn */
15302 IRTemp rnTnew
= IRTemp_INVALID
;
15303 if (summary
== 2 || summary
== 3) {
15304 rnTnew
= newTemp(Ity_I32
);
15305 assign(rnTnew
, binop(summary
== 2 ? Iop_Add32
: Iop_Sub32
,
15307 mkU32(4 * nRegs
)));
15310 /* decide on the base transfer address */
15311 IRTemp taT
= newTemp(Ity_I32
);
15312 assign(taT
, summary
== 3 ? mkexpr(rnTnew
) : mkexpr(rnT
));
15314 /* update Rn if necessary -- in case 3, we're moving it down, so
15315 update before any memory reference, in order to keep Memcheck
15316 and V's stack-extending logic (on linux) happy */
15317 if (summary
== 3) {
15319 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
15321 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
15324 /* generate the transfers */
15325 for (i
= 0; i
< nRegs
; i
++) {
15326 IRExpr
* addr
= binop(Iop_Add32
, mkexpr(taT
), mkU32(4*i
));
15328 putFReg(fD
+ i
, loadLE(Ity_F32
, addr
), IRTemp_INVALID
);
15330 storeLE(addr
, getFReg(fD
+ i
));
15334 /* update Rn if necessary -- in case 2, we're moving it up, so
15335 update after any memory reference, in order to keep Memcheck
15336 and V's stack-extending logic (on linux) happy */
15337 if (summary
== 2) {
15339 putIRegT(rN
, mkexpr(rnTnew
), IRTemp_INVALID
);
15341 putIRegA(rN
, mkexpr(rnTnew
), IRTemp_INVALID
, Ijk_Boring
);
15344 const HChar
* nm
= bL
==1 ? "ld" : "st";
15346 case 1: DIP("f%sms%s r%u, {s%u-s%u}\n",
15347 nm
, nCC(conq
), rN
, fD
, fD
+ nRegs
- 1);
15349 case 2: DIP("f%smias%s r%u!, {s%u-s%u}\n",
15350 nm
, nCC(conq
), rN
, fD
, fD
+ nRegs
- 1);
15352 case 3: DIP("f%smdbs%s r%u!, {s%u-s%u}\n",
15353 nm
, nCC(conq
), rN
, fD
, fD
+ nRegs
- 1);
15355 default: vassert(0);
15358 goto decode_success_vfp
;
15359 /* FIXME alignment constraints? */
15362 after_vfp_fldms_fstms
:
15364 /* --------------------- fmsr, fmrs --------------------- */
15365 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
15366 && BITS4(1,0,1,0) == INSN(11,8)
15367 && BITS4(0,0,0,0) == INSN(3,0)
15368 && BITS4(0,0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
15369 UInt rD
= INSN(15,12);
15370 UInt b7
= (insn28
>> 7) & 1;
15371 UInt fN
= (INSN(19,16) << 1) | b7
;
15372 UInt b20
= (insn28
>> 20) & 1;
15375 /* Let's assume that no sane person would want to do
15376 floating-point transfers to or from the program counter,
15377 and simply decline to decode the instruction. The ARM ARM
15378 doesn't seem to explicitly disallow this case, though. */
15381 IRExpr
* res
= unop(Iop_ReinterpF32asI32
, getFReg(fN
));
15383 putIRegT(rD
, res
, condT
);
15385 putIRegA(rD
, res
, condT
, Ijk_Boring
);
15386 DIP("fmrs%s r%u, s%u\n", nCC(conq
), rD
, fN
);
15388 putFReg(fN
, unop(Iop_ReinterpI32asF32
,
15389 isT
? getIRegT(rD
) : getIRegA(rD
)),
15391 DIP("fmsr%s s%u, r%u\n", nCC(conq
), fN
, rD
);
15393 goto decode_success_vfp
;
15398 /* --------------------- f{ld,st}s --------------------- */
15400 if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
15401 && BITS4(1,0,1,0) == INSN(11,8)) {
15402 UInt bD
= (insn28
>> 22) & 1;
15403 UInt fD
= (INSN(15,12) << 1) | bD
;
15404 UInt rN
= INSN(19,16);
15405 UInt offset
= (insn28
& 0xFF) << 2;
15406 UInt bU
= (insn28
>> 23) & 1; /* 1: +offset 0: -offset */
15407 UInt bL
= (insn28
>> 20) & 1; /* 1: load 0: store */
15408 /* make unconditional */
15409 if (condT
!= IRTemp_INVALID
) {
15411 mk_skip_over_T32_if_cond_is_false( condT
);
15413 mk_skip_over_A32_if_cond_is_false( condT
);
15414 condT
= IRTemp_INVALID
;
15416 IRTemp ea
= newTemp(Ity_I32
);
15417 assign(ea
, binop(bU
? Iop_Add32
: Iop_Sub32
,
15418 align4if(isT
? getIRegT(rN
) : getIRegA(rN
),
15422 putFReg(fD
, loadLE(Ity_F32
,mkexpr(ea
)), IRTemp_INVALID
);
15424 storeLE(mkexpr(ea
), getFReg(fD
));
15426 DIP("f%ss%s s%u, [r%u, %c#%u]\n",
15427 bL
? "ld" : "st", nCC(conq
), fD
, rN
,
15428 bU
? '+' : '-', offset
);
15429 goto decode_success_vfp
;
15432 /* --------------------- dp insns (F) --------------------- */
15433 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
15434 && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
15435 && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
15436 UInt bM
= (insn28
>> 5) & 1;
15437 UInt bD
= (insn28
>> 22) & 1;
15438 UInt bN
= (insn28
>> 7) & 1;
15439 UInt fM
= (INSN(3,0) << 1) | bM
; /* argR */
15440 UInt fD
= (INSN(15,12) << 1) | bD
; /* dst/acc */
15441 UInt fN
= (INSN(19,16) << 1) | bN
; /* argL */
15442 UInt bP
= (insn28
>> 23) & 1;
15443 UInt bQ
= (insn28
>> 21) & 1;
15444 UInt bR
= (insn28
>> 20) & 1;
15445 UInt bS
= (insn28
>> 6) & 1;
15446 UInt opc
= (bP
<< 3) | (bQ
<< 2) | (bR
<< 1) | bS
;
15447 IRExpr
* rm
= get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
15449 case BITS4(0,0,0,0): /* MAC: d + n * m */
15450 putFReg(fD
, triop(Iop_AddF32
, rm
,
15452 triop(Iop_MulF32
, rm
, getFReg(fN
), getFReg(fM
))),
15454 DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15455 goto decode_success_vfp
;
15456 case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
15457 putFReg(fD
, triop(Iop_AddF32
, rm
,
15460 triop(Iop_MulF32
, rm
, getFReg(fN
),
15463 DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15464 goto decode_success_vfp
;
15465 case BITS4(0,0,1,0): /* MSC: - d + n * m */
15466 putFReg(fD
, triop(Iop_AddF32
, rm
,
15467 unop(Iop_NegF32
, getFReg(fD
)),
15468 triop(Iop_MulF32
, rm
, getFReg(fN
), getFReg(fM
))),
15470 DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15471 goto decode_success_vfp
;
15472 case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
15473 putFReg(fD
, triop(Iop_AddF32
, rm
,
15474 unop(Iop_NegF32
, getFReg(fD
)),
15476 triop(Iop_MulF32
, rm
,
15480 DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15481 goto decode_success_vfp
;
15482 case BITS4(0,1,0,0): /* MUL: n * m */
15483 putFReg(fD
, triop(Iop_MulF32
, rm
, getFReg(fN
), getFReg(fM
)),
15485 DIP("fmuls%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15486 goto decode_success_vfp
;
15487 case BITS4(0,1,0,1): /* NMUL: - n * m */
15488 putFReg(fD
, unop(Iop_NegF32
,
15489 triop(Iop_MulF32
, rm
, getFReg(fN
),
15492 DIP("fnmuls%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15493 goto decode_success_vfp
;
15494 case BITS4(0,1,1,0): /* ADD: n + m */
15495 putFReg(fD
, triop(Iop_AddF32
, rm
, getFReg(fN
), getFReg(fM
)),
15497 DIP("fadds%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15498 goto decode_success_vfp
;
15499 case BITS4(0,1,1,1): /* SUB: n - m */
15500 putFReg(fD
, triop(Iop_SubF32
, rm
, getFReg(fN
), getFReg(fM
)),
15502 DIP("fsubs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15503 goto decode_success_vfp
;
15504 case BITS4(1,0,0,0): /* DIV: n / m */
15505 putFReg(fD
, triop(Iop_DivF32
, rm
, getFReg(fN
), getFReg(fM
)),
15507 DIP("fdivs%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15508 goto decode_success_vfp
;
15509 case BITS4(1,0,1,0): /* VNFMS: -(d - n * m) (fused) */
15510 /* XXXROUNDINGFIXME look up ARM reference for fused
15511 multiply-add rounding */
15512 putFReg(fD
, triop(Iop_AddF32
, rm
,
15513 unop(Iop_NegF32
, getFReg(fD
)),
15514 triop(Iop_MulF32
, rm
,
15518 DIP("vfnmss%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15519 goto decode_success_vfp
;
15520 case BITS4(1,0,1,1): /* VNFMA: -(d + n * m) (fused) */
15521 /* XXXROUNDINGFIXME look up ARM reference for fused
15522 multiply-add rounding */
15523 putFReg(fD
, triop(Iop_AddF32
, rm
,
15524 unop(Iop_NegF32
, getFReg(fD
)),
15525 triop(Iop_MulF32
, rm
,
15526 unop(Iop_NegF32
, getFReg(fN
)),
15529 DIP("vfnmas%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15530 goto decode_success_vfp
;
15531 case BITS4(1,1,0,0): /* VFMA: d + n * m (fused) */
15532 /* XXXROUNDINGFIXME look up ARM reference for fused
15533 multiply-add rounding */
15534 putFReg(fD
, triop(Iop_AddF32
, rm
,
15536 triop(Iop_MulF32
, rm
, getFReg(fN
),
15539 DIP("vfmas%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15540 goto decode_success_vfp
;
15541 case BITS4(1,1,0,1): /* VFMS: d + (-n * m) (fused) */
15542 /* XXXROUNDINGFIXME look up ARM reference for fused
15543 multiply-add rounding */
15544 putFReg(fD
, triop(Iop_AddF32
, rm
,
15546 triop(Iop_MulF32
, rm
,
15547 unop(Iop_NegF32
, getFReg(fN
)),
15550 DIP("vfmss%s s%u, s%u, s%u\n", nCC(conq
), fD
, fN
, fM
);
15551 goto decode_success_vfp
;
15557 /* --------------------- compares (S) --------------------- */
15558 /* 31 27 23 19 15 11 7 3
15559 28 24 20 16 12 8 4 0
15560 FCMPS cond 1110 1D11 0100 Fd 1010 01M0 Fm
15561 FCMPES cond 1110 1D11 0100 Fd 1010 11M0 Fm
15562 FCMPZS cond 1110 1D11 0101 Fd 1010 0100 0000
15563 FCMPZED cond 1110 1D11 0101 Fd 1010 1100 0000
15566 Z=0 Compare Fd:D vs Fm:M and set FPSCR 31:28 accordingly
15567 Z=1 Compare Fd:D vs zero
15569 N=1 generates Invalid Operation exn if either arg is any kind of NaN
15570 N=0 generates Invalid Operation exn if either arg is a signalling NaN
15571 (Not that we pay any attention to N here)
15573 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15574 && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15575 && BITS4(1,0,1,0) == INSN(11,8)
15576 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15577 UInt bZ
= (insn28
>> 16) & 1;
15578 UInt bN
= (insn28
>> 7) & 1;
15579 UInt bD
= (insn28
>> 22) & 1;
15580 UInt bM
= (insn28
>> 5) & 1;
15581 UInt fD
= (INSN(15,12) << 1) | bD
;
15582 UInt fM
= (INSN(3,0) << 1) | bM
;
15583 if (bZ
&& (INSN(3,0) != 0 || (INSN(7,4) & 3) != 0)) {
15584 /* does not decode; fall through */
15586 IRTemp argL
= newTemp(Ity_F64
);
15587 IRTemp argR
= newTemp(Ity_F64
);
15588 IRTemp irRes
= newTemp(Ity_I32
);
15590 assign(argL
, unop(Iop_F32toF64
, getFReg(fD
)));
15591 assign(argR
, bZ
? IRExpr_Const(IRConst_F64i(0))
15592 : unop(Iop_F32toF64
, getFReg(fM
)));
15593 assign(irRes
, binop(Iop_CmpF64
, mkexpr(argL
), mkexpr(argR
)));
15595 IRTemp nzcv
= IRTemp_INVALID
;
15596 IRTemp oldFPSCR
= newTemp(Ity_I32
);
15597 IRTemp newFPSCR
= newTemp(Ity_I32
);
15599 /* This is where the fun starts. We have to convert 'irRes'
15600 from an IR-convention return result (IRCmpF64Result) to an
15601 ARM-encoded (N,Z,C,V) group. The final result is in the
15602 bottom 4 bits of 'nzcv'. */
15603 /* Map compare result from IR to ARM(nzcv) */
15605 FP cmp result | IR | ARM(nzcv)
15606 --------------------------------
15612 nzcv
= mk_convert_IRCmpF64Result_to_NZCV(irRes
);
15614 /* And update FPSCR accordingly */
15615 assign(oldFPSCR
, IRExpr_Get(OFFB_FPSCR
, Ity_I32
));
15618 binop(Iop_And32
, mkexpr(oldFPSCR
), mkU32(0x0FFFFFFF)),
15619 binop(Iop_Shl32
, mkexpr(nzcv
), mkU8(28))));
15621 putMiscReg32(OFFB_FPSCR
, mkexpr(newFPSCR
), condT
);
15624 DIP("fcmpz%ss%s s%u\n", bN
? "e" : "", nCC(conq
), fD
);
15626 DIP("fcmp%ss%s s%u, s%u\n", bN
? "e" : "",
15627 nCC(conq
), fD
, fM
);
15629 goto decode_success_vfp
;
15634 /* --------------------- unary (S) --------------------- */
15635 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15636 && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15637 && BITS4(1,0,1,0) == INSN(11,8)
15638 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15639 UInt bD
= (insn28
>> 22) & 1;
15640 UInt bM
= (insn28
>> 5) & 1;
15641 UInt fD
= (INSN(15,12) << 1) | bD
;
15642 UInt fM
= (INSN(3,0) << 1) | bM
;
15643 UInt b16
= (insn28
>> 16) & 1;
15644 UInt b7
= (insn28
>> 7) & 1;
15645 /**/ if (b16
== 0 && b7
== 0) {
15647 putFReg(fD
, getFReg(fM
), condT
);
15648 DIP("fcpys%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15649 goto decode_success_vfp
;
15651 else if (b16
== 0 && b7
== 1) {
15653 putFReg(fD
, unop(Iop_AbsF32
, getFReg(fM
)), condT
);
15654 DIP("fabss%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15655 goto decode_success_vfp
;
15657 else if (b16
== 1 && b7
== 0) {
15659 putFReg(fD
, unop(Iop_NegF32
, getFReg(fM
)), condT
);
15660 DIP("fnegs%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15661 goto decode_success_vfp
;
15663 else if (b16
== 1 && b7
== 1) {
15665 IRExpr
* rm
= get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
15666 putFReg(fD
, binop(Iop_SqrtF32
, rm
, getFReg(fM
)), condT
);
15667 DIP("fsqrts%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15668 goto decode_success_vfp
;
15676 /* ----------------- I <-> S conversions ----------------- */
15678 // F{S,U}ITOS fD, fM
15679 /* These are more complex than FSITOD/FUITOD. In the D cases, a 32
15680 bit int will always fit within the 53 bit mantissa, so there's
15681 no possibility of a loss of precision, but that's obviously not
15682 the case here. Hence this case possibly requires rounding, and
15683 so it drags in the current rounding mode. */
15684 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15685 && BITS4(1,0,0,0) == INSN(19,16)
15686 && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
15687 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15688 UInt bM
= (insn28
>> 5) & 1;
15689 UInt bD
= (insn28
>> 22) & 1;
15690 UInt fM
= (INSN(3,0) << 1) | bM
;
15691 UInt fD
= (INSN(15,12) << 1) | bD
;
15692 UInt syned
= (insn28
>> 7) & 1;
15693 IRTemp rmode
= newTemp(Ity_I32
);
15694 assign(rmode
, mkexpr(mk_get_IR_rounding_mode()));
15697 putFReg(fD
, binop(Iop_F64toF32
,
15699 unop(Iop_I32StoF64
,
15700 unop(Iop_ReinterpF32asI32
, getFReg(fM
)))),
15702 DIP("fsitos%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15705 putFReg(fD
, binop(Iop_F64toF32
,
15707 unop(Iop_I32UtoF64
,
15708 unop(Iop_ReinterpF32asI32
, getFReg(fM
)))),
15710 DIP("fuitos%s s%u, s%u\n", nCC(conq
), fD
, fM
);
15712 goto decode_success_vfp
;
15715 // FTO{S,U}IS fD, fM
15716 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15717 && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
15718 && BITS4(1,0,1,0) == INSN(11,8)
15719 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
15720 UInt bM
= (insn28
>> 5) & 1;
15721 UInt bD
= (insn28
>> 22) & 1;
15722 UInt fD
= (INSN(15,12) << 1) | bD
;
15723 UInt fM
= (INSN(3,0) << 1) | bM
;
15724 UInt bZ
= (insn28
>> 7) & 1;
15725 UInt syned
= (insn28
>> 16) & 1;
15726 IRTemp rmode
= newTemp(Ity_I32
);
15727 assign(rmode
, bZ
? mkU32(Irrm_ZERO
)
15728 : mkexpr(mk_get_IR_rounding_mode()));
15731 putFReg(fD
, unop(Iop_ReinterpI32asF32
,
15732 binop(Iop_F64toI32S
, mkexpr(rmode
),
15733 unop(Iop_F32toF64
, getFReg(fM
)))),
15735 DIP("ftosi%ss%s s%u, d%u\n", bZ
? "z" : "",
15736 nCC(conq
), fD
, fM
);
15737 goto decode_success_vfp
;
15740 putFReg(fD
, unop(Iop_ReinterpI32asF32
,
15741 binop(Iop_F64toI32U
, mkexpr(rmode
),
15742 unop(Iop_F32toF64
, getFReg(fM
)))),
15744 DIP("ftoui%ss%s s%u, d%u\n", bZ
? "z" : "",
15745 nCC(conq
), fD
, fM
);
15746 goto decode_success_vfp
;
15750 /* ----------------- S <-> D conversions ----------------- */
15753 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15754 && BITS4(0,1,1,1) == INSN(19,16)
15755 && BITS4(1,0,1,0) == INSN(11,8)
15756 && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
15757 UInt dD
= INSN(15,12) | (INSN(22,22) << 4);
15758 UInt bM
= (insn28
>> 5) & 1;
15759 UInt fM
= (INSN(3,0) << 1) | bM
;
15760 putDReg(dD
, unop(Iop_F32toF64
, getFReg(fM
)), condT
);
15761 DIP("fcvtds%s d%u, s%u\n", nCC(conq
), dD
, fM
);
15762 goto decode_success_vfp
;
15766 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15767 && BITS4(0,1,1,1) == INSN(19,16)
15768 && BITS4(1,0,1,1) == INSN(11,8)
15769 && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
15770 UInt bD
= (insn28
>> 22) & 1;
15771 UInt fD
= (INSN(15,12) << 1) | bD
;
15772 UInt dM
= INSN(3,0) | (INSN(5,5) << 4);
15773 IRTemp rmode
= newTemp(Ity_I32
);
15774 assign(rmode
, mkexpr(mk_get_IR_rounding_mode()));
15775 putFReg(fD
, binop(Iop_F64toF32
, mkexpr(rmode
), getDReg(dM
)),
15777 DIP("fcvtsd%s s%u, d%u\n", nCC(conq
), fD
, dM
);
15778 goto decode_success_vfp
;
15781 /* --------------- VCVT fixed<->floating, VFP --------------- */
15782 /* 31 27 23 19 15 11 7 3
15783 28 24 20 16 12 8 4 0
15785 cond 1110 1D11 1p1U Vd 101f x1i0 imm4
15787 VCVT<c>.<Td>.F64 <Dd>, <Dd>, #fbits
15788 VCVT<c>.<Td>.F32 <Dd>, <Dd>, #fbits
15789 VCVT<c>.F64.<Td> <Dd>, <Dd>, #fbits
15790 VCVT<c>.F32.<Td> <Dd>, <Dd>, #fbits
15791 are of this form. We only handle a subset of the cases though.
15793 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
15794 && BITS4(1,0,1,0) == (INSN(19,16) & BITS4(1,0,1,0))
15795 && BITS3(1,0,1) == INSN(11,9)
15796 && BITS3(1,0,0) == (INSN(6,4) & BITS3(1,0,1))) {
15797 UInt bD
= INSN(22,22);
15798 UInt bOP
= INSN(18,18);
15799 UInt bU
= INSN(16,16);
15800 UInt Vd
= INSN(15,12);
15801 UInt bSF
= INSN(8,8);
15802 UInt bSX
= INSN(7,7);
15803 UInt bI
= INSN(5,5);
15804 UInt imm4
= INSN(3,0);
15805 Bool to_fixed
= bOP
== 1;
15806 Bool dp_op
= bSF
== 1;
15807 Bool unsyned
= bU
== 1;
15808 UInt size
= bSX
== 0 ? 16 : 32;
15809 Int frac_bits
= size
- ((imm4
<< 1) | bI
);
15810 UInt d
= dp_op
? ((bD
<< 4) | Vd
) : ((Vd
<< 1) | bD
);
15812 IRExpr
* rm
= mkU32(Irrm_NEAREST
);
15813 IRTemp scale
= newTemp(Ity_F64
);
15814 assign(scale
, unop(Iop_I32UtoF64
, mkU32( ((UInt
)1) << (frac_bits
-1) )));
15816 if (frac_bits
>= 1 && frac_bits
<= 32 && !to_fixed
&& !dp_op
15818 /* VCVT.F32.{S,U}32 S[d], S[d], #frac_bits */
15819 /* This generates really horrible code. We could potentially
15821 IRTemp rmode
= newTemp(Ity_I32
);
15822 assign(rmode
, mkU32(Irrm_NEAREST
)); // per the spec
15823 IRTemp src32
= newTemp(Ity_I32
);
15824 assign(src32
, unop(Iop_ReinterpF32asI32
, getFReg(d
)));
15825 IRExpr
* as_F64
= unop( unsyned
? Iop_I32UtoF64
: Iop_I32StoF64
,
15827 IRExpr
* resF64
= triop(Iop_DivF64
,
15829 triop(Iop_AddF64
, rm
, mkexpr(scale
),
15831 IRExpr
* resF32
= binop(Iop_F64toF32
, mkexpr(rmode
), resF64
);
15832 putFReg(d
, resF32
, condT
);
15833 DIP("vcvt.f32.%c32, s%u, s%u, #%d\n",
15834 unsyned
? 'u' : 's', d
, d
, frac_bits
);
15835 goto decode_success_vfp
;
15837 if (frac_bits
>= 1 && frac_bits
<= 32 && !to_fixed
&& dp_op
15839 /* VCVT.F64.{S,U}32 D[d], D[d], #frac_bits */
15840 /* This generates really horrible code. We could potentially
15842 IRTemp src32
= newTemp(Ity_I32
);
15843 assign(src32
, unop(Iop_64to32
, getDRegI64(d
)));
15844 IRExpr
* as_F64
= unop( unsyned
? Iop_I32UtoF64
: Iop_I32StoF64
,
15846 IRExpr
* resF64
= triop(Iop_DivF64
,
15848 triop(Iop_AddF64
, rm
, mkexpr(scale
),
15850 putDReg(d
, resF64
, condT
);
15851 DIP("vcvt.f64.%c32, d%u, d%u, #%d\n",
15852 unsyned
? 'u' : 's', d
, d
, frac_bits
);
15853 goto decode_success_vfp
;
15855 if (frac_bits
>= 1 && frac_bits
<= 32 && to_fixed
&& dp_op
15857 /* VCVT.{S,U}32.F64 D[d], D[d], #frac_bits */
15858 IRTemp srcF64
= newTemp(Ity_F64
);
15859 assign(srcF64
, getDReg(d
));
15860 IRTemp scaledF64
= newTemp(Ity_F64
);
15861 assign(scaledF64
, triop(Iop_MulF64
,
15862 rm
, mkexpr(srcF64
),
15863 triop(Iop_AddF64
, rm
, mkexpr(scale
),
15865 IRTemp rmode
= newTemp(Ity_I32
);
15866 assign(rmode
, mkU32(Irrm_ZERO
)); // as per the spec
15867 IRTemp asI32
= newTemp(Ity_I32
);
15868 assign(asI32
, binop(unsyned
? Iop_F64toI32U
: Iop_F64toI32S
,
15869 mkexpr(rmode
), mkexpr(scaledF64
)));
15870 putDRegI64(d
, unop(unsyned
? Iop_32Uto64
: Iop_32Sto64
,
15871 mkexpr(asI32
)), condT
);
15873 DIP("vcvt.%c32.f64, d%u, d%u, #%d\n",
15874 unsyned
? 'u' : 's', d
, d
, frac_bits
);
15875 goto decode_success_vfp
;
15877 if (frac_bits
>= 1 && frac_bits
<= 32 && to_fixed
&& !dp_op
15879 /* VCVT.{S,U}32.F32 S[d], S[d], #frac_bits */
15880 IRTemp srcF32
= newTemp(Ity_F32
);
15881 assign(srcF32
, getFReg(d
));
15882 IRTemp scaledF64
= newTemp(Ity_F64
);
15883 assign(scaledF64
, triop(Iop_MulF64
,
15884 rm
, unop(Iop_F32toF64
, mkexpr(srcF32
)),
15885 triop(Iop_AddF64
, rm
, mkexpr(scale
),
15887 IRTemp rmode
= newTemp(Ity_I32
);
15888 assign(rmode
, mkU32(Irrm_ZERO
)); // as per the spec
15889 IRTemp asI32
= newTemp(Ity_I32
);
15890 assign(asI32
, binop(unsyned
? Iop_F64toI32U
: Iop_F64toI32S
,
15891 mkexpr(rmode
), mkexpr(scaledF64
)));
15892 putFReg(d
, unop(Iop_ReinterpI32asF32
, mkexpr(asI32
)), condT
);
15893 DIP("vcvt.%c32.f32, d%u, d%u, #%d\n",
15894 unsyned
? 'u' : 's', d
, d
, frac_bits
);
15895 goto decode_success_vfp
;
15903 decode_success_vfp
:
15904 /* Check that any accepted insn really is a CP10 or CP11 insn, iow,
15905 assert that we aren't accepting, in this fn, insns that actually
15906 should be handled somewhere else. */
15907 vassert(INSN(11,9) == BITS3(1,0,1)); // 11:8 = 1010 or 1011
15914 /*------------------------------------------------------------*/
15915 /*--- Instructions in NV (never) space ---*/
15916 /*------------------------------------------------------------*/
15919 /* Translate a NV space instruction. If successful, returns True and
15920 *dres may or may not be updated. If failure, returns False and
15921 doesn't change *dres nor create any IR.
15923 Note that all NEON instructions (in ARM mode) up to and including
15924 ARMv7, but not later, are handled through here, since they are all
15927 static Bool decode_NV_instruction_ARMv7_and_below
15928 ( /*MOD*/DisResult
* dres
,
15929 const VexArchInfo
* archinfo
,
15932 # define INSN(_bMax,_bMin) SLICE_UInt(insn, (_bMax), (_bMin))
15933 # define INSN_COND SLICE_UInt(insn, 31, 28)
15935 HChar dis_buf
[128];
15937 // Should only be called for NV instructions
15938 vassert(BITS4(1,1,1,1) == INSN_COND
);
15940 /* ------------------------ pld{w} ------------------------ */
15941 if (BITS8(0,1,0,1, 0,0, 0,1) == (INSN(27,20) & BITS8(1,1,1,1, 0,0, 1,1))
15942 && BITS4(1,1,1,1) == INSN(15,12)) {
15943 UInt rN
= INSN(19,16);
15944 UInt imm12
= INSN(11,0);
15945 UInt bU
= INSN(23,23);
15946 UInt bR
= INSN(22,22);
15947 DIP("pld%c [r%u, #%c%u]\n", bR
? ' ' : 'w', rN
, bU
? '+' : '-', imm12
);
15951 if (BITS8(0,1,1,1, 0,0, 0,1) == (INSN(27,20) & BITS8(1,1,1,1, 0,0, 1,1))
15952 && BITS4(1,1,1,1) == INSN(15,12)
15953 && 0 == INSN(4,4)) {
15954 UInt rN
= INSN(19,16);
15955 UInt rM
= INSN(3,0);
15956 UInt imm5
= INSN(11,7);
15957 UInt sh2
= INSN(6,5);
15958 UInt bU
= INSN(23,23);
15959 UInt bR
= INSN(22,22);
15960 if (rM
!= 15 && (rN
!= 15 || bR
)) {
15961 IRExpr
* eaE
= mk_EA_reg_plusminus_shifted_reg(rN
, bU
, rM
,
15962 sh2
, imm5
, dis_buf
);
15963 IRTemp eaT
= newTemp(Ity_I32
);
15964 /* Bind eaE to a temp merely for debugging-vex purposes, so we
15965 can check it's a plausible decoding. It will get removed
15966 by iropt a little later on. */
15969 DIP("pld%c %s\n", bR
? ' ' : 'w', dis_buf
);
15975 /* ------------------------ pli ------------------------ */
15976 if (BITS8(0,1,0,0, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
15977 && BITS4(1,1,1,1) == INSN(15,12)) {
15978 UInt rN
= INSN(19,16);
15979 UInt imm12
= INSN(11,0);
15980 UInt bU
= INSN(23,23);
15981 DIP("pli [r%u, #%c%u]\n", rN
, bU
? '+' : '-', imm12
);
15985 /* --------------------- Interworking branches --------------------- */
15987 // BLX (1), viz, unconditional branch and link to R15+simm24
15988 // and set CPSR.T = 1, that is, switch to Thumb mode
15989 if (INSN(31,25) == BITS7(1,1,1,1,1,0,1)) {
15990 UInt bitH
= INSN(24,24);
15991 UInt uimm24
= INSN(23,0); uimm24
<<= 8;
15992 Int simm24
= (Int
)uimm24
; simm24
>>= 8;
15993 simm24
= (((UInt
)simm24
) << 2) + (bitH
<< 1);
15994 /* Now this is a bit tricky. Since we're decoding an ARM insn,
15995 it is implies that CPSR.T == 0. Hence the current insn's
15996 address is guaranteed to be of the form X--(30)--X00. So, no
15997 need to mask any bits off it. But need to set the lowest bit
15998 to 1 to denote we're in Thumb mode after this, since
15999 guest_R15T has CPSR.T as the lowest bit. And we can't chase
16000 into the call, so end the block at this point. */
16001 UInt dst
= guest_R15_curr_instr_notENC
+ 8 + (simm24
| 1);
16002 putIRegA( 14, mkU32(guest_R15_curr_instr_notENC
+ 4),
16003 IRTemp_INVALID
/*because AL*/, Ijk_Boring
);
16004 llPutIReg(15, mkU32(dst
));
16005 dres
->jk_StopHere
= Ijk_Call
;
16006 dres
->whatNext
= Dis_StopHere
;
16007 DIP("blx 0x%x (and switch to Thumb mode)\n", dst
- 1);
16011 /* ------------------- v7 barrier insns ------------------- */
16013 case 0xF57FF06F: /* ISB */
16014 stmt( IRStmt_MBE(Imbe_Fence
) );
16017 case 0xF57FF04F: /* DSB sy */
16018 case 0xF57FF04E: /* DSB st */
16019 case 0xF57FF04B: /* DSB ish */
16020 case 0xF57FF04A: /* DSB ishst */
16021 case 0xF57FF047: /* DSB nsh */
16022 case 0xF57FF046: /* DSB nshst */
16023 case 0xF57FF043: /* DSB osh */
16024 case 0xF57FF042: /* DSB oshst */
16025 stmt( IRStmt_MBE(Imbe_Fence
) );
16028 case 0xF57FF05F: /* DMB sy */
16029 case 0xF57FF05E: /* DMB st */
16030 case 0xF57FF05B: /* DMB ish */
16031 case 0xF57FF05A: /* DMB ishst */
16032 case 0xF57FF057: /* DMB nsh */
16033 case 0xF57FF056: /* DMB nshst */
16034 case 0xF57FF053: /* DMB osh */
16035 case 0xF57FF052: /* DMB oshst */
16036 stmt( IRStmt_MBE(Imbe_Fence
) );
16043 /* ------------------- CLREX ------------------ */
16044 if (insn
== 0xF57FF01F) {
16045 /* AFAICS, this simply cancels a (all?) reservations made by a
16046 (any?) preceding LDREX(es). Arrange to hand it through to
16048 stmt( IRStmt_MBE(Imbe_CancelReservation
) );
16053 /* ------------------- NEON ------------------- */
16054 if (archinfo
->hwcaps
& VEX_HWCAPS_ARM_NEON
) {
16055 Bool ok_neon
= decode_NEON_instruction_ARMv7_and_below(
16056 dres
, insn
, IRTemp_INVALID
/*unconditional*/,
16071 /*------------------------------------------------------------*/
16072 /*--- Disassemble a single ARM instruction ---*/
16073 /*------------------------------------------------------------*/
16075 /* Disassemble a single ARM instruction into IR. The instruction is
16076 located in host memory at guest_instr, and has (decoded) guest IP
16077 of guest_R15_curr_instr_notENC, which will have been set before the
16081 DisResult
disInstr_ARM_WRK (
16082 Bool (*resteerOkFn
) ( /*opaque*/void*, Addr
),
16084 void* callback_opaque
,
16085 const UChar
* guest_instr
,
16086 const VexArchInfo
* archinfo
,
16087 const VexAbiInfo
* abiinfo
,
16091 // A macro to fish bits out of 'insn'.
16092 # define INSN(_bMax,_bMin) SLICE_UInt(insn, (_bMax), (_bMin))
16093 # define INSN_COND SLICE_UInt(insn, 31, 28)
16097 IRTemp condT
; /* :: Ity_I32 */
16099 HChar dis_buf
[128]; // big enough to hold LDMIA etc text
16101 /* Set result defaults. */
16102 dres
.whatNext
= Dis_Continue
;
16104 dres
.continueAt
= 0;
16105 dres
.jk_StopHere
= Ijk_INVALID
;
16106 dres
.hint
= Dis_HintNone
;
16108 /* Set default actions for post-insn handling of writes to r15, if
16110 r15written
= False
;
16111 r15guard
= IRTemp_INVALID
; /* unconditional */
16112 r15kind
= Ijk_Boring
;
16114 /* At least this is simple on ARM: insns are all 4 bytes long, and
16115 4-aligned. So just fish the whole thing out of memory right now
16117 insn
= getUIntLittleEndianly( guest_instr
);
16119 if (0) vex_printf("insn: 0x%x\n", insn
);
16121 DIP("\t(arm) 0x%x: ", (UInt
)guest_R15_curr_instr_notENC
);
16123 vassert(0 == (guest_R15_curr_instr_notENC
& 3));
16125 /* ----------------------------------------------------------- */
16127 /* Spot "Special" instructions (see comment at top of file). */
16129 const UChar
* code
= guest_instr
;
16130 /* Spot the 16-byte preamble:
16132 e1a0c1ec mov r12, r12, ROR #3
16133 e1a0c6ec mov r12, r12, ROR #13
16134 e1a0ceec mov r12, r12, ROR #29
16135 e1a0c9ec mov r12, r12, ROR #19
16137 UInt word1
= 0xE1A0C1EC;
16138 UInt word2
= 0xE1A0C6EC;
16139 UInt word3
= 0xE1A0CEEC;
16140 UInt word4
= 0xE1A0C9EC;
16141 if (getUIntLittleEndianly(code
+ 0) == word1
&&
16142 getUIntLittleEndianly(code
+ 4) == word2
&&
16143 getUIntLittleEndianly(code
+ 8) == word3
&&
16144 getUIntLittleEndianly(code
+12) == word4
) {
16145 /* Got a "Special" instruction preamble. Which one is it? */
16146 if (getUIntLittleEndianly(code
+16) == 0xE18AA00A
16147 /* orr r10,r10,r10 */) {
16148 /* R3 = client_request ( R4 ) */
16149 DIP("r3 = client_request ( %%r4 )\n");
16150 llPutIReg(15, mkU32( guest_R15_curr_instr_notENC
+ 20 ));
16151 dres
.jk_StopHere
= Ijk_ClientReq
;
16152 dres
.whatNext
= Dis_StopHere
;
16153 goto decode_success
;
16156 if (getUIntLittleEndianly(code
+16) == 0xE18BB00B
16157 /* orr r11,r11,r11 */) {
16158 /* R3 = guest_NRADDR */
16159 DIP("r3 = guest_NRADDR\n");
16161 llPutIReg(3, IRExpr_Get( OFFB_NRADDR
, Ity_I32
));
16162 goto decode_success
;
16165 if (getUIntLittleEndianly(code
+16) == 0xE18CC00C
16166 /* orr r12,r12,r12 */) {
16167 /* branch-and-link-to-noredir R4 */
16168 DIP("branch-and-link-to-noredir r4\n");
16169 llPutIReg(14, mkU32( guest_R15_curr_instr_notENC
+ 20) );
16170 llPutIReg(15, llGetIReg(4));
16171 dres
.jk_StopHere
= Ijk_NoRedir
;
16172 dres
.whatNext
= Dis_StopHere
;
16173 goto decode_success
;
16176 if (getUIntLittleEndianly(code
+16) == 0xE1899009
16177 /* orr r9,r9,r9 */) {
16179 DIP("IR injection\n");
16180 vex_inject_ir(irsb
, Iend_LE
);
16181 // Invalidate the current insn. The reason is that the IRop we're
16182 // injecting here can change. In which case the translation has to
16183 // be redone. For ease of handling, we simply invalidate all the
16185 stmt(IRStmt_Put(OFFB_CMSTART
, mkU32(guest_R15_curr_instr_notENC
)));
16186 stmt(IRStmt_Put(OFFB_CMLEN
, mkU32(20)));
16187 llPutIReg(15, mkU32( guest_R15_curr_instr_notENC
+ 20 ));
16188 dres
.whatNext
= Dis_StopHere
;
16189 dres
.jk_StopHere
= Ijk_InvalICache
;
16190 goto decode_success
;
16192 /* We don't know what it is. Set opc1/opc2 so decode_failure
16193 can print the insn following the Special-insn preamble. */
16194 insn
= getUIntLittleEndianly(code
+16);
16195 goto decode_failure
;
16201 /* ----------------------------------------------------------- */
16203 /* Main ARM instruction decoder starts here. */
16205 /* Deal with the condition. Strategy is to merely generate a
16206 condition temporary at this point (or IRTemp_INVALID, meaning
16207 unconditional). We leave it to lower-level instruction decoders
16208 to decide whether they can generate straight-line code, or
16209 whether they must generate a side exit before the instruction.
16210 condT :: Ity_I32 and is always either zero or one. */
16211 condT
= IRTemp_INVALID
;
16212 switch ( (ARMCondcode
)INSN_COND
) {
16214 // Illegal instruction prior to v5 (see ARM ARM A3-5), but
16215 // some cases are acceptable
16217 = decode_NV_instruction_ARMv7_and_below(&dres
, archinfo
, insn
);
16219 goto decode_success
;
16221 goto after_v7_decoder
;
16223 case ARMCondAL
: // Always executed
16225 case ARMCondEQ
: case ARMCondNE
: case ARMCondHS
: case ARMCondLO
:
16226 case ARMCondMI
: case ARMCondPL
: case ARMCondVS
: case ARMCondVC
:
16227 case ARMCondHI
: case ARMCondLS
: case ARMCondGE
: case ARMCondLT
:
16228 case ARMCondGT
: case ARMCondLE
:
16229 condT
= newTemp(Ity_I32
);
16230 assign( condT
, mk_armg_calculate_condition( INSN_COND
));
16234 /* ----------------------------------------------------------- */
16235 /* -- ARMv5 integer instructions -- */
16236 /* ----------------------------------------------------------- */
16238 /* ---------------- Data processing ops ------------------- */
16240 if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0))
16241 && !(INSN(25,25) == 0 && INSN(7,7) == 1 && INSN(4,4) == 1)) {
16242 IRTemp shop
= IRTemp_INVALID
; /* shifter operand */
16243 IRTemp shco
= IRTemp_INVALID
; /* shifter carry out */
16244 UInt rD
= (insn
>> 12) & 0xF; /* 15:12 */
16245 UInt rN
= (insn
>> 16) & 0xF; /* 19:16 */
16246 UInt bitS
= (insn
>> 20) & 1; /* 20:20 */
16247 IRTemp rNt
= IRTemp_INVALID
;
16248 IRTemp res
= IRTemp_INVALID
;
16249 IRTemp oldV
= IRTemp_INVALID
;
16250 IRTemp oldC
= IRTemp_INVALID
;
16251 const HChar
* name
= NULL
;
16252 IROp op
= Iop_INVALID
;
16255 switch (INSN(24,21)) {
16257 /* --------- ADD, SUB, AND, OR --------- */
16258 case BITS4(0,1,0,0): /* ADD: Rd = Rn + shifter_operand */
16259 name
= "add"; op
= Iop_Add32
; goto rd_eq_rn_op_SO
;
16260 case BITS4(0,0,1,0): /* SUB: Rd = Rn - shifter_operand */
16261 name
= "sub"; op
= Iop_Sub32
; goto rd_eq_rn_op_SO
;
16262 case BITS4(0,0,1,1): /* RSB: Rd = shifter_operand - Rn */
16263 name
= "rsb"; op
= Iop_Sub32
; goto rd_eq_rn_op_SO
;
16264 case BITS4(0,0,0,0): /* AND: Rd = Rn & shifter_operand */
16265 name
= "and"; op
= Iop_And32
; goto rd_eq_rn_op_SO
;
16266 case BITS4(1,1,0,0): /* OR: Rd = Rn | shifter_operand */
16267 name
= "orr"; op
= Iop_Or32
; goto rd_eq_rn_op_SO
;
16268 case BITS4(0,0,0,1): /* EOR: Rd = Rn ^ shifter_operand */
16269 name
= "eor"; op
= Iop_Xor32
; goto rd_eq_rn_op_SO
;
16270 case BITS4(1,1,1,0): /* BIC: Rd = Rn & ~shifter_operand */
16271 name
= "bic"; op
= Iop_And32
; goto rd_eq_rn_op_SO
;
16273 Bool isRSB
= False
;
16274 Bool isBIC
= False
;
16275 switch (INSN(24,21)) {
16276 case BITS4(0,0,1,1):
16277 vassert(op
== Iop_Sub32
); isRSB
= True
; break;
16278 case BITS4(1,1,1,0):
16279 vassert(op
== Iop_And32
); isBIC
= True
; break;
16283 rNt
= newTemp(Ity_I32
);
16284 assign(rNt
, getIRegA(rN
));
16285 ok
= mk_shifter_operand(
16286 INSN(25,25), INSN(11,0),
16287 &shop
, bitS
? &shco
: NULL
, dis_buf
16291 res
= newTemp(Ity_I32
);
16292 // compute the main result
16294 // reverse-subtract: shifter_operand - Rn
16295 vassert(op
== Iop_Sub32
);
16296 assign(res
, binop(op
, mkexpr(shop
), mkexpr(rNt
)) );
16297 } else if (isBIC
) {
16298 // andn: shifter_operand & ~Rn
16299 vassert(op
== Iop_And32
);
16300 assign(res
, binop(op
, mkexpr(rNt
),
16301 unop(Iop_Not32
, mkexpr(shop
))) );
16303 // normal: Rn op shifter_operand
16304 assign(res
, binop(op
, mkexpr(rNt
), mkexpr(shop
)) );
16306 // but don't commit it until after we've finished
16307 // all necessary reads from the guest state
16309 && (op
== Iop_And32
|| op
== Iop_Or32
|| op
== Iop_Xor32
)) {
16310 oldV
= newTemp(Ity_I32
);
16311 assign( oldV
, mk_armg_calculate_flag_v() );
16313 // can't safely read guest state after here
16314 // now safe to put the main result
16315 putIRegA( rD
, mkexpr(res
), condT
, Ijk_Boring
);
16316 // XXXX!! not safe to read any guest state after
16317 // this point (I think the code below doesn't do that).
16319 vassert(shco
== IRTemp_INVALID
);
16320 /* Update the flags thunk if necessary */
16322 vassert(shco
!= IRTemp_INVALID
);
16325 setFlags_D1_D2( ARMG_CC_OP_ADD
, rNt
, shop
, condT
);
16329 setFlags_D1_D2( ARMG_CC_OP_SUB
, shop
, rNt
, condT
);
16331 setFlags_D1_D2( ARMG_CC_OP_SUB
, rNt
, shop
, condT
);
16334 case Iop_And32
: /* BIC and AND set the flags the same */
16337 // oldV has been read just above
16338 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
,
16339 res
, shco
, oldV
, condT
);
16345 DIP("%s%s%s r%u, r%u, %s\n",
16346 name
, nCC(INSN_COND
), bitS
? "s" : "", rD
, rN
, dis_buf
);
16347 goto decode_success
;
16350 /* --------- MOV, MVN --------- */
16351 case BITS4(1,1,0,1): /* MOV: Rd = shifter_operand */
16352 case BITS4(1,1,1,1): { /* MVN: Rd = not(shifter_operand) */
16353 Bool isMVN
= INSN(24,21) == BITS4(1,1,1,1);
16354 IRTemp jk
= Ijk_Boring
;
16356 break; /* rN must be zero */
16357 ok
= mk_shifter_operand(
16358 INSN(25,25), INSN(11,0),
16359 &shop
, bitS
? &shco
: NULL
, dis_buf
16363 res
= newTemp(Ity_I32
);
16364 assign( res
, isMVN
? unop(Iop_Not32
, mkexpr(shop
))
16367 vassert(shco
!= IRTemp_INVALID
);
16368 oldV
= newTemp(Ity_I32
);
16369 assign( oldV
, mk_armg_calculate_flag_v() );
16371 vassert(shco
== IRTemp_INVALID
);
16373 /* According to the Cortex A8 TRM Sec. 5.2.1, MOV PC, r14 is a
16374 return for purposes of branch prediction. */
16375 if (!isMVN
&& INSN(11,0) == 14) {
16378 // can't safely read guest state after here
16379 putIRegA( rD
, mkexpr(res
), condT
, jk
);
16380 /* Update the flags thunk if necessary */
16382 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
,
16383 res
, shco
, oldV
, condT
);
16385 DIP("%s%s%s r%u, %s\n",
16386 isMVN
? "mvn" : "mov",
16387 nCC(INSN_COND
), bitS
? "s" : "", rD
, dis_buf
);
16388 goto decode_success
;
16391 /* --------- CMP --------- */
16392 case BITS4(1,0,1,0): /* CMP: (void) Rn - shifter_operand */
16393 case BITS4(1,0,1,1): { /* CMN: (void) Rn + shifter_operand */
16394 Bool isCMN
= INSN(24,21) == BITS4(1,0,1,1);
16396 break; /* rD must be zero */
16398 break; /* if S (bit 20) is not set, it's not CMP/CMN */
16399 rNt
= newTemp(Ity_I32
);
16400 assign(rNt
, getIRegA(rN
));
16401 ok
= mk_shifter_operand(
16402 INSN(25,25), INSN(11,0),
16403 &shop
, NULL
, dis_buf
16407 // can't safely read guest state after here
16408 /* Update the flags thunk. */
16409 setFlags_D1_D2( isCMN
? ARMG_CC_OP_ADD
: ARMG_CC_OP_SUB
,
16410 rNt
, shop
, condT
);
16411 DIP("%s%s r%u, %s\n",
16412 isCMN
? "cmn" : "cmp",
16413 nCC(INSN_COND
), rN
, dis_buf
);
16414 goto decode_success
;
16417 /* --------- TST --------- */
16418 case BITS4(1,0,0,0): /* TST: (void) Rn & shifter_operand */
16419 case BITS4(1,0,0,1): { /* TEQ: (void) Rn ^ shifter_operand */
16420 Bool isTEQ
= INSN(24,21) == BITS4(1,0,0,1);
16422 break; /* rD must be zero */
16424 break; /* if S (bit 20) is not set, it's not TST/TEQ */
16425 rNt
= newTemp(Ity_I32
);
16426 assign(rNt
, getIRegA(rN
));
16427 ok
= mk_shifter_operand(
16428 INSN(25,25), INSN(11,0),
16429 &shop
, &shco
, dis_buf
16433 /* Update the flags thunk. */
16434 res
= newTemp(Ity_I32
);
16435 assign( res
, binop(isTEQ
? Iop_Xor32
: Iop_And32
,
16436 mkexpr(rNt
), mkexpr(shop
)) );
16437 oldV
= newTemp(Ity_I32
);
16438 assign( oldV
, mk_armg_calculate_flag_v() );
16439 // can't safely read guest state after here
16440 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
,
16441 res
, shco
, oldV
, condT
);
16442 DIP("%s%s r%u, %s\n",
16443 isTEQ
? "teq" : "tst",
16444 nCC(INSN_COND
), rN
, dis_buf
);
16445 goto decode_success
;
16448 /* --------- ADC, SBC, RSC --------- */
16449 case BITS4(0,1,0,1): /* ADC: Rd = Rn + shifter_operand + oldC */
16450 name
= "adc"; goto rd_eq_rn_op_SO_op_oldC
;
16451 case BITS4(0,1,1,0): /* SBC: Rd = Rn - shifter_operand - (oldC ^ 1) */
16452 name
= "sbc"; goto rd_eq_rn_op_SO_op_oldC
;
16453 case BITS4(0,1,1,1): /* RSC: Rd = shifter_operand - Rn - (oldC ^ 1) */
16454 name
= "rsc"; goto rd_eq_rn_op_SO_op_oldC
;
16455 rd_eq_rn_op_SO_op_oldC
: {
16456 // FIXME: shco isn't used for anything. Get rid of it.
16457 rNt
= newTemp(Ity_I32
);
16458 assign(rNt
, getIRegA(rN
));
16459 ok
= mk_shifter_operand(
16460 INSN(25,25), INSN(11,0),
16461 &shop
, bitS
? &shco
: NULL
, dis_buf
16465 oldC
= newTemp(Ity_I32
);
16466 assign( oldC
, mk_armg_calculate_flag_c() );
16467 res
= newTemp(Ity_I32
);
16468 // compute the main result
16469 switch (INSN(24,21)) {
16470 case BITS4(0,1,0,1): /* ADC */
16473 binop(Iop_Add32
, mkexpr(rNt
), mkexpr(shop
)),
16476 case BITS4(0,1,1,0): /* SBC */
16479 binop(Iop_Sub32
, mkexpr(rNt
), mkexpr(shop
)),
16480 binop(Iop_Xor32
, mkexpr(oldC
), mkU32(1)) ));
16482 case BITS4(0,1,1,1): /* RSC */
16485 binop(Iop_Sub32
, mkexpr(shop
), mkexpr(rNt
)),
16486 binop(Iop_Xor32
, mkexpr(oldC
), mkU32(1)) ));
16491 // but don't commit it until after we've finished
16492 // all necessary reads from the guest state
16493 // now safe to put the main result
16494 putIRegA( rD
, mkexpr(res
), condT
, Ijk_Boring
);
16495 // XXXX!! not safe to read any guest state after
16496 // this point (I think the code below doesn't do that).
16498 vassert(shco
== IRTemp_INVALID
);
16499 /* Update the flags thunk if necessary */
16501 vassert(shco
!= IRTemp_INVALID
);
16502 switch (INSN(24,21)) {
16503 case BITS4(0,1,0,1): /* ADC */
16504 setFlags_D1_D2_ND( ARMG_CC_OP_ADC
,
16505 rNt
, shop
, oldC
, condT
);
16507 case BITS4(0,1,1,0): /* SBC */
16508 setFlags_D1_D2_ND( ARMG_CC_OP_SBB
,
16509 rNt
, shop
, oldC
, condT
);
16511 case BITS4(0,1,1,1): /* RSC */
16512 setFlags_D1_D2_ND( ARMG_CC_OP_SBB
,
16513 shop
, rNt
, oldC
, condT
);
16519 DIP("%s%s%s r%u, r%u, %s\n",
16520 name
, nCC(INSN_COND
), bitS
? "s" : "", rD
, rN
, dis_buf
);
16521 goto decode_success
;
16527 } /* if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) */
16529 /* --------------------- Load/store (ubyte & word) -------- */
16530 // LDR STR LDRB STRB
16531 /* 31 27 23 19 15 11 6 4 3 # highest bit
16533 A5-20 1 | 16 cond 0101 UB0L Rn Rd imm12
16534 A5-22 1 | 32 cond 0111 UBOL Rn Rd imm5 sh2 0 Rm
16535 A5-24 2 | 16 cond 0101 UB1L Rn Rd imm12
16536 A5-26 2 | 32 cond 0111 UB1L Rn Rd imm5 sh2 0 Rm
16537 A5-28 3 | 16 cond 0100 UB0L Rn Rd imm12
16538 A5-32 3 | 32 cond 0110 UB0L Rn Rd imm5 sh2 0 Rm
16541 1 at-ea (access at ea)
16542 2 at-ea-then-upd (access at ea, then Rn = ea)
16543 3 at-Rn-then-upd (access at Rn, then Rn = ea)
16546 32 Rn +/- Rm sh2 imm5
16548 /* Quickly skip over all of this for hopefully most instructions */
16549 if ((INSN(27,24) & BITS4(1,1,0,0)) != BITS4(0,1,0,0))
16550 goto after_load_store_ubyte_or_word
;
16554 /**/ if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 0) {
16557 else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 0
16558 && INSN(4,4) == 0) {
16561 else if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 1) {
16564 else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 1
16565 && INSN(4,4) == 0) {
16568 else if (INSN(27,24) == BITS4(0,1,0,0) && INSN(21,21) == 0) {
16571 else if (INSN(27,24) == BITS4(0,1,1,0) && INSN(21,21) == 0
16572 && INSN(4,4) == 0) {
16575 else goto after_load_store_ubyte_or_word
;
16577 { UInt rN
= (insn
>> 16) & 0xF; /* 19:16 */
16578 UInt rD
= (insn
>> 12) & 0xF; /* 15:12 */
16579 UInt rM
= (insn
>> 0) & 0xF; /* 3:0 */
16580 UInt bU
= (insn
>> 23) & 1; /* 23 */
16581 UInt bB
= (insn
>> 22) & 1; /* 22 */
16582 UInt bL
= (insn
>> 20) & 1; /* 20 */
16583 UInt imm12
= (insn
>> 0) & 0xFFF; /* 11:0 */
16584 UInt imm5
= (insn
>> 7) & 0x1F; /* 11:7 */
16585 UInt sh2
= (insn
>> 5) & 3; /* 6:5 */
16587 /* Skip some invalid cases, which would lead to two competing
16588 updates to the same register, or which are otherwise
16589 disallowed by the spec. */
16594 if (rM
== 15) goto after_load_store_ubyte_or_word
;
16596 case 2 | 16: case 3 | 16:
16597 if (rN
== 15) goto after_load_store_ubyte_or_word
;
16598 if (bL
== 1 && rN
== rD
) goto after_load_store_ubyte_or_word
;
16600 case 2 | 32: case 3 | 32:
16601 if (rM
== 15) goto after_load_store_ubyte_or_word
;
16602 if (rN
== 15) goto after_load_store_ubyte_or_word
;
16603 if (rN
== rM
) goto after_load_store_ubyte_or_word
;
16604 if (bL
== 1 && rN
== rD
) goto after_load_store_ubyte_or_word
;
16610 /* compute the effective address. Bind it to a tmp since we
16611 may need to use it twice. */
16612 IRExpr
* eaE
= NULL
;
16613 switch (summary
& 0xF0) {
16615 eaE
= mk_EA_reg_plusminus_imm12( rN
, bU
, imm12
, dis_buf
);
16618 eaE
= mk_EA_reg_plusminus_shifted_reg( rN
, bU
, rM
, sh2
, imm5
,
16623 IRTemp eaT
= newTemp(Ity_I32
);
16626 /* get the old Rn value */
16627 IRTemp rnT
= newTemp(Ity_I32
);
16628 assign(rnT
, getIRegA(rN
));
16630 /* decide on the transfer address */
16631 IRTemp taT
= IRTemp_INVALID
;
16632 switch (summary
& 0x0F) {
16633 case 1: case 2: taT
= eaT
; break;
16634 case 3: taT
= rnT
; break;
16636 vassert(taT
!= IRTemp_INVALID
);
16639 /* Store. If necessary, update the base register before the
16640 store itself, so that the common idiom of "str rX, [sp,
16641 #-4]!" (store rX at sp-4, then do new sp = sp-4, a.k.a "push
16642 rX") doesn't cause Memcheck to complain that the access is
16643 below the stack pointer. Also, not updating sp before the
16644 store confuses Valgrind's dynamic stack-extending logic. So
16645 do it before the store. Hence we need to snarf the store
16646 data before doing the basereg update. */
16648 /* get hold of the data to be stored */
16649 IRTemp rDt
= newTemp(Ity_I32
);
16650 assign(rDt
, getIRegA(rD
));
16652 /* Update Rn if necessary. */
16653 switch (summary
& 0x0F) {
16655 putIRegA( rN
, mkexpr(eaT
), condT
, Ijk_Boring
);
16659 /* generate the transfer */
16660 if (bB
== 0) { // word store
16661 storeGuardedLE( mkexpr(taT
), mkexpr(rDt
), condT
);
16662 } else { // byte store
16664 storeGuardedLE( mkexpr(taT
), unop(Iop_32to8
, mkexpr(rDt
)), condT
);
16671 /* generate the transfer */
16672 if (bB
== 0) { // word load
16673 IRTemp jk
= Ijk_Boring
;
16674 /* According to the Cortex A8 TRM Sec. 5.2.1, LDR(1) with r13 as the
16675 base register and PC as the destination register is a return for
16676 purposes of branch prediction.
16677 The ARM ARM Sec. C9.10.1 further specifies that it must use a
16678 post-increment by immediate addressing mode to be counted in
16679 event 0x0E (Procedure return).*/
16680 if (rN
== 13 && summary
== (3 | 16) && bB
== 0) {
16683 IRTemp tD
= newTemp(Ity_I32
);
16684 loadGuardedLE( tD
, ILGop_Ident32
,
16685 mkexpr(taT
), llGetIReg(rD
), condT
);
16686 /* "rD == 15 ? condT : IRTemp_INVALID": simply
16687 IRTemp_INVALID would be correct in all cases here, and
16688 for the non-r15 case it generates better code, by
16689 avoiding two tests of the cond (since it is already
16690 tested by loadGuardedLE). However, the logic at the end
16691 of this function, that deals with writes to r15, has an
16692 optimisation which depends on seeing whether or not the
16693 write is conditional. Hence in this particular case we
16694 let it "see" the guard condition. */
16695 putIRegA( rD
, mkexpr(tD
),
16696 rD
== 15 ? condT
: IRTemp_INVALID
, jk
);
16697 } else { // byte load
16699 IRTemp tD
= newTemp(Ity_I32
);
16700 loadGuardedLE( tD
, ILGop_8Uto32
, mkexpr(taT
), llGetIReg(rD
), condT
);
16701 /* No point in similar 3rd arg complexity here, since we
16702 can't sanely write anything to r15 like this. */
16703 putIRegA( rD
, mkexpr(tD
), IRTemp_INVALID
, Ijk_Boring
);
16706 /* Update Rn if necessary. */
16707 switch (summary
& 0x0F) {
16709 // should be assured by logic above:
16711 vassert(rD
!= rN
); /* since we just wrote rD */
16712 putIRegA( rN
, mkexpr(eaT
), condT
, Ijk_Boring
);
16717 switch (summary
& 0x0F) {
16718 case 1: DIP("%sr%s%s r%u, %s\n",
16719 bL
== 0 ? "st" : "ld",
16720 bB
== 0 ? "" : "b", nCC(INSN_COND
), rD
, dis_buf
);
16722 case 2: DIP("%sr%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
16723 bL
== 0 ? "st" : "ld",
16724 bB
== 0 ? "" : "b", nCC(INSN_COND
), rD
, dis_buf
);
16726 case 3: DIP("%sr%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
16727 bL
== 0 ? "st" : "ld",
16728 bB
== 0 ? "" : "b", nCC(INSN_COND
), rD
, dis_buf
);
16730 default: vassert(0);
16733 /* XXX deal with alignment constraints */
16735 goto decode_success
;
16739 For all loads: if the Amode specifies base register
16740 writeback, and the same register is specified for Rd and Rn,
16741 the results are UNPREDICTABLE.
16743 For all loads and stores: if R15 is written, branch to
16744 that address afterwards.
16746 STRB: straightforward
16747 LDRB: loaded data is zero extended
16748 STR: lowest 2 bits of address are ignored
16749 LDR: if the lowest 2 bits of the address are nonzero
16750 then the loaded value is rotated right by 8 * the lowest 2 bits
16754 after_load_store_ubyte_or_word
:
16756 /* --------------------- Load/store (sbyte & hword) -------- */
16757 // LDRH LDRSH STRH LDRSB
16758 /* 31 27 23 19 15 11 7 3 # highest bit
16759 28 24 20 16 12 8 4 0
16760 A5-36 1 | 16 cond 0001 U10L Rn Rd im4h 1SH1 im4l
16761 A5-38 1 | 32 cond 0001 U00L Rn Rd 0000 1SH1 Rm
16762 A5-40 2 | 16 cond 0001 U11L Rn Rd im4h 1SH1 im4l
16763 A5-42 2 | 32 cond 0001 U01L Rn Rd 0000 1SH1 Rm
16764 A5-44 3 | 16 cond 0000 U10L Rn Rd im4h 1SH1 im4l
16765 A5-46 3 | 32 cond 0000 U00L Rn Rd 0000 1SH1 Rm
16768 1 at-ea (access at ea)
16769 2 at-ea-then-upd (access at ea, then Rn = ea)
16770 3 at-Rn-then-upd (access at Rn, then Rn = ea)
16775 /* Quickly skip over all of this for hopefully most instructions */
16776 if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
16777 goto after_load_store_sbyte_or_hword
;
16779 /* Check the "1SH1" thing. */
16780 if ((INSN(7,4) & BITS4(1,0,0,1)) != BITS4(1,0,0,1))
16781 goto after_load_store_sbyte_or_hword
;
16785 /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,0)) {
16788 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,0)) {
16791 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,1)) {
16794 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,1)) {
16797 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(1,0)) {
16800 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(0,0)) {
16803 else goto after_load_store_sbyte_or_hword
;
16805 { UInt rN
= (insn
>> 16) & 0xF; /* 19:16 */
16806 UInt rD
= (insn
>> 12) & 0xF; /* 15:12 */
16807 UInt rM
= (insn
>> 0) & 0xF; /* 3:0 */
16808 UInt bU
= (insn
>> 23) & 1; /* 23 U=1 offset+, U=0 offset- */
16809 UInt bL
= (insn
>> 20) & 1; /* 20 L=1 load, L=0 store */
16810 UInt bH
= (insn
>> 5) & 1; /* H=1 halfword, H=0 byte */
16811 UInt bS
= (insn
>> 6) & 1; /* S=1 signed, S=0 unsigned */
16812 UInt imm8
= ((insn
>> 4) & 0xF0) | (insn
& 0xF); /* 11:8, 3:0 */
16814 /* Skip combinations that are either meaningless or already
16815 handled by main word-or-unsigned-byte load-store
16817 if (bS
== 0 && bH
== 0) /* "unsigned byte" */
16818 goto after_load_store_sbyte_or_hword
;
16819 if (bS
== 1 && bL
== 0) /* "signed store" */
16820 goto after_load_store_sbyte_or_hword
;
16822 /* Require 11:8 == 0 for Rn +/- Rm cases */
16823 if ((summary
& 32) != 0 && (imm8
& 0xF0) != 0)
16824 goto after_load_store_sbyte_or_hword
;
16826 /* Skip some invalid cases, which would lead to two competing
16827 updates to the same register, or which are otherwise
16828 disallowed by the spec. */
16833 if (rM
== 15) goto after_load_store_sbyte_or_hword
;
16835 case 2 | 16: case 3 | 16:
16836 if (rN
== 15) goto after_load_store_sbyte_or_hword
;
16837 if (bL
== 1 && rN
== rD
) goto after_load_store_sbyte_or_hword
;
16839 case 2 | 32: case 3 | 32:
16840 if (rM
== 15) goto after_load_store_sbyte_or_hword
;
16841 if (rN
== 15) goto after_load_store_sbyte_or_hword
;
16842 if (rN
== rM
) goto after_load_store_sbyte_or_hword
;
16843 if (bL
== 1 && rN
== rD
) goto after_load_store_sbyte_or_hword
;
16849 /* If this is a branch, make it unconditional at this point.
16850 Doing conditional branches in-line is too complex (for now).
16851 Note that you'd have to be insane to use any of these loads to
16852 do a branch, since they only load 16 bits at most, but we
16853 handle it just in case. */
16854 if (bL
== 1 && rD
== 15 && condT
!= IRTemp_INVALID
) {
16856 mk_skip_over_A32_if_cond_is_false( condT
);
16857 condT
= IRTemp_INVALID
;
16861 /* compute the effective address. Bind it to a tmp since we
16862 may need to use it twice. */
16863 IRExpr
* eaE
= NULL
;
16864 switch (summary
& 0xF0) {
16866 eaE
= mk_EA_reg_plusminus_imm8( rN
, bU
, imm8
, dis_buf
);
16869 eaE
= mk_EA_reg_plusminus_reg( rN
, bU
, rM
, dis_buf
);
16873 IRTemp eaT
= newTemp(Ity_I32
);
16876 /* get the old Rn value */
16877 IRTemp rnT
= newTemp(Ity_I32
);
16878 assign(rnT
, getIRegA(rN
));
16880 /* decide on the transfer address */
16881 IRTemp taT
= IRTemp_INVALID
;
16882 switch (summary
& 0x0F) {
16883 case 1: case 2: taT
= eaT
; break;
16884 case 3: taT
= rnT
; break;
16886 vassert(taT
!= IRTemp_INVALID
);
16888 /* ll previous value of rD, for dealing with conditional loads */
16889 IRTemp llOldRd
= newTemp(Ity_I32
);
16890 assign(llOldRd
, llGetIReg(rD
));
16892 /* halfword store H 1 L 0 S 0
16893 uhalf load H 1 L 1 S 0
16894 shalf load H 1 L 1 S 1
16895 sbyte load H 0 L 1 S 1
16897 const HChar
* name
= NULL
;
16898 /* generate the transfer */
16899 /**/ if (bH
== 1 && bL
== 0 && bS
== 0) { // halfword store
16900 storeGuardedLE( mkexpr(taT
),
16901 unop(Iop_32to16
, getIRegA(rD
)), condT
);
16904 else if (bH
== 1 && bL
== 1 && bS
== 0) { // uhalf load
16905 IRTemp newRd
= newTemp(Ity_I32
);
16906 loadGuardedLE( newRd
, ILGop_16Uto32
,
16907 mkexpr(taT
), mkexpr(llOldRd
), condT
);
16908 putIRegA( rD
, mkexpr(newRd
), IRTemp_INVALID
, Ijk_Boring
);
16911 else if (bH
== 1 && bL
== 1 && bS
== 1) { // shalf load
16912 IRTemp newRd
= newTemp(Ity_I32
);
16913 loadGuardedLE( newRd
, ILGop_16Sto32
,
16914 mkexpr(taT
), mkexpr(llOldRd
), condT
);
16915 putIRegA( rD
, mkexpr(newRd
), IRTemp_INVALID
, Ijk_Boring
);
16918 else if (bH
== 0 && bL
== 1 && bS
== 1) { // sbyte load
16919 IRTemp newRd
= newTemp(Ity_I32
);
16920 loadGuardedLE( newRd
, ILGop_8Sto32
,
16921 mkexpr(taT
), mkexpr(llOldRd
), condT
);
16922 putIRegA( rD
, mkexpr(newRd
), IRTemp_INVALID
, Ijk_Boring
);
16926 vassert(0); // should be assured by logic above
16928 /* Update Rn if necessary. */
16929 switch (summary
& 0x0F) {
16931 // should be assured by logic above:
16933 vassert(rD
!= rN
); /* since we just wrote rD */
16934 putIRegA( rN
, mkexpr(eaT
), condT
, Ijk_Boring
);
16938 switch (summary
& 0x0F) {
16939 case 1: DIP("%s%s r%u, %s\n", name
, nCC(INSN_COND
), rD
, dis_buf
);
16941 case 2: DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
16942 name
, nCC(INSN_COND
), rD
, dis_buf
);
16944 case 3: DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
16945 name
, nCC(INSN_COND
), rD
, dis_buf
);
16947 default: vassert(0);
16950 /* XXX deal with alignment constraints */
16952 goto decode_success
;
16956 For all loads: if the Amode specifies base register
16957 writeback, and the same register is specified for Rd and Rn,
16958 the results are UNPREDICTABLE.
16960 For all loads and stores: if R15 is written, branch to
16961 that address afterwards.
16963 Misaligned halfword stores => Unpredictable
16964 Misaligned halfword loads => Unpredictable
16968 after_load_store_sbyte_or_hword
:
16970 /* --------------------- Load/store multiple -------------- */
16971 // LD/STMIA LD/STMIB LD/STMDA LD/STMDB
16972 // Remarkably complex and difficult to get right
16973 // match 27:20 as 100XX0WL
16974 if (BITS8(1,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,1,0,0))) {
16975 // A5-50 LD/STMIA cond 1000 10WL Rn RegList
16976 // A5-51 LD/STMIB cond 1001 10WL Rn RegList
16977 // A5-53 LD/STMDA cond 1000 00WL Rn RegList
16978 // A5-53 LD/STMDB cond 1001 00WL Rn RegList
16981 UInt bINC
= (insn
>> 23) & 1;
16982 UInt bBEFORE
= (insn
>> 24) & 1;
16984 UInt bL
= (insn
>> 20) & 1; /* load=1, store=0 */
16985 UInt bW
= (insn
>> 21) & 1; /* Rn wback=1, no wback=0 */
16986 UInt rN
= (insn
>> 16) & 0xF;
16987 UInt regList
= insn
& 0xFFFF;
16988 /* Skip some invalid cases, which would lead to two competing
16989 updates to the same register, or which are otherwise
16990 disallowed by the spec. Note the test above has required
16991 that S == 0, since that looks like a kernel-mode only thing.
16992 Done by forcing the real pattern, viz 100XXSWL to actually be
16994 if (rN
== 15) goto after_load_store_multiple
;
16995 // reglist can't be empty
16996 if (regList
== 0) goto after_load_store_multiple
;
16997 // if requested to writeback Rn, and this is a load instruction,
16998 // then Rn can't appear in RegList, since we'd have two competing
16999 // new values for Rn. We do however accept this case for store
17001 if (bW
== 1 && bL
== 1 && ((1 << rN
) & regList
) > 0)
17002 goto after_load_store_multiple
;
17004 /* Now, we can't do a conditional load or store, since that very
17005 likely will generate an exception. So we have to take a side
17006 exit at this point if the condition is false. */
17007 if (condT
!= IRTemp_INVALID
) {
17008 mk_skip_over_A32_if_cond_is_false( condT
);
17009 condT
= IRTemp_INVALID
;
17012 /* Ok, now we're unconditional. Generate the IR. */
17013 mk_ldm_stm( True
/*arm*/, rN
, bINC
, bBEFORE
, bW
, bL
, regList
);
17015 DIP("%sm%c%c%s r%u%s, {0x%04x}\n",
17016 bL
== 1 ? "ld" : "st", bINC
? 'i' : 'd', bBEFORE
? 'b' : 'a',
17018 rN
, bW
? "!" : "", regList
);
17020 goto decode_success
;
17023 after_load_store_multiple
:
17025 /* --------------------- Control flow --------------------- */
17026 // B, BL (Branch, or Branch-and-Link, to immediate offset)
17028 if (BITS8(1,0,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))) {
17029 UInt link
= (insn
>> 24) & 1;
17030 UInt uimm24
= insn
& ((1<<24)-1); uimm24
<<= 8;
17031 Int simm24
= (Int
)uimm24
; simm24
>>= 8;
17032 UInt dst
= guest_R15_curr_instr_notENC
+ 8 + (((UInt
)simm24
) << 2);
17033 IRJumpKind jk
= link
? Ijk_Call
: Ijk_Boring
;
17035 putIRegA(14, mkU32(guest_R15_curr_instr_notENC
+ 4),
17036 condT
, Ijk_Boring
);
17038 if (condT
== IRTemp_INVALID
) {
17039 /* unconditional transfer to 'dst'. See if we can simply
17040 continue tracing at the destination. */
17041 if (resteerOkFn( callback_opaque
, dst
)) {
17043 dres
.whatNext
= Dis_ResteerU
;
17044 dres
.continueAt
= dst
;
17046 /* no; terminate the SB at this point. */
17047 llPutIReg(15, mkU32(dst
));
17048 dres
.jk_StopHere
= jk
;
17049 dres
.whatNext
= Dis_StopHere
;
17051 DIP("b%s 0x%x\n", link
? "l" : "", dst
);
17053 /* conditional transfer to 'dst' */
17054 const HChar
* comment
= "";
17056 /* First see if we can do some speculative chasing into one
17057 arm or the other. Be conservative and only chase if
17058 !link, that is, this is a normal conditional branch to a
17059 known destination. */
17062 && vex_control
.guest_chase_cond
17063 && dst
< guest_R15_curr_instr_notENC
17064 && resteerOkFn( callback_opaque
, dst
) ) {
17065 /* Speculation: assume this backward branch is taken. So
17066 we need to emit a side-exit to the insn following this
17067 one, on the negation of the condition, and continue at
17068 the branch target address (dst). */
17069 stmt( IRStmt_Exit( unop(Iop_Not1
,
17070 unop(Iop_32to1
, mkexpr(condT
))),
17072 IRConst_U32(guest_R15_curr_instr_notENC
+4),
17074 dres
.whatNext
= Dis_ResteerC
;
17075 dres
.continueAt
= (Addr32
)dst
;
17076 comment
= "(assumed taken)";
17081 && vex_control
.guest_chase_cond
17082 && dst
>= guest_R15_curr_instr_notENC
17083 && resteerOkFn( callback_opaque
,
17084 guest_R15_curr_instr_notENC
+4) ) {
17085 /* Speculation: assume this forward branch is not taken.
17086 So we need to emit a side-exit to dst (the dest) and
17087 continue disassembling at the insn immediately
17088 following this one. */
17089 stmt( IRStmt_Exit( unop(Iop_32to1
, mkexpr(condT
)),
17093 dres
.whatNext
= Dis_ResteerC
;
17094 dres
.continueAt
= guest_R15_curr_instr_notENC
+4;
17095 comment
= "(assumed not taken)";
17098 /* Conservative default translation - end the block at
17100 stmt( IRStmt_Exit( unop(Iop_32to1
, mkexpr(condT
)),
17101 jk
, IRConst_U32(dst
), OFFB_R15T
));
17102 llPutIReg(15, mkU32(guest_R15_curr_instr_notENC
+ 4));
17103 dres
.jk_StopHere
= Ijk_Boring
;
17104 dres
.whatNext
= Dis_StopHere
;
17106 DIP("b%s%s 0x%x %s\n", link
? "l" : "", nCC(INSN_COND
),
17109 goto decode_success
;
17112 // B, BL (Branch, or Branch-and-Link, to a register)
17113 // NB: interworking branch
17114 if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
17115 && INSN(19,12) == BITS8(1,1,1,1,1,1,1,1)
17116 && (INSN(11,4) == BITS8(1,1,1,1,0,0,1,1)
17117 || INSN(11,4) == BITS8(1,1,1,1,0,0,0,1))) {
17118 IRTemp dst
= newTemp(Ity_I32
);
17119 UInt link
= (INSN(11,4) >> 1) & 1;
17120 UInt rM
= INSN(3,0);
17121 // we don't decode the case (link && rM == 15), as that's
17123 if (!(link
&& rM
== 15)) {
17124 if (condT
!= IRTemp_INVALID
) {
17125 mk_skip_over_A32_if_cond_is_false( condT
);
17127 // rM contains an interworking address exactly as we require
17128 // (with continuation CPSR.T in bit 0), so we can use it
17129 // as-is, with no masking.
17130 assign( dst
, getIRegA(rM
) );
17132 putIRegA( 14, mkU32(guest_R15_curr_instr_notENC
+ 4),
17133 IRTemp_INVALID
/*because AL*/, Ijk_Boring
);
17135 llPutIReg(15, mkexpr(dst
));
17136 dres
.jk_StopHere
= link
? Ijk_Call
17137 : (rM
== 14 ? Ijk_Ret
: Ijk_Boring
);
17138 dres
.whatNext
= Dis_StopHere
;
17139 if (condT
== IRTemp_INVALID
) {
17140 DIP("b%sx r%u\n", link
? "l" : "", rM
);
17142 DIP("b%sx%s r%u\n", link
? "l" : "", nCC(INSN_COND
), rM
);
17144 goto decode_success
;
17146 /* else: (link && rM == 15): just fall through */
17149 /* --- NB: ARM interworking branches are in NV space, hence
17150 are handled elsewhere by decode_NV_instruction_ARMv7_and_below.
17154 /* --------------------- Clz --------------------- */
17156 if (INSN(27,20) == BITS8(0,0,0,1,0,1,1,0)
17157 && INSN(19,16) == BITS4(1,1,1,1)
17158 && INSN(11,4) == BITS8(1,1,1,1,0,0,0,1)) {
17159 UInt rD
= INSN(15,12);
17160 UInt rM
= INSN(3,0);
17161 IRTemp arg
= newTemp(Ity_I32
);
17162 IRTemp res
= newTemp(Ity_I32
);
17163 assign(arg
, getIRegA(rM
));
17164 assign(res
, IRExpr_ITE(
17165 binop(Iop_CmpEQ32
, mkexpr(arg
), mkU32(0)),
17167 unop(Iop_Clz32
, mkexpr(arg
))
17169 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
17170 DIP("clz%s r%u, r%u\n", nCC(INSN_COND
), rD
, rM
);
17171 goto decode_success
;
17174 /* --------------------- Mul etc --------------------- */
17176 if (BITS8(0,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
17177 && INSN(15,12) == BITS4(0,0,0,0)
17178 && INSN(7,4) == BITS4(1,0,0,1)) {
17179 UInt bitS
= (insn
>> 20) & 1; /* 20:20 */
17180 UInt rD
= INSN(19,16);
17181 UInt rS
= INSN(11,8);
17182 UInt rM
= INSN(3,0);
17183 if (rD
== 15 || rM
== 15 || rS
== 15) {
17184 /* Unpredictable; don't decode; fall through */
17186 IRTemp argL
= newTemp(Ity_I32
);
17187 IRTemp argR
= newTemp(Ity_I32
);
17188 IRTemp res
= newTemp(Ity_I32
);
17189 IRTemp oldC
= IRTemp_INVALID
;
17190 IRTemp oldV
= IRTemp_INVALID
;
17191 assign( argL
, getIRegA(rM
));
17192 assign( argR
, getIRegA(rS
));
17193 assign( res
, binop(Iop_Mul32
, mkexpr(argL
), mkexpr(argR
)) );
17195 oldC
= newTemp(Ity_I32
);
17196 assign(oldC
, mk_armg_calculate_flag_c());
17197 oldV
= newTemp(Ity_I32
);
17198 assign(oldV
, mk_armg_calculate_flag_v());
17200 // now update guest state
17201 putIRegA( rD
, mkexpr(res
), condT
, Ijk_Boring
);
17203 IRTemp pair
= newTemp(Ity_I32
);
17204 assign( pair
, binop(Iop_Or32
,
17205 binop(Iop_Shl32
, mkexpr(oldC
), mkU8(1)),
17207 setFlags_D1_ND( ARMG_CC_OP_MUL
, res
, pair
, condT
);
17209 DIP("mul%c%s r%u, r%u, r%u\n",
17210 bitS
? 's' : ' ', nCC(INSN_COND
), rD
, rM
, rS
);
17211 goto decode_success
;
17216 /* --------------------- Integer Divides --------------------- */
17218 if (BITS8(0,1,1,1,0,0,0,1) == INSN(27,20)
17219 && INSN(15,12) == BITS4(1,1,1,1)
17220 && INSN(7,4) == BITS4(0,0,0,1)) {
17221 UInt rD
= INSN(19,16);
17222 UInt rM
= INSN(11,8);
17223 UInt rN
= INSN(3,0);
17224 if (rD
== 15 || rM
== 15 || rN
== 15) {
17225 /* Unpredictable; don't decode; fall through */
17227 IRTemp res
= newTemp(Ity_I32
);
17228 IRTemp argL
= newTemp(Ity_I32
);
17229 IRTemp argR
= newTemp(Ity_I32
);
17230 assign(argL
, getIRegA(rN
));
17231 assign(argR
, getIRegA(rM
));
17232 assign(res
, binop(Iop_DivS32
, mkexpr(argL
), mkexpr(argR
)));
17233 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
17234 DIP("sdiv r%u, r%u, r%u\n", rD
, rN
, rM
);
17235 goto decode_success
;
17240 if (BITS8(0,1,1,1,0,0,1,1) == INSN(27,20)
17241 && INSN(15,12) == BITS4(1,1,1,1)
17242 && INSN(7,4) == BITS4(0,0,0,1)) {
17243 UInt rD
= INSN(19,16);
17244 UInt rM
= INSN(11,8);
17245 UInt rN
= INSN(3,0);
17246 if (rD
== 15 || rM
== 15 || rN
== 15) {
17247 /* Unpredictable; don't decode; fall through */
17249 IRTemp res
= newTemp(Ity_I32
);
17250 IRTemp argL
= newTemp(Ity_I32
);
17251 IRTemp argR
= newTemp(Ity_I32
);
17252 assign(argL
, getIRegA(rN
));
17253 assign(argR
, getIRegA(rM
));
17254 assign(res
, binop(Iop_DivU32
, mkexpr(argL
), mkexpr(argR
)));
17255 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
17256 DIP("udiv r%u, r%u, r%u\n", rD
, rN
, rM
);
17257 goto decode_success
;
17262 if (BITS8(0,0,0,0,0,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
17263 && INSN(7,4) == BITS4(1,0,0,1)) {
17264 UInt bitS
= (insn
>> 20) & 1; /* 20:20 */
17265 UInt isMLS
= (insn
>> 22) & 1; /* 22:22 */
17266 UInt rD
= INSN(19,16);
17267 UInt rN
= INSN(15,12);
17268 UInt rS
= INSN(11,8);
17269 UInt rM
= INSN(3,0);
17270 if (bitS
== 1 && isMLS
== 1) {
17271 /* This isn't allowed (MLS that sets flags). don't decode;
17275 if (rD
== 15 || rM
== 15 || rS
== 15 || rN
== 15) {
17276 /* Unpredictable; don't decode; fall through */
17278 IRTemp argL
= newTemp(Ity_I32
);
17279 IRTemp argR
= newTemp(Ity_I32
);
17280 IRTemp argP
= newTemp(Ity_I32
);
17281 IRTemp res
= newTemp(Ity_I32
);
17282 IRTemp oldC
= IRTemp_INVALID
;
17283 IRTemp oldV
= IRTemp_INVALID
;
17284 assign( argL
, getIRegA(rM
));
17285 assign( argR
, getIRegA(rS
));
17286 assign( argP
, getIRegA(rN
));
17287 assign( res
, binop(isMLS
? Iop_Sub32
: Iop_Add32
,
17289 binop(Iop_Mul32
, mkexpr(argL
), mkexpr(argR
)) ));
17291 vassert(!isMLS
); // guaranteed above
17292 oldC
= newTemp(Ity_I32
);
17293 assign(oldC
, mk_armg_calculate_flag_c());
17294 oldV
= newTemp(Ity_I32
);
17295 assign(oldV
, mk_armg_calculate_flag_v());
17297 // now update guest state
17298 putIRegA( rD
, mkexpr(res
), condT
, Ijk_Boring
);
17300 IRTemp pair
= newTemp(Ity_I32
);
17301 assign( pair
, binop(Iop_Or32
,
17302 binop(Iop_Shl32
, mkexpr(oldC
), mkU8(1)),
17304 setFlags_D1_ND( ARMG_CC_OP_MUL
, res
, pair
, condT
);
17306 DIP("ml%c%c%s r%u, r%u, r%u, r%u\n",
17307 isMLS
? 's' : 'a', bitS
? 's' : ' ',
17308 nCC(INSN_COND
), rD
, rM
, rS
, rN
);
17309 goto decode_success
;
17315 if (BITS8(0,0,0,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
17316 && INSN(7,4) == BITS4(1,0,0,1)) {
17317 UInt bitS
= (insn
>> 20) & 1; /* 20:20 */
17318 UInt rDhi
= INSN(19,16);
17319 UInt rDlo
= INSN(15,12);
17320 UInt rS
= INSN(11,8);
17321 UInt rM
= INSN(3,0);
17322 UInt isS
= (INSN(27,20) >> 2) & 1; /* 22:22 */
17323 if (rDhi
== 15 || rDlo
== 15 || rM
== 15 || rS
== 15 || rDhi
== rDlo
) {
17324 /* Unpredictable; don't decode; fall through */
17326 IRTemp argL
= newTemp(Ity_I32
);
17327 IRTemp argR
= newTemp(Ity_I32
);
17328 IRTemp res
= newTemp(Ity_I64
);
17329 IRTemp resHi
= newTemp(Ity_I32
);
17330 IRTemp resLo
= newTemp(Ity_I32
);
17331 IRTemp oldC
= IRTemp_INVALID
;
17332 IRTemp oldV
= IRTemp_INVALID
;
17333 IROp mulOp
= isS
? Iop_MullS32
: Iop_MullU32
;
17334 assign( argL
, getIRegA(rM
));
17335 assign( argR
, getIRegA(rS
));
17336 assign( res
, binop(mulOp
, mkexpr(argL
), mkexpr(argR
)) );
17337 assign( resHi
, unop(Iop_64HIto32
, mkexpr(res
)) );
17338 assign( resLo
, unop(Iop_64to32
, mkexpr(res
)) );
17340 oldC
= newTemp(Ity_I32
);
17341 assign(oldC
, mk_armg_calculate_flag_c());
17342 oldV
= newTemp(Ity_I32
);
17343 assign(oldV
, mk_armg_calculate_flag_v());
17345 // now update guest state
17346 putIRegA( rDhi
, mkexpr(resHi
), condT
, Ijk_Boring
);
17347 putIRegA( rDlo
, mkexpr(resLo
), condT
, Ijk_Boring
);
17349 IRTemp pair
= newTemp(Ity_I32
);
17350 assign( pair
, binop(Iop_Or32
,
17351 binop(Iop_Shl32
, mkexpr(oldC
), mkU8(1)),
17353 setFlags_D1_D2_ND( ARMG_CC_OP_MULL
, resLo
, resHi
, pair
, condT
);
17355 DIP("%cmull%c%s r%u, r%u, r%u, r%u\n",
17356 isS
? 's' : 'u', bitS
? 's' : ' ',
17357 nCC(INSN_COND
), rDlo
, rDhi
, rM
, rS
);
17358 goto decode_success
;
17364 if (BITS8(0,0,0,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
17365 && INSN(7,4) == BITS4(1,0,0,1)) {
17366 UInt bitS
= (insn
>> 20) & 1; /* 20:20 */
17367 UInt rDhi
= INSN(19,16);
17368 UInt rDlo
= INSN(15,12);
17369 UInt rS
= INSN(11,8);
17370 UInt rM
= INSN(3,0);
17371 UInt isS
= (INSN(27,20) >> 2) & 1; /* 22:22 */
17372 if (rDhi
== 15 || rDlo
== 15 || rM
== 15 || rS
== 15 || rDhi
== rDlo
) {
17373 /* Unpredictable; don't decode; fall through */
17375 IRTemp argL
= newTemp(Ity_I32
);
17376 IRTemp argR
= newTemp(Ity_I32
);
17377 IRTemp old
= newTemp(Ity_I64
);
17378 IRTemp res
= newTemp(Ity_I64
);
17379 IRTemp resHi
= newTemp(Ity_I32
);
17380 IRTemp resLo
= newTemp(Ity_I32
);
17381 IRTemp oldC
= IRTemp_INVALID
;
17382 IRTemp oldV
= IRTemp_INVALID
;
17383 IROp mulOp
= isS
? Iop_MullS32
: Iop_MullU32
;
17384 assign( argL
, getIRegA(rM
));
17385 assign( argR
, getIRegA(rS
));
17386 assign( old
, binop(Iop_32HLto64
, getIRegA(rDhi
), getIRegA(rDlo
)) );
17387 assign( res
, binop(Iop_Add64
,
17389 binop(mulOp
, mkexpr(argL
), mkexpr(argR
))) );
17390 assign( resHi
, unop(Iop_64HIto32
, mkexpr(res
)) );
17391 assign( resLo
, unop(Iop_64to32
, mkexpr(res
)) );
17393 oldC
= newTemp(Ity_I32
);
17394 assign(oldC
, mk_armg_calculate_flag_c());
17395 oldV
= newTemp(Ity_I32
);
17396 assign(oldV
, mk_armg_calculate_flag_v());
17398 // now update guest state
17399 putIRegA( rDhi
, mkexpr(resHi
), condT
, Ijk_Boring
);
17400 putIRegA( rDlo
, mkexpr(resLo
), condT
, Ijk_Boring
);
17402 IRTemp pair
= newTemp(Ity_I32
);
17403 assign( pair
, binop(Iop_Or32
,
17404 binop(Iop_Shl32
, mkexpr(oldC
), mkU8(1)),
17406 setFlags_D1_D2_ND( ARMG_CC_OP_MULL
, resLo
, resHi
, pair
, condT
);
17408 DIP("%cmlal%c%s r%u, r%u, r%u, r%u\n",
17409 isS
? 's' : 'u', bitS
? 's' : ' ', nCC(INSN_COND
),
17410 rDlo
, rDhi
, rM
, rS
);
17411 goto decode_success
;
17417 if (BITS8(0,0,0,0,0,1,0,0) == INSN(27,20) && INSN(7,4) == BITS4(1,0,0,1)) {
17418 UInt rDhi
= INSN(19,16);
17419 UInt rDlo
= INSN(15,12);
17420 UInt rM
= INSN(11,8);
17421 UInt rN
= INSN(3,0);
17422 if (rDlo
== 15 || rDhi
== 15 || rN
== 15 || rM
== 15 || rDhi
== rDlo
) {
17423 /* Unpredictable; don't decode; fall through */
17425 IRTemp argN
= newTemp(Ity_I32
);
17426 IRTemp argM
= newTemp(Ity_I32
);
17427 IRTemp argDhi
= newTemp(Ity_I32
);
17428 IRTemp argDlo
= newTemp(Ity_I32
);
17429 IRTemp res
= newTemp(Ity_I64
);
17430 IRTemp resHi
= newTemp(Ity_I32
);
17431 IRTemp resLo
= newTemp(Ity_I32
);
17432 assign( argN
, getIRegA(rN
) );
17433 assign( argM
, getIRegA(rM
) );
17434 assign( argDhi
, getIRegA(rDhi
) );
17435 assign( argDlo
, getIRegA(rDlo
) );
17439 binop(Iop_MullU32
, mkexpr(argN
), mkexpr(argM
)),
17440 unop(Iop_32Uto64
, mkexpr(argDhi
))),
17441 unop(Iop_32Uto64
, mkexpr(argDlo
))) );
17442 assign( resHi
, unop(Iop_64HIto32
, mkexpr(res
)) );
17443 assign( resLo
, unop(Iop_64to32
, mkexpr(res
)) );
17444 // now update guest state
17445 putIRegA( rDhi
, mkexpr(resHi
), condT
, Ijk_Boring
);
17446 putIRegA( rDlo
, mkexpr(resLo
), condT
, Ijk_Boring
);
17447 DIP("umaal %s r%u, r%u, r%u, r%u\n",
17448 nCC(INSN_COND
), rDlo
, rDhi
, rN
, rM
);
17449 goto decode_success
;
17454 /* --------------------- Msr etc --------------------- */
17457 if (INSN(27,20) == BITS8(0,0,1,1,0,0,1,0)
17458 && INSN(17,12) == BITS6(0,0,1,1,1,1)) {
17459 UInt write_ge
= INSN(18,18);
17460 UInt write_nzcvq
= INSN(19,19);
17461 if (write_nzcvq
|| write_ge
) {
17462 UInt imm
= (INSN(11,0) >> 0) & 0xFF;
17463 UInt rot
= 2 * ((INSN(11,0) >> 8) & 0xF);
17464 IRTemp immT
= newTemp(Ity_I32
);
17465 vassert(rot
<= 30);
17466 imm
= ROR32(imm
, rot
);
17467 assign(immT
, mkU32(imm
));
17468 desynthesise_APSR( write_nzcvq
, write_ge
, immT
, condT
);
17469 DIP("msr%s cpsr%s%sf, #0x%08x\n", nCC(INSN_COND
),
17470 write_nzcvq
? "f" : "", write_ge
? "g" : "", imm
);
17471 goto decode_success
;
17477 if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
17478 && INSN(17,12) == BITS6(0,0,1,1,1,1)
17479 && INSN(11,4) == BITS8(0,0,0,0,0,0,0,0)) {
17480 UInt rN
= INSN(3,0);
17481 UInt write_ge
= INSN(18,18);
17482 UInt write_nzcvq
= INSN(19,19);
17483 if (rN
!= 15 && (write_nzcvq
|| write_ge
)) {
17484 IRTemp rNt
= newTemp(Ity_I32
);
17485 assign(rNt
, getIRegA(rN
));
17486 desynthesise_APSR( write_nzcvq
, write_ge
, rNt
, condT
);
17487 DIP("msr%s cpsr_%s%s, r%u\n", nCC(INSN_COND
),
17488 write_nzcvq
? "f" : "", write_ge
? "g" : "", rN
);
17489 goto decode_success
;
17495 if ((insn
& 0x0FFF0FFF) == 0x010F0000) {
17496 UInt rD
= INSN(15,12);
17498 IRTemp apsr
= synthesise_APSR();
17499 putIRegA( rD
, mkexpr(apsr
), condT
, Ijk_Boring
);
17500 DIP("mrs%s r%u, cpsr\n", nCC(INSN_COND
), rD
);
17501 goto decode_success
;
17506 /* --------------------- Svc --------------------- */
17507 if (BITS8(1,1,1,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))) {
17508 UInt imm24
= (insn
>> 0) & 0xFFFFFF;
17510 /* A syscall. We can't do this conditionally, hence: */
17511 if (condT
!= IRTemp_INVALID
) {
17512 mk_skip_over_A32_if_cond_is_false( condT
);
17515 llPutIReg(15, mkU32( guest_R15_curr_instr_notENC
+ 4 ));
17516 dres
.jk_StopHere
= Ijk_Sys_syscall
;
17517 dres
.whatNext
= Dis_StopHere
;
17518 DIP("svc%s #0x%08x\n", nCC(INSN_COND
), imm24
);
17519 goto decode_success
;
17524 /* ------------------------ swp ------------------------ */
17527 if (BITS8(0,0,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
17528 && BITS4(0,0,0,0) == INSN(11,8)
17529 && BITS4(1,0,0,1) == INSN(7,4)) {
17530 UInt rN
= INSN(19,16);
17531 UInt rD
= INSN(15,12);
17532 UInt rM
= INSN(3,0);
17533 IRTemp tRn
= newTemp(Ity_I32
);
17534 IRTemp tNew
= newTemp(Ity_I32
);
17535 IRTemp tOld
= IRTemp_INVALID
;
17536 IRTemp tSC1
= newTemp(Ity_I1
);
17537 UInt isB
= (insn
>> 22) & 1;
17539 if (rD
== 15 || rN
== 15 || rM
== 15 || rN
== rM
|| rN
== rD
) {
17540 /* undecodable; fall through */
17542 /* make unconditional */
17543 if (condT
!= IRTemp_INVALID
) {
17544 mk_skip_over_A32_if_cond_is_false( condT
);
17545 condT
= IRTemp_INVALID
;
17547 /* Ok, now we're unconditional. Generate a LL-SC loop. */
17548 assign(tRn
, getIRegA(rN
));
17549 assign(tNew
, getIRegA(rM
));
17552 tOld
= newTemp(Ity_I8
);
17553 stmt( IRStmt_LLSC(Iend_LE
, tOld
, mkexpr(tRn
),
17555 stmt( IRStmt_LLSC(Iend_LE
, tSC1
, mkexpr(tRn
),
17556 unop(Iop_32to8
, mkexpr(tNew
))) );
17559 tOld
= newTemp(Ity_I32
);
17560 stmt( IRStmt_LLSC(Iend_LE
, tOld
, mkexpr(tRn
),
17562 stmt( IRStmt_LLSC(Iend_LE
, tSC1
, mkexpr(tRn
),
17565 stmt( IRStmt_Exit(unop(Iop_Not1
, mkexpr(tSC1
)),
17566 /*Ijk_NoRedir*/Ijk_Boring
,
17567 IRConst_U32(guest_R15_curr_instr_notENC
),
17569 putIRegA(rD
, isB
? unop(Iop_8Uto32
, mkexpr(tOld
)) : mkexpr(tOld
),
17570 IRTemp_INVALID
, Ijk_Boring
);
17571 DIP("swp%s%s r%u, r%u, [r%u]\n",
17572 isB
? "b" : "", nCC(INSN_COND
), rD
, rM
, rN
);
17573 goto decode_success
;
17578 /* ----------------------------------------------------------- */
17579 /* -- ARMv6 instructions -- */
17580 /* ----------------------------------------------------------- */
17582 /* ------------------- {ldr,str}ex{,b,h,d} ------------------- */
17584 // LDREXD, LDREX, LDREXH, LDREXB
17585 if (0x01900F9F == (insn
& 0x0F900FFF)) {
17586 UInt rT
= INSN(15,12);
17587 UInt rN
= INSN(19,16);
17588 IRType ty
= Ity_INVALID
;
17589 IROp widen
= Iop_INVALID
;
17590 const HChar
* nm
= NULL
;
17592 switch (INSN(22,21)) {
17593 case 0: nm
= ""; ty
= Ity_I32
; break;
17594 case 1: nm
= "d"; ty
= Ity_I64
; break;
17595 case 2: nm
= "b"; ty
= Ity_I8
; widen
= Iop_8Uto32
; break;
17596 case 3: nm
= "h"; ty
= Ity_I16
; widen
= Iop_16Uto32
; break;
17597 default: vassert(0);
17599 if (ty
== Ity_I32
|| ty
== Ity_I16
|| ty
== Ity_I8
) {
17600 if (rT
== 15 || rN
== 15)
17603 vassert(ty
== Ity_I64
);
17604 if ((rT
& 1) == 1 || rT
== 14 || rN
== 15)
17609 /* make unconditional */
17610 if (condT
!= IRTemp_INVALID
) {
17611 mk_skip_over_A32_if_cond_is_false( condT
);
17612 condT
= IRTemp_INVALID
;
17614 /* Ok, now we're unconditional. Do the load. */
17616 // FIXME: assumes little-endian guest
17617 stmt( IRStmt_LLSC(Iend_LE
, res
, getIRegA(rN
),
17618 NULL
/*this is a load*/) );
17619 if (ty
== Ity_I64
) {
17620 // FIXME: assumes little-endian guest
17621 putIRegA(rT
+0, unop(Iop_64to32
, mkexpr(res
)),
17622 IRTemp_INVALID
, Ijk_Boring
);
17623 putIRegA(rT
+1, unop(Iop_64HIto32
, mkexpr(res
)),
17624 IRTemp_INVALID
, Ijk_Boring
);
17625 DIP("ldrex%s%s r%u, r%u, [r%u]\n",
17626 nm
, nCC(INSN_COND
), rT
+0, rT
+1, rN
);
17628 putIRegA(rT
, widen
== Iop_INVALID
17629 ? mkexpr(res
) : unop(widen
, mkexpr(res
)),
17630 IRTemp_INVALID
, Ijk_Boring
);
17631 DIP("ldrex%s%s r%u, [r%u]\n", nm
, nCC(INSN_COND
), rT
, rN
);
17633 goto decode_success
;
17635 /* undecodable; fall through */
17638 // STREXD, STREX, STREXH, STREXB
17639 if (0x01800F90 == (insn
& 0x0F900FF0)) {
17640 UInt rT
= INSN(3,0);
17641 UInt rN
= INSN(19,16);
17642 UInt rD
= INSN(15,12);
17643 IRType ty
= Ity_INVALID
;
17644 IROp narrow
= Iop_INVALID
;
17645 const HChar
* nm
= NULL
;
17647 switch (INSN(22,21)) {
17648 case 0: nm
= ""; ty
= Ity_I32
; break;
17649 case 1: nm
= "d"; ty
= Ity_I64
; break;
17650 case 2: nm
= "b"; ty
= Ity_I8
; narrow
= Iop_32to8
; break;
17651 case 3: nm
= "h"; ty
= Ity_I16
; narrow
= Iop_32to16
; break;
17652 default: vassert(0);
17654 if (ty
== Ity_I32
|| ty
== Ity_I16
|| ty
== Ity_I8
) {
17655 if (rD
== 15 || rN
== 15 || rT
== 15
17656 || rD
== rN
|| rD
== rT
)
17659 vassert(ty
== Ity_I64
);
17660 if (rD
== 15 || (rT
& 1) == 1 || rT
== 14 || rN
== 15
17661 || rD
== rN
|| rD
== rT
|| rD
== rT
+1)
17665 IRTemp resSC1
, resSC32
, data
;
17666 /* make unconditional */
17667 if (condT
!= IRTemp_INVALID
) {
17668 mk_skip_over_A32_if_cond_is_false( condT
);
17669 condT
= IRTemp_INVALID
;
17671 /* Ok, now we're unconditional. Do the store. */
17672 data
= newTemp(ty
);
17675 // FIXME: assumes little-endian guest
17676 ? binop(Iop_32HLto64
, getIRegA(rT
+1), getIRegA(rT
+0))
17677 : narrow
== Iop_INVALID
17679 : unop(narrow
, getIRegA(rT
)));
17680 resSC1
= newTemp(Ity_I1
);
17681 // FIXME: assumes little-endian guest
17682 stmt( IRStmt_LLSC(Iend_LE
, resSC1
, getIRegA(rN
), mkexpr(data
)) );
17684 /* Set rD to 1 on failure, 0 on success. Currently we have
17685 resSC1 == 0 on failure, 1 on success. */
17686 resSC32
= newTemp(Ity_I32
);
17688 unop(Iop_1Uto32
, unop(Iop_Not1
, mkexpr(resSC1
))));
17690 putIRegA(rD
, mkexpr(resSC32
),
17691 IRTemp_INVALID
, Ijk_Boring
);
17692 if (ty
== Ity_I64
) {
17693 DIP("strex%s%s r%u, r%u, r%u, [r%u]\n",
17694 nm
, nCC(INSN_COND
), rD
, rT
, rT
+1, rN
);
17696 DIP("strex%s%s r%u, r%u, [r%u]\n",
17697 nm
, nCC(INSN_COND
), rD
, rT
, rN
);
17699 goto decode_success
;
17704 /* --------------------- movw, movt --------------------- */
17705 if (0x03000000 == (insn
& 0x0FF00000)
17706 || 0x03400000 == (insn
& 0x0FF00000)) /* pray for CSE */ {
17707 UInt rD
= INSN(15,12);
17708 UInt imm16
= (insn
& 0xFFF) | ((insn
>> 4) & 0x0000F000);
17709 UInt isT
= (insn
>> 22) & 1;
17716 binop(Iop_And32
, getIRegA(rD
), mkU32(0xFFFF)),
17717 mkU32(imm16
<< 16)),
17718 condT
, Ijk_Boring
);
17719 DIP("movt%s r%u, #0x%04x\n", nCC(INSN_COND
), rD
, imm16
);
17720 goto decode_success
;
17722 putIRegA(rD
, mkU32(imm16
), condT
, Ijk_Boring
);
17723 DIP("movw%s r%u, #0x%04x\n", nCC(INSN_COND
), rD
, imm16
);
17724 goto decode_success
;
17730 /* ----------- uxtb, sxtb, uxth, sxth, uxtb16, sxtb16 ----------- */
17731 /* FIXME: this is an exact duplicate of the Thumb version. They
17732 should be commoned up. */
17733 if (BITS8(0,1,1,0,1, 0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,0))
17734 && BITS4(1,1,1,1) == INSN(19,16)
17735 && BITS4(0,1,1,1) == INSN(7,4)
17736 && BITS4(0,0, 0,0) == (INSN(11,8) & BITS4(0,0,1,1))) {
17737 UInt subopc
= INSN(27,20) & BITS8(0,0,0,0,0, 1,1,1);
17738 if (subopc
!= BITS4(0,0,0,1) && subopc
!= BITS4(0,1,0,1)) {
17739 Int rot
= (INSN(11,8) >> 2) & 3;
17740 UInt rM
= INSN(3,0);
17741 UInt rD
= INSN(15,12);
17742 IRTemp srcT
= newTemp(Ity_I32
);
17743 IRTemp rotT
= newTemp(Ity_I32
);
17744 IRTemp dstT
= newTemp(Ity_I32
);
17745 const HChar
* nm
= "???";
17746 assign(srcT
, getIRegA(rM
));
17747 assign(rotT
, genROR32(srcT
, 8 * rot
)); /* 0, 8, 16 or 24 only */
17749 case BITS4(0,1,1,0): // UXTB
17750 assign(dstT
, unop(Iop_8Uto32
, unop(Iop_32to8
, mkexpr(rotT
))));
17753 case BITS4(0,0,1,0): // SXTB
17754 assign(dstT
, unop(Iop_8Sto32
, unop(Iop_32to8
, mkexpr(rotT
))));
17757 case BITS4(0,1,1,1): // UXTH
17758 assign(dstT
, unop(Iop_16Uto32
, unop(Iop_32to16
, mkexpr(rotT
))));
17761 case BITS4(0,0,1,1): // SXTH
17762 assign(dstT
, unop(Iop_16Sto32
, unop(Iop_32to16
, mkexpr(rotT
))));
17765 case BITS4(0,1,0,0): // UXTB16
17766 assign(dstT
, binop(Iop_And32
, mkexpr(rotT
), mkU32(0x00FF00FF)));
17769 case BITS4(0,0,0,0): { // SXTB16
17770 IRTemp lo32
= newTemp(Ity_I32
);
17771 IRTemp hi32
= newTemp(Ity_I32
);
17772 assign(lo32
, binop(Iop_And32
, mkexpr(rotT
), mkU32(0xFF)));
17773 assign(hi32
, binop(Iop_Shr32
, mkexpr(rotT
), mkU8(16)));
17779 unop(Iop_32to8
, mkexpr(lo32
))),
17783 unop(Iop_32to8
, mkexpr(hi32
))),
17790 vassert(0); // guarded by "if" above
17792 putIRegA(rD
, mkexpr(dstT
), condT
, Ijk_Boring
);
17793 DIP("%s%s r%u, r%u, ROR #%d\n", nm
, nCC(INSN_COND
), rD
, rM
, rot
);
17794 goto decode_success
;
17799 /* ------------------- bfi, bfc ------------------- */
17800 if (BITS8(0,1,1,1,1,1,0, 0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
17801 && BITS4(0, 0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
17802 UInt rD
= INSN(15,12);
17803 UInt rN
= INSN(3,0);
17804 UInt msb
= (insn
>> 16) & 0x1F; /* 20:16 */
17805 UInt lsb
= (insn
>> 7) & 0x1F; /* 11:7 */
17806 if (rD
== 15 || msb
< lsb
) {
17807 /* undecodable; fall through */
17809 IRTemp src
= newTemp(Ity_I32
);
17810 IRTemp olddst
= newTemp(Ity_I32
);
17811 IRTemp newdst
= newTemp(Ity_I32
);
17812 UInt mask
= ((UInt
)1) << (msb
- lsb
);
17813 mask
= (mask
- 1) + mask
;
17814 vassert(mask
!= 0); // guaranteed by "msb < lsb" check above
17817 assign(src
, rN
== 15 ? mkU32(0) : getIRegA(rN
));
17818 assign(olddst
, getIRegA(rD
));
17822 binop(Iop_Shl32
, mkexpr(src
), mkU8(lsb
)),
17829 putIRegA(rD
, mkexpr(newdst
), condT
, Ijk_Boring
);
17832 DIP("bfc%s r%u, #%u, #%u\n",
17833 nCC(INSN_COND
), rD
, lsb
, msb
-lsb
+1);
17835 DIP("bfi%s r%u, r%u, #%u, #%u\n",
17836 nCC(INSN_COND
), rD
, rN
, lsb
, msb
-lsb
+1);
17838 goto decode_success
;
17843 /* ------------------- {u,s}bfx ------------------- */
17844 if (BITS8(0,1,1,1,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
17845 && BITS4(0,1,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
17846 UInt rD
= INSN(15,12);
17847 UInt rN
= INSN(3,0);
17848 UInt wm1
= (insn
>> 16) & 0x1F; /* 20:16 */
17849 UInt lsb
= (insn
>> 7) & 0x1F; /* 11:7 */
17850 UInt msb
= lsb
+ wm1
;
17851 UInt isU
= (insn
>> 22) & 1; /* 22:22 */
17852 if (rD
== 15 || rN
== 15 || msb
>= 32) {
17853 /* undecodable; fall through */
17855 IRTemp src
= newTemp(Ity_I32
);
17856 IRTemp tmp
= newTemp(Ity_I32
);
17857 IRTemp res
= newTemp(Ity_I32
);
17858 UInt mask
= ((1 << wm1
) - 1) + (1 << wm1
);
17859 vassert(msb
>= 0 && msb
<= 31);
17860 vassert(mask
!= 0); // guaranteed by msb being in 0 .. 31 inclusive
17862 assign(src
, getIRegA(rN
));
17863 assign(tmp
, binop(Iop_And32
,
17864 binop(Iop_Shr32
, mkexpr(src
), mkU8(lsb
)),
17866 assign(res
, binop(isU
? Iop_Shr32
: Iop_Sar32
,
17867 binop(Iop_Shl32
, mkexpr(tmp
), mkU8(31-wm1
)),
17870 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
17872 DIP("%s%s r%u, r%u, #%u, #%u\n",
17873 isU
? "ubfx" : "sbfx",
17874 nCC(INSN_COND
), rD
, rN
, lsb
, wm1
+ 1);
17875 goto decode_success
;
17880 /* --------------------- Load/store doubleword ------------- */
17882 /* 31 27 23 19 15 11 7 3 # highest bit
17883 28 24 20 16 12 8 4 0
17884 A5-36 1 | 16 cond 0001 U100 Rn Rd im4h 11S1 im4l
17885 A5-38 1 | 32 cond 0001 U000 Rn Rd 0000 11S1 Rm
17886 A5-40 2 | 16 cond 0001 U110 Rn Rd im4h 11S1 im4l
17887 A5-42 2 | 32 cond 0001 U010 Rn Rd 0000 11S1 Rm
17888 A5-44 3 | 16 cond 0000 U100 Rn Rd im4h 11S1 im4l
17889 A5-46 3 | 32 cond 0000 U000 Rn Rd 0000 11S1 Rm
17892 1 at-ea (access at ea)
17893 2 at-ea-then-upd (access at ea, then Rn = ea)
17894 3 at-Rn-then-upd (access at Rn, then Rn = ea)
17899 /* Quickly skip over all of this for hopefully most instructions */
17900 if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
17901 goto after_load_store_doubleword
;
17903 /* Check the "11S1" thing. */
17904 if ((INSN(7,4) & BITS4(1,1,0,1)) != BITS4(1,1,0,1))
17905 goto after_load_store_doubleword
;
17909 /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,0,0)) {
17912 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,0,0)) {
17915 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,1,0)) {
17918 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,1,0)) {
17921 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(1,0,0)) {
17924 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(0,0,0)) {
17927 else goto after_load_store_doubleword
;
17929 { UInt rN
= (insn
>> 16) & 0xF; /* 19:16 */
17930 UInt rD
= (insn
>> 12) & 0xF; /* 15:12 */
17931 UInt rM
= (insn
>> 0) & 0xF; /* 3:0 */
17932 UInt bU
= (insn
>> 23) & 1; /* 23 U=1 offset+, U=0 offset- */
17933 UInt bS
= (insn
>> 5) & 1; /* S=1 store, S=0 load */
17934 UInt imm8
= ((insn
>> 4) & 0xF0) | (insn
& 0xF); /* 11:8, 3:0 */
17936 /* Require rD to be an even numbered register */
17938 goto after_load_store_doubleword
;
17940 /* Require 11:8 == 0 for Rn +/- Rm cases */
17941 if ((summary
& 32) != 0 && (imm8
& 0xF0) != 0)
17942 goto after_load_store_doubleword
;
17944 /* Skip some invalid cases, which would lead to two competing
17945 updates to the same register, or which are otherwise
17946 disallowed by the spec. */
17951 if (rM
== 15) goto after_load_store_doubleword
;
17953 case 2 | 16: case 3 | 16:
17954 if (rN
== 15) goto after_load_store_doubleword
;
17955 if (bS
== 0 && (rN
== rD
|| rN
== rD
+1))
17956 goto after_load_store_doubleword
;
17958 case 2 | 32: case 3 | 32:
17959 if (rM
== 15) goto after_load_store_doubleword
;
17960 if (rN
== 15) goto after_load_store_doubleword
;
17961 if (rN
== rM
) goto after_load_store_doubleword
;
17962 if (bS
== 0 && (rN
== rD
|| rN
== rD
+1))
17963 goto after_load_store_doubleword
;
17969 /* If this is a branch, make it unconditional at this point.
17970 Doing conditional branches in-line is too complex (for
17972 vassert((rD
& 1) == 0); /* from tests above */
17973 if (bS
== 0 && rD
+1 == 15 && condT
!= IRTemp_INVALID
) {
17975 mk_skip_over_A32_if_cond_is_false( condT
);
17976 condT
= IRTemp_INVALID
;
17980 /* compute the effective address. Bind it to a tmp since we
17981 may need to use it twice. */
17982 IRExpr
* eaE
= NULL
;
17983 switch (summary
& 0xF0) {
17985 eaE
= mk_EA_reg_plusminus_imm8( rN
, bU
, imm8
, dis_buf
);
17988 eaE
= mk_EA_reg_plusminus_reg( rN
, bU
, rM
, dis_buf
);
17992 IRTemp eaT
= newTemp(Ity_I32
);
17995 /* get the old Rn value */
17996 IRTemp rnT
= newTemp(Ity_I32
);
17997 assign(rnT
, getIRegA(rN
));
17999 /* decide on the transfer address */
18000 IRTemp taT
= IRTemp_INVALID
;
18001 switch (summary
& 0x0F) {
18002 case 1: case 2: taT
= eaT
; break;
18003 case 3: taT
= rnT
; break;
18005 vassert(taT
!= IRTemp_INVALID
);
18007 /* XXX deal with alignment constraints */
18008 /* XXX: but the A8 doesn't seem to trap for misaligned loads, so,
18009 ignore alignment issues for the time being. */
18011 /* For almost all cases, we do the writeback after the transfers.
18012 However, that leaves the stack "uncovered" in cases like:
18014 strd rD, [sp, #-16]
18015 In which case, do the writeback to SP now, instead of later.
18016 This is bad in that it makes the insn non-restartable if the
18017 accesses fault, but at least keeps Memcheck happy. */
18018 Bool writeback_already_done
= False
;
18019 if (bS
== 1 /*store*/ && summary
== (2 | 16)
18020 && rN
== 13 && rN
!= rD
&& rN
!= rD
+1
18021 && bU
== 0/*minus*/
18022 && (imm8
== 8 || imm8
== 16)) {
18023 putIRegA( rN
, mkexpr(eaT
), condT
, Ijk_Boring
);
18024 writeback_already_done
= True
;
18027 /* doubleword store S 1
18028 doubleword load S 0
18030 const HChar
* name
= NULL
;
18031 /* generate the transfers */
18032 if (bS
== 1) { // doubleword store
18033 storeGuardedLE( binop(Iop_Add32
, mkexpr(taT
), mkU32(0)),
18034 getIRegA(rD
+0), condT
);
18035 storeGuardedLE( binop(Iop_Add32
, mkexpr(taT
), mkU32(4)),
18036 getIRegA(rD
+1), condT
);
18038 } else { // doubleword load
18039 IRTemp oldRd0
= newTemp(Ity_I32
);
18040 IRTemp oldRd1
= newTemp(Ity_I32
);
18041 assign(oldRd0
, llGetIReg(rD
+0));
18042 assign(oldRd1
, llGetIReg(rD
+1));
18043 IRTemp newRd0
= newTemp(Ity_I32
);
18044 IRTemp newRd1
= newTemp(Ity_I32
);
18045 loadGuardedLE( newRd0
, ILGop_Ident32
,
18046 binop(Iop_Add32
, mkexpr(taT
), mkU32(0)),
18047 mkexpr(oldRd0
), condT
);
18048 putIRegA( rD
+0, mkexpr(newRd0
), IRTemp_INVALID
, Ijk_Boring
);
18049 loadGuardedLE( newRd1
, ILGop_Ident32
,
18050 binop(Iop_Add32
, mkexpr(taT
), mkU32(4)),
18051 mkexpr(oldRd1
), condT
);
18052 putIRegA( rD
+1, mkexpr(newRd1
), IRTemp_INVALID
, Ijk_Boring
);
18056 /* Update Rn if necessary. */
18057 switch (summary
& 0x0F) {
18059 // should be assured by logic above:
18060 vassert(rN
!= 15); /* from checks above */
18062 vassert(rD
+0 != rN
); /* since we just wrote rD+0 */
18063 vassert(rD
+1 != rN
); /* since we just wrote rD+1 */
18065 if (!writeback_already_done
)
18066 putIRegA( rN
, mkexpr(eaT
), condT
, Ijk_Boring
);
18070 switch (summary
& 0x0F) {
18071 case 1: DIP("%s%s r%u, %s\n", name
, nCC(INSN_COND
), rD
, dis_buf
);
18073 case 2: DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
18074 name
, nCC(INSN_COND
), rD
, dis_buf
);
18076 case 3: DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
18077 name
, nCC(INSN_COND
), rD
, dis_buf
);
18079 default: vassert(0);
18082 goto decode_success
;
18085 after_load_store_doubleword
:
18087 /* ------------------- {s,u}xtab ------------- */
18088 if (BITS8(0,1,1,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
18089 && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
18090 && BITS4(0,1,1,1) == INSN(7,4)) {
18091 UInt rN
= INSN(19,16);
18092 UInt rD
= INSN(15,12);
18093 UInt rM
= INSN(3,0);
18094 UInt rot
= (insn
>> 10) & 3;
18095 UInt isU
= INSN(22,22);
18096 if (rN
== 15/*it's {S,U}XTB*/ || rD
== 15 || rM
== 15) {
18097 /* undecodable; fall through */
18099 IRTemp srcL
= newTemp(Ity_I32
);
18100 IRTemp srcR
= newTemp(Ity_I32
);
18101 IRTemp res
= newTemp(Ity_I32
);
18102 assign(srcR
, getIRegA(rM
));
18103 assign(srcL
, getIRegA(rN
));
18104 assign(res
, binop(Iop_Add32
,
18106 unop(isU
? Iop_8Uto32
: Iop_8Sto32
,
18108 genROR32(srcR
, 8 * rot
)))));
18109 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
18110 DIP("%cxtab%s r%u, r%u, r%u, ror #%u\n",
18111 isU
? 'u' : 's', nCC(INSN_COND
), rD
, rN
, rM
, rot
);
18112 goto decode_success
;
18117 /* ------------------- {s,u}xtah ------------- */
18118 if (BITS8(0,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
18119 && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
18120 && BITS4(0,1,1,1) == INSN(7,4)) {
18121 UInt rN
= INSN(19,16);
18122 UInt rD
= INSN(15,12);
18123 UInt rM
= INSN(3,0);
18124 UInt rot
= (insn
>> 10) & 3;
18125 UInt isU
= INSN(22,22);
18126 if (rN
== 15/*it's {S,U}XTH*/ || rD
== 15 || rM
== 15) {
18127 /* undecodable; fall through */
18129 IRTemp srcL
= newTemp(Ity_I32
);
18130 IRTemp srcR
= newTemp(Ity_I32
);
18131 IRTemp res
= newTemp(Ity_I32
);
18132 assign(srcR
, getIRegA(rM
));
18133 assign(srcL
, getIRegA(rN
));
18134 assign(res
, binop(Iop_Add32
,
18136 unop(isU
? Iop_16Uto32
: Iop_16Sto32
,
18138 genROR32(srcR
, 8 * rot
)))));
18139 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
18141 DIP("%cxtah%s r%u, r%u, r%u, ror #%u\n",
18142 isU
? 'u' : 's', nCC(INSN_COND
), rD
, rN
, rM
, rot
);
18143 goto decode_success
;
18148 /* ------------------- rev16, rev ------------------ */
18149 if (INSN(27,16) == 0x6BF
18150 && (INSN(11,4) == 0xFB/*rev16*/ || INSN(11,4) == 0xF3/*rev*/)) {
18151 Bool isREV
= INSN(11,4) == 0xF3;
18152 UInt rM
= INSN(3,0);
18153 UInt rD
= INSN(15,12);
18154 if (rM
!= 15 && rD
!= 15) {
18155 IRTemp rMt
= newTemp(Ity_I32
);
18156 assign(rMt
, getIRegA(rM
));
18157 IRTemp res
= isREV
? gen_REV(rMt
) : gen_REV16(rMt
);
18158 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
18159 DIP("rev%s%s r%u, r%u\n", isREV
? "" : "16",
18160 nCC(INSN_COND
), rD
, rM
);
18161 goto decode_success
;
18165 /* ------------------- revsh ----------------------- */
18166 if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xFB) {
18167 UInt rM
= INSN(3,0);
18168 UInt rD
= INSN(15,12);
18169 if (rM
!= 15 && rD
!= 15) {
18170 IRTemp irt_rM
= newTemp(Ity_I32
);
18171 IRTemp irt_hi
= newTemp(Ity_I32
);
18172 IRTemp irt_low
= newTemp(Ity_I32
);
18173 IRTemp irt_res
= newTemp(Ity_I32
);
18174 assign(irt_rM
, getIRegA(rM
));
18177 binop(Iop_Shl32
, mkexpr(irt_rM
), mkU8(24)),
18183 binop(Iop_Shr32
, mkexpr(irt_rM
), mkU8(8)),
18188 binop(Iop_Or32
, mkexpr(irt_hi
), mkexpr(irt_low
))
18190 putIRegA(rD
, mkexpr(irt_res
), condT
, Ijk_Boring
);
18191 DIP("revsh%s r%u, r%u\n", nCC(INSN_COND
), rD
, rM
);
18192 goto decode_success
;
18196 /* ------------------- rbit ------------------ */
18197 if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) {
18198 UInt rD
= INSN(15,12);
18199 UInt rM
= INSN(3,0);
18200 if (rD
!= 15 && rM
!= 15) {
18201 IRTemp arg
= newTemp(Ity_I32
);
18202 assign(arg
, getIRegA(rM
));
18203 IRTemp res
= gen_BITREV(arg
);
18204 putIRegA(rD
, mkexpr(res
), condT
, Ijk_Boring
);
18205 DIP("rbit r%u, r%u\n", rD
, rM
);
18206 goto decode_success
;
18210 /* ------------------- smmul ------------------ */
18211 if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
18212 && INSN(15,12) == BITS4(1,1,1,1)
18213 && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
18214 UInt bitR
= INSN(5,5);
18215 UInt rD
= INSN(19,16);
18216 UInt rM
= INSN(11,8);
18217 UInt rN
= INSN(3,0);
18218 if (rD
!= 15 && rM
!= 15 && rN
!= 15) {
18220 = unop(Iop_64HIto32
,
18222 binop(Iop_MullS32
, getIRegA(rN
), getIRegA(rM
)),
18223 mkU64(bitR
? 0x80000000ULL
: 0ULL)));
18224 putIRegA(rD
, res
, condT
, Ijk_Boring
);
18225 DIP("smmul%s%s r%u, r%u, r%u\n",
18226 nCC(INSN_COND
), bitR
? "r" : "", rD
, rN
, rM
);
18227 goto decode_success
;
18231 /* ------------------- smmla ------------------ */
18232 if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
18233 && INSN(15,12) != BITS4(1,1,1,1)
18234 && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
18235 UInt bitR
= INSN(5,5);
18236 UInt rD
= INSN(19,16);
18237 UInt rA
= INSN(15,12);
18238 UInt rM
= INSN(11,8);
18239 UInt rN
= INSN(3,0);
18240 if (rD
!= 15 && rM
!= 15 && rN
!= 15) {
18242 = unop(Iop_64HIto32
,
18245 binop(Iop_32HLto64
, getIRegA(rA
), mkU32(0)),
18246 binop(Iop_MullS32
, getIRegA(rN
), getIRegA(rM
))),
18247 mkU64(bitR
? 0x80000000ULL
: 0ULL)));
18248 putIRegA(rD
, res
, condT
, Ijk_Boring
);
18249 DIP("smmla%s%s r%u, r%u, r%u, r%u\n",
18250 nCC(INSN_COND
), bitR
? "r" : "", rD
, rN
, rM
, rA
);
18251 goto decode_success
;
18255 /* -------------- (A1) LDRT reg+/-#imm12 -------------- */
18256 /* Load Register Unprivileged:
18257 ldrt<c> Rt, [Rn] {, #+/-imm12}
18259 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,0,0,0,0,1,1) ) {
18260 UInt rT
= INSN(15,12);
18261 UInt rN
= INSN(19,16);
18262 UInt imm12
= INSN(11,0);
18263 UInt bU
= INSN(23,23);
18265 if (rT
== 15 || rN
== 15 || rN
== rT
) valid
= False
;
18267 IRTemp newRt
= newTemp(Ity_I32
);
18268 loadGuardedLE( newRt
,
18269 ILGop_Ident32
, getIRegA(rN
), getIRegA(rT
), condT
);
18270 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18271 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18272 getIRegA(rN
), mkU32(imm12
));
18273 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18274 DIP("ldrt%s r%u, [r%u], #%c%u\n",
18275 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm12
);
18276 goto decode_success
;
18280 /* -------------- (A2) LDRT reg+/-reg with shift -------------- */
18281 /* Load Register Unprivileged:
18282 ldrt<c> Rt, [Rn], +/-Rm{, shift}
18284 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,1,0,0,0,1,1)
18285 && INSN(4,4) == 0 ) {
18286 UInt rT
= INSN(15,12);
18287 UInt rN
= INSN(19,16);
18288 UInt rM
= INSN(3,0);
18289 UInt imm5
= INSN(11,7);
18290 UInt bU
= INSN(23,23);
18291 UInt type
= INSN(6,5);
18293 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15
18294 /* || (ArchVersion() < 6 && rM == rN) */)
18297 IRTemp newRt
= newTemp(Ity_I32
);
18298 loadGuardedLE( newRt
,
18299 ILGop_Ident32
, getIRegA(rN
), getIRegA(rT
), condT
);
18300 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18301 // dis_buf generated is slightly bogus, in fact.
18302 IRExpr
* erN
= mk_EA_reg_plusminus_shifted_reg(rN
, bU
, rM
,
18303 type
, imm5
, dis_buf
);
18304 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18305 DIP("ldrt%s r%u, %s\n", nCC(INSN_COND
), rT
, dis_buf
);
18306 goto decode_success
;
18310 /* -------------- (A1) LDRBT reg+/-#imm12 -------------- */
18311 /* Load Register Byte Unprivileged:
18312 ldrbt<c> Rt, [Rn], #+/-imm12
18314 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,0,0,0,1,1,1) ) {
18315 UInt rT
= INSN(15,12);
18316 UInt rN
= INSN(19,16);
18317 UInt imm12
= INSN(11,0);
18318 UInt bU
= INSN(23,23);
18320 if (rT
== 15 || rN
== 15 || rN
== rT
) valid
= False
;
18322 IRTemp newRt
= newTemp(Ity_I32
);
18323 loadGuardedLE( newRt
,
18324 ILGop_8Uto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18325 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18326 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18327 getIRegA(rN
), mkU32(imm12
));
18328 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18329 DIP("ldrbt%s r%u, [r%u], #%c%u\n",
18330 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm12
);
18331 goto decode_success
;
18335 /* -------------- (A2) LDRBT reg+/-reg with shift -------------- */
18336 /* Load Register Byte Unprivileged:
18337 ldrbt<c> Rt, [Rn], +/-Rm{, shift}
18339 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,1,0,0,1,1,1)
18340 && INSN(4,4) == 0 ) {
18341 UInt rT
= INSN(15,12);
18342 UInt rN
= INSN(19,16);
18343 UInt rM
= INSN(3,0);
18344 UInt imm5
= INSN(11,7);
18345 UInt bU
= INSN(23,23);
18346 UInt type
= INSN(6,5);
18348 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15
18349 /* || (ArchVersion() < 6 && rM == rN) */)
18352 IRTemp newRt
= newTemp(Ity_I32
);
18353 loadGuardedLE( newRt
,
18354 ILGop_8Uto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18355 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18356 // dis_buf generated is slightly bogus, in fact.
18357 IRExpr
* erN
= mk_EA_reg_plusminus_shifted_reg(rN
, bU
, rM
,
18358 type
, imm5
, dis_buf
);
18359 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18360 DIP("ldrbt%s r%u, %s\n", nCC(INSN_COND
), rT
, dis_buf
);
18361 goto decode_success
;
18365 /* -------------- (A1) LDRHT reg+#imm8 -------------- */
18366 /* Load Register Halfword Unprivileged:
18367 ldrht<c> Rt, [Rn] {, #+/-imm8}
18369 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,1,1,1)
18370 && INSN(7,4) == BITS4(1,0,1,1) ) {
18371 UInt rT
= INSN(15,12);
18372 UInt rN
= INSN(19,16);
18373 UInt bU
= INSN(23,23);
18374 UInt imm4H
= INSN(11,8);
18375 UInt imm4L
= INSN(3,0);
18376 UInt imm8
= (imm4H
<< 4) | imm4L
;
18378 if (rT
== 15 || rN
== 15 || rN
== rT
)
18381 IRTemp newRt
= newTemp(Ity_I32
);
18382 loadGuardedLE( newRt
,
18383 ILGop_16Uto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18384 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18385 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18386 getIRegA(rN
), mkU32(imm8
));
18387 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18388 DIP("ldrht%s r%u, [r%u], #%c%u\n",
18389 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm8
);
18390 goto decode_success
;
18394 /* -------------- (A2) LDRHT reg+/-reg -------------- */
18395 /* Load Register Halfword Unprivileged:
18396 ldrht<c> Rt, [Rn], +/-Rm
18398 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,0,1,1)
18399 && INSN(11,4) == BITS8(0,0,0,0,1,0,1,1) ) {
18400 UInt rT
= INSN(15,12);
18401 UInt rN
= INSN(19,16);
18402 UInt rM
= INSN(3,0);
18403 UInt bU
= INSN(23,23);
18405 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15)
18408 IRTemp newRt
= newTemp(Ity_I32
);
18409 loadGuardedLE( newRt
,
18410 ILGop_16Uto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18411 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18412 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18413 getIRegA(rN
), getIRegA(rM
));
18414 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18415 DIP("ldrht%s r%u, [r%u], %cr%u\n",
18416 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', rM
);
18417 goto decode_success
;
18421 /* -------------- (A1) LDRSHT reg+#imm8 -------------- */
18422 /* Load Register Signed Halfword Unprivileged:
18423 ldrsht<c> Rt, [Rn] {, #+/-imm8}
18425 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,1,1,1)
18426 && INSN(7,4) == BITS4(1,1,1,1)) {
18427 UInt rT
= INSN(15,12);
18428 UInt rN
= INSN(19,16);
18429 UInt bU
= INSN(23,23);
18430 UInt imm4H
= INSN(11,8);
18431 UInt imm4L
= INSN(3,0);
18432 UInt imm8
= (imm4H
<< 4) | imm4L
;
18434 if (rN
== 15 || rT
== 15 || rN
== rT
)
18437 IRTemp newRt
= newTemp(Ity_I32
);
18438 loadGuardedLE( newRt
,
18439 ILGop_16Sto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18440 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18441 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18442 getIRegA(rN
), mkU32(imm8
));
18443 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18444 DIP("ldrsht%s r%u, [r%u], #%c%u\n",
18445 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm8
);
18446 goto decode_success
;
18450 /* -------------- (A2) LDRSHT reg+/-reg -------------- */
18451 /* Load Register Signed Halfword Unprivileged:
18452 ldrsht<c> Rt, [Rn], +/-Rm
18454 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,0,1,1)
18455 && INSN(11,4) == BITS8(0,0,0,0,1,1,1,1)) {
18456 UInt rT
= INSN(15,12);
18457 UInt rN
= INSN(19,16);
18458 UInt rM
= INSN(3,0);
18459 UInt bU
= INSN(23,23);
18461 if (rN
== 15 || rT
== 15 || rN
== rT
|| rM
== 15)
18464 IRTemp newRt
= newTemp(Ity_I32
);
18465 loadGuardedLE( newRt
,
18466 ILGop_16Sto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18467 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18468 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18469 getIRegA(rN
), getIRegA(rM
));
18470 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18471 DIP("ldrsht%s r%u, [r%u], %cr%u\n",
18472 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', rM
);
18473 goto decode_success
;
18477 /* -------------- (A1) LDRSBT reg+#imm8 -------------- */
18478 /* Load Register Signed Byte Unprivileged:
18479 ldrsbt<c> Rt, [Rn] {, #+/-imm8}
18481 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,1,1,1)
18482 && INSN(7,4) == BITS4(1,1,0,1)) {
18483 UInt rT
= INSN(15,12);
18484 UInt rN
= INSN(19,16);
18485 UInt bU
= INSN(23,23);
18486 UInt imm4H
= INSN(11,8);
18487 UInt imm4L
= INSN(3,0);
18488 UInt imm8
= (imm4H
<< 4) | imm4L
;
18490 if (rT
== 15 || rN
== 15 || rN
== rT
)
18493 IRTemp newRt
= newTemp(Ity_I32
);
18494 loadGuardedLE( newRt
,
18495 ILGop_8Sto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18496 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18497 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18498 getIRegA(rN
), mkU32(imm8
));
18499 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18500 DIP("ldrsbt%s r%u, [r%u], #%c%u\n",
18501 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm8
);
18502 goto decode_success
;
18506 /* -------------- (A2) LDRSBT reg+/-reg -------------- */
18507 /* Load Register Signed Byte Unprivileged:
18508 ldrsbt<c> Rt, [Rn], +/-Rm
18510 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,0,1,1)
18511 && INSN(11,4) == BITS8(0,0,0,0,1,1,0,1)) {
18512 UInt rT
= INSN(15,12);
18513 UInt rN
= INSN(19,16);
18514 UInt bU
= INSN(23,23);
18515 UInt rM
= INSN(3,0);
18517 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15)
18520 IRTemp newRt
= newTemp(Ity_I32
);
18521 loadGuardedLE( newRt
,
18522 ILGop_8Sto32
, getIRegA(rN
), getIRegA(rT
), condT
);
18523 putIRegA(rT
, mkexpr(newRt
), IRTemp_INVALID
, Ijk_Boring
);
18524 IRExpr
* erN
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18525 getIRegA(rN
), getIRegA(rM
));
18526 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18527 DIP("ldrsbt%s r%u, [r%u], %cr%u\n",
18528 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', rM
);
18529 goto decode_success
;
18533 /* -------------- (A1) STRBT reg+#imm12 -------------- */
18534 /* Store Register Byte Unprivileged:
18535 strbt<c> Rt, [Rn], #+/-imm12
18537 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,0,0,0,1,1,0) ) {
18538 UInt rT
= INSN(15,12);
18539 UInt rN
= INSN(19,16);
18540 UInt imm12
= INSN(11,0);
18541 UInt bU
= INSN(23,23);
18543 if (rT
== 15 || rN
== 15 || rN
== rT
) valid
= False
;
18545 IRExpr
* address
= getIRegA(rN
);
18546 IRExpr
* data
= unop(Iop_32to8
, getIRegA(rT
));
18547 storeGuardedLE( address
, data
, condT
);
18548 IRExpr
* newRn
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18549 getIRegA(rN
), mkU32(imm12
));
18550 putIRegA(rN
, newRn
, condT
, Ijk_Boring
);
18551 DIP("strbt%s r%u, [r%u], #%c%u\n",
18552 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm12
);
18553 goto decode_success
;
18557 /* -------------- (A2) STRBT reg+/-reg -------------- */
18558 /* Store Register Byte Unprivileged:
18559 strbt<c> Rt, [Rn], +/-Rm{, shift}
18561 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,1,0,0,1,1,0)
18562 && INSN(4,4) == 0) {
18563 UInt rT
= INSN(15,12);
18564 UInt rN
= INSN(19,16);
18565 UInt imm5
= INSN(11,7);
18566 UInt type
= INSN(6,5);
18567 UInt rM
= INSN(3,0);
18568 UInt bU
= INSN(23,23);
18570 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15) valid
= False
;
18572 IRExpr
* address
= getIRegA(rN
);
18573 IRExpr
* data
= unop(Iop_32to8
, getIRegA(rT
));
18574 storeGuardedLE( address
, data
, condT
);
18575 // dis_buf generated is slightly bogus, in fact.
18576 IRExpr
* erN
= mk_EA_reg_plusminus_shifted_reg(rN
, bU
, rM
,
18577 type
, imm5
, dis_buf
);
18578 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18579 DIP("strbt%s r%u, %s\n", nCC(INSN_COND
), rT
, dis_buf
);
18580 goto decode_success
;
18584 /* -------------- (A1) STRHT reg+#imm8 -------------- */
18585 /* Store Register Halfword Unprivileged:
18586 strht<c> Rt, [Rn], #+/-imm8
18588 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,1,1,0)
18589 && INSN(7,4) == BITS4(1,0,1,1) ) {
18590 UInt rT
= INSN(15,12);
18591 UInt rN
= INSN(19,16);
18592 UInt imm4H
= INSN(11,8);
18593 UInt imm4L
= INSN(3,0);
18594 UInt imm8
= (imm4H
<< 4) | imm4L
;
18595 UInt bU
= INSN(23,23);
18597 if (rT
== 15 || rN
== 15 || rN
== rT
) valid
= False
;
18599 IRExpr
* address
= getIRegA(rN
);
18600 IRExpr
* data
= unop(Iop_32to16
, getIRegA(rT
));
18601 storeGuardedLE( address
, data
, condT
);
18602 IRExpr
* newRn
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18603 getIRegA(rN
), mkU32(imm8
));
18604 putIRegA(rN
, newRn
, condT
, Ijk_Boring
);
18605 DIP("strht%s r%u, [r%u], #%c%u\n",
18606 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm8
);
18607 goto decode_success
;
18611 /* -------------- (A2) STRHT reg+reg -------------- */
18612 /* Store Register Halfword Unprivileged:
18613 strht<c> Rt, [Rn], +/-Rm
18615 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,0,0,0,0,0,1,0)
18616 && INSN(11,4) == BITS8(0,0,0,0,1,0,1,1) ) {
18617 UInt rT
= INSN(15,12);
18618 UInt rN
= INSN(19,16);
18619 UInt rM
= INSN(3,0);
18620 UInt bU
= INSN(23,23);
18622 if (rT
== 15 || rN
== 15 || rN
== rT
|| rM
== 15) valid
= False
;
18624 IRExpr
* address
= getIRegA(rN
);
18625 IRExpr
* data
= unop(Iop_32to16
, getIRegA(rT
));
18626 storeGuardedLE( address
, data
, condT
);
18627 IRExpr
* newRn
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18628 getIRegA(rN
), getIRegA(rM
));
18629 putIRegA(rN
, newRn
, condT
, Ijk_Boring
);
18630 DIP("strht%s r%u, [r%u], %cr%u\n",
18631 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', rM
);
18632 goto decode_success
;
18636 /* -------------- (A1) STRT reg+imm12 -------------- */
18637 /* Store Register Unprivileged:
18638 strt<c> Rt, [Rn], #+/-imm12
18640 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,0,0,0,0,1,0) ) {
18641 UInt rT
= INSN(15,12);
18642 UInt rN
= INSN(19,16);
18643 UInt imm12
= INSN(11,0);
18644 UInt bU
= INSN(23,23);
18646 if (rN
== 15 || rN
== rT
) valid
= False
;
18648 IRExpr
* address
= getIRegA(rN
);
18649 storeGuardedLE( address
, getIRegA(rT
), condT
);
18650 IRExpr
* newRn
= binop(bU
? Iop_Add32
: Iop_Sub32
,
18651 getIRegA(rN
), mkU32(imm12
));
18652 putIRegA(rN
, newRn
, condT
, Ijk_Boring
);
18653 DIP("strt%s r%u, [r%u], %c%u\n",
18654 nCC(INSN_COND
), rT
, rN
, bU
? '+' : '-', imm12
);
18655 goto decode_success
;
18659 /* -------------- (A2) STRT reg+reg -------------- */
18660 /* Store Register Unprivileged:
18661 strt<c> Rt, [Rn], +/-Rm{, shift}
18663 if ( (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) == BITS8(0,1,1,0,0,0,1,0)
18664 && INSN(4,4) == 0 ) {
18665 UInt rT
= INSN(15,12);
18666 UInt rN
= INSN(19,16);
18667 UInt rM
= INSN(3,0);
18668 UInt type
= INSN(6,5);
18669 UInt imm5
= INSN(11,7);
18670 UInt bU
= INSN(23,23);
18672 if (rN
== 15 || rN
== rT
|| rM
== 15) valid
= False
;
18673 /* FIXME We didn't do:
18674 if ArchVersion() < 6 && rM == rN then UNPREDICTABLE */
18676 storeGuardedLE( getIRegA(rN
), getIRegA(rT
), condT
);
18677 // dis_buf generated is slightly bogus, in fact.
18678 IRExpr
* erN
= mk_EA_reg_plusminus_shifted_reg(rN
, bU
, rM
,
18679 type
, imm5
, dis_buf
);
18680 putIRegA(rN
, erN
, condT
, Ijk_Boring
);
18681 DIP("strt%s r%u, %s\n", nCC(INSN_COND
), rT
, dis_buf
);
18682 goto decode_success
;
18686 /* ----------------------------------------------------------- */
18687 /* -- ARMv7 instructions -- */
18688 /* ----------------------------------------------------------- */
18690 /* -------------- read CP15 TPIDRURO register ------------- */
18691 /* mrc p15, 0, r0, c13, c0, 3 up to
18692 mrc p15, 0, r14, c13, c0, 3
18694 /* I don't know whether this is really v7-only. But anyway, we
18695 have to support it since arm-linux uses TPIDRURO as a thread
18697 if (0x0E1D0F70 == (insn
& 0x0FFF0FFF)) {
18698 UInt rD
= INSN(15,12);
18700 /* skip r15, that's too stupid to handle */
18701 putIRegA(rD
, IRExpr_Get(OFFB_TPIDRURO
, Ity_I32
),
18702 condT
, Ijk_Boring
);
18703 DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND
), rD
);
18704 goto decode_success
;
18709 /* ------------ read/write CP15 TPIDRURW register ----------- */
18710 /* mcr p15, 0, r0, c13, c0, 2 (r->cr xfer) up to
18711 mcr p15, 0, r14, c13, c0, 2
18713 mrc p15, 0, r0, c13, c0, 2 (rc->r xfer) up to
18714 mrc p15, 0, r14, c13, c0, 2
18716 if (0x0E0D0F50 == (insn
& 0x0FFF0FFF)) { // MCR
18717 UInt rS
= INSN(15,12);
18719 /* skip r15, that's too stupid to handle */
18720 putMiscReg32(OFFB_TPIDRURW
, getIRegA(rS
), condT
);
18721 DIP("mcr%s p15,0, r%u, c13, c0, 2\n", nCC(INSN_COND
), rS
);
18722 goto decode_success
;
18726 if (0x0E1D0F50 == (insn
& 0x0FFF0FFF)) { // MRC
18727 UInt rD
= INSN(15,12);
18729 /* skip r15, that's too stupid to handle */
18730 putIRegA(rD
, IRExpr_Get(OFFB_TPIDRURW
, Ity_I32
),
18731 condT
, Ijk_Boring
);
18732 DIP("mrc%s p15,0, r%u, c13, c0, 2\n", nCC(INSN_COND
), rD
);
18733 goto decode_success
;
18738 /* -------------- read CP15 PMUSRENR register ------------- */
18739 /* mrc p15, 0, r0, c9, c14, 0 up to
18740 mrc p15, 0, r14, c9, c14, 0
18742 /* A program reading this register is really asking "which
18743 performance monitoring registes are available in user space?
18744 The simple answer here is to return zero, meaning "none". See
18746 if (0x0E190F1E == (insn
& 0x0FFF0FFF)) {
18747 UInt rD
= INSN(15,12);
18749 /* skip r15, that's too stupid to handle */
18750 putIRegA(rD
, mkU32(0), condT
, Ijk_Boring
);
18751 DIP("mrc%s p15,0, r%u, c9, c14, 0\n", nCC(INSN_COND
), rD
);
18752 goto decode_success
;
18757 /* Handle various kinds of barriers. This is rather indiscriminate
18758 in the sense that they are all turned into an IR Fence, which
18759 means we don't know which they are, so the back end has to
18760 re-emit them all when it comes acrosss an IR Fence.
18762 /* v6 */ /* mcr 15, 0, rT, c7, c10, 5 */
18763 if (0xEE070FBA == (insn
& 0xFFFF0FFF)) {
18764 UInt rT
= INSN(15,12);
18766 /* mcr 15, 0, rT, c7, c10, 5 (v6) equiv to DMB (v7). Data
18767 Memory Barrier -- ensures ordering of memory accesses. */
18768 stmt( IRStmt_MBE(Imbe_Fence
) );
18769 DIP("mcr 15, 0, r%u, c7, c10, 5 (data memory barrier)\n", rT
);
18770 goto decode_success
;
18774 /* other flavours of barrier */
18776 case 0xEE070F9A: /* v6 */
18777 /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7). Data
18778 Synch Barrier -- ensures completion of memory accesses. */
18779 stmt( IRStmt_MBE(Imbe_Fence
) );
18780 DIP("mcr 15, 0, r0, c7, c10, 4 (data synch barrier)\n");
18781 goto decode_success
;
18782 case 0xEE070F95: /* v6 */
18783 /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7).
18784 Instruction Synchronisation Barrier (or Flush Prefetch
18785 Buffer) -- a pipe flush, I think. I suspect we could
18786 ignore those, but to be on the safe side emit a fence
18788 stmt( IRStmt_MBE(Imbe_Fence
) );
18789 DIP("mcr 15, 0, r0, c7, c5, 4 (insn synch barrier)\n");
18790 goto decode_success
;
18795 /* ----------------------------------------------------------- */
18797 /* ----------------------------------------------------------- */
18799 switch (insn
& 0x0FFFFFFF) {
18800 /* ------------------- NOP ------------------ */
18802 DIP("nop%s\n", nCC(INSN_COND
));
18803 goto decode_success
;
18804 /* ------------------- YIELD ------------------ */
18806 /* Continue after conditionally yielding. */
18807 DIP("yield%s\n", nCC(INSN_COND
));
18808 stmt( IRStmt_Exit( unop(Iop_32to1
,
18809 condT
== IRTemp_INVALID
18810 ? mkU32(1) : mkexpr(condT
)),
18812 IRConst_U32(guest_R15_curr_instr_notENC
+ 4),
18814 goto decode_success
;
18819 /* ----------------------------------------------------------- */
18820 /* -- VFP (CP 10, CP 11) instructions (in ARM mode) -- */
18821 /* ----------------------------------------------------------- */
18823 if (INSN_COND
!= ARMCondNV
) {
18824 Bool ok_vfp
= decode_CP10_CP11_instruction (
18825 &dres
, INSN(27,0), condT
, INSN_COND
,
18829 goto decode_success
;
18832 /* ----------------------------------------------------------- */
18833 /* -- NEON instructions (in ARM mode) -- */
18834 /* ----------------------------------------------------------- */
18836 /* These are all in NV space, and so are taken care of (far) above,
18837 by a call from this function to
18838 decode_NV_instruction_ARMv7_and_below(). */
18840 /* ----------------------------------------------------------- */
18841 /* -- v6 media instructions (in ARM mode) -- */
18842 /* ----------------------------------------------------------- */
18844 { Bool ok_v6m
= decode_V6MEDIA_instruction(
18845 &dres
, INSN(27,0), condT
, INSN_COND
,
18849 goto decode_success
;
18852 /* ----------------------------------------------------------- */
18853 /* -- v8 instructions (in ARM mode) -- */
18854 /* ----------------------------------------------------------- */
18858 /* If we get here, it means that all attempts to decode the
18859 instruction as ARMv7 or earlier have failed. So, if we're doing
18860 ARMv8 or later, here is the point to try for it. */
18862 if (VEX_ARM_ARCHLEVEL(archinfo
->hwcaps
) >= 8) {
18864 = decode_V8_instruction( &dres
, insn
, condT
, False
/*!isT*/,
18865 IRTemp_INVALID
, IRTemp_INVALID
);
18867 goto decode_success
;
18870 /* ----------------------------------------------------------- */
18871 /* -- Undecodable -- */
18872 /* ----------------------------------------------------------- */
18874 goto decode_failure
;
18878 /* All decode failures end up here. */
18880 vex_printf("disInstr(arm): unhandled instruction: "
18882 vex_printf(" cond=%d(0x%x) 27:20=%d(0x%02x) "
18885 (Int
)INSN_COND
, (UInt
)INSN_COND
,
18886 (Int
)INSN(27,20), (UInt
)INSN(27,20),
18888 (Int
)INSN(3,0), (UInt
)INSN(3,0) );
18891 /* Tell the dispatcher that this insn cannot be decoded, and so has
18892 not been executed, and (is currently) the next to be executed.
18893 R15 should be up-to-date since it made so at the start of each
18894 insn, but nevertheless be paranoid and update it again right
18896 vassert(0 == (guest_R15_curr_instr_notENC
& 3));
18897 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC
) );
18899 dres
.whatNext
= Dis_StopHere
;
18900 dres
.jk_StopHere
= Ijk_NoDecode
;
18901 dres
.continueAt
= 0;
18905 /* All decode successes end up here. */
18908 vassert(dres
.len
== 4 || dres
.len
== 20);
18910 /* Now then. Do we have an implicit jump to r15 to deal with? */
18912 /* If we get jump to deal with, we assume that there's been no
18913 other competing branch stuff previously generated for this
18914 insn. That's reasonable, in the sense that the ARM insn set
18915 appears to declare as "Unpredictable" any instruction which
18916 generates more than one possible new value for r15. Hence
18917 just assert. The decoders themselves should check against
18918 all such instructions which are thusly Unpredictable, and
18919 decline to decode them. Hence we should never get here if we
18920 have competing new values for r15, and hence it is safe to
18922 vassert(dres
.whatNext
== Dis_Continue
);
18923 vassert(irsb
->next
== NULL
);
18924 vassert(irsb
->jumpkind
== Ijk_Boring
);
18925 /* If r15 is unconditionally written, terminate the block by
18926 jumping to it. If it's conditionally written, still
18927 terminate the block (a shame, but we can't do side exits to
18928 arbitrary destinations), but first jump to the next
18929 instruction if the condition doesn't hold. */
18930 /* We can't use getIReg(15) to get the destination, since that
18931 will produce r15+8, which isn't what we want. Must use
18932 llGetIReg(15) instead. */
18933 if (r15guard
== IRTemp_INVALID
) {
18934 /* unconditional */
18940 mkexpr(r15guard
), mkU32(1))),
18942 IRConst_U32(guest_R15_curr_instr_notENC
+ 4),
18946 /* This seems crazy, but we're required to finish the insn with
18947 a write to the guest PC. As usual we rely on ir_opt to tidy
18949 llPutIReg(15, llGetIReg(15));
18950 dres
.whatNext
= Dis_StopHere
;
18951 dres
.jk_StopHere
= r15kind
;
18953 /* Set up the end-state in the normal way. */
18954 switch (dres
.whatNext
) {
18956 llPutIReg(15, mkU32(dres
.len
+ guest_R15_curr_instr_notENC
));
18960 llPutIReg(15, mkU32(dres
.continueAt
));
18976 /*------------------------------------------------------------*/
18977 /*--- Disassemble a single Thumb2 instruction ---*/
18978 /*------------------------------------------------------------*/
18980 static const UChar it_length_table
[256]; /* fwds */
18982 /* NB: in Thumb mode we do fetches of regs with getIRegT, which
18983 automagically adds 4 to fetches of r15. However, writes to regs
18984 are done with putIRegT, which disallows writes to r15. Hence any
18985 r15 writes and associated jumps have to be done "by hand". */
18987 /* Disassemble a single Thumb instruction into IR. The instruction is
18988 located in host memory at guest_instr, and has (decoded) guest IP
18989 of guest_R15_curr_instr_notENC, which will have been set before the
18993 DisResult
disInstr_THUMB_WRK (
18994 Bool (*resteerOkFn
) ( /*opaque*/void*, Addr
),
18996 void* callback_opaque
,
18997 const UChar
* guest_instr
,
18998 const VexArchInfo
* archinfo
,
18999 const VexAbiInfo
* abiinfo
,
19003 /* A macro to fish bits out of insn0. There's also INSN1, to fish
19004 bits out of insn1, but that's defined only after the end of the
19005 16-bit insn decoder, so as to stop it mistakenly being used
19007 # define INSN0(_bMax,_bMin) SLICE_UInt(((UInt)insn0), (_bMax), (_bMin))
19010 UShort insn0
; /* first 16 bits of the insn */
19011 UShort insn1
; /* second 16 bits of the insn */
19012 HChar dis_buf
[128]; // big enough to hold LDMIA etc text
19014 /* Summary result of the ITxxx backwards analysis: False == safe
19016 Bool guaranteedUnconditional
= False
;
19018 /* Set result defaults. */
19019 dres
.whatNext
= Dis_Continue
;
19021 dres
.continueAt
= 0;
19022 dres
.jk_StopHere
= Ijk_INVALID
;
19023 dres
.hint
= Dis_HintNone
;
19025 /* Set default actions for post-insn handling of writes to r15, if
19027 r15written
= False
;
19028 r15guard
= IRTemp_INVALID
; /* unconditional */
19029 r15kind
= Ijk_Boring
;
19031 /* Insns could be 2 or 4 bytes long. Just get the first 16 bits at
19032 this point. If we need the second 16, get them later. We can't
19033 get them both out immediately because it risks a fault (very
19034 unlikely, but ..) if the second 16 bits aren't actually
19036 insn0
= getUShortLittleEndianly( guest_instr
);
19037 insn1
= 0; /* We'll get it later, once we know we need it. */
19039 /* Similarly, will set this later. */
19040 IRTemp old_itstate
= IRTemp_INVALID
;
19042 if (0) vex_printf("insn: 0x%x\n", insn0
);
19044 DIP("\t(thumb) 0x%x: ", (UInt
)guest_R15_curr_instr_notENC
);
19046 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
19048 /* ----------------------------------------------------------- */
19049 /* Spot "Special" instructions (see comment at top of file). */
19051 const UChar
* code
= guest_instr
;
19052 /* Spot the 16-byte preamble:
19054 ea4f 0cfc mov.w ip, ip, ror #3
19055 ea4f 3c7c mov.w ip, ip, ror #13
19056 ea4f 7c7c mov.w ip, ip, ror #29
19057 ea4f 4cfc mov.w ip, ip, ror #19
19059 UInt word1
= 0x0CFCEA4F;
19060 UInt word2
= 0x3C7CEA4F;
19061 UInt word3
= 0x7C7CEA4F;
19062 UInt word4
= 0x4CFCEA4F;
19063 if (getUIntLittleEndianly(code
+ 0) == word1
&&
19064 getUIntLittleEndianly(code
+ 4) == word2
&&
19065 getUIntLittleEndianly(code
+ 8) == word3
&&
19066 getUIntLittleEndianly(code
+12) == word4
) {
19067 /* Got a "Special" instruction preamble. Which one is it? */
19069 if (getUIntLittleEndianly(code
+16) == 0x0A0AEA4A
19070 /* orr.w r10,r10,r10 */) {
19071 /* R3 = client_request ( R4 ) */
19072 DIP("r3 = client_request ( %%r4 )\n");
19073 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC
+ 20) | 1 ));
19074 dres
.jk_StopHere
= Ijk_ClientReq
;
19075 dres
.whatNext
= Dis_StopHere
;
19076 goto decode_success
;
19080 if (getUIntLittleEndianly(code
+16) == 0x0B0BEA4B
19081 /* orr r11,r11,r11 */) {
19082 /* R3 = guest_NRADDR */
19083 DIP("r3 = guest_NRADDR\n");
19085 llPutIReg(3, IRExpr_Get( OFFB_NRADDR
, Ity_I32
));
19086 goto decode_success
;
19090 if (getUIntLittleEndianly(code
+16) == 0x0C0CEA4C
19091 /* orr r12,r12,r12 */) {
19092 /* branch-and-link-to-noredir R4 */
19093 DIP("branch-and-link-to-noredir r4\n");
19094 llPutIReg(14, mkU32( (guest_R15_curr_instr_notENC
+ 20) | 1 ));
19095 llPutIReg(15, getIRegT(4));
19096 dres
.jk_StopHere
= Ijk_NoRedir
;
19097 dres
.whatNext
= Dis_StopHere
;
19098 goto decode_success
;
19102 if (getUIntLittleEndianly(code
+16) == 0x0909EA49
19103 /* orr r9,r9,r9 */) {
19105 DIP("IR injection\n");
19106 vex_inject_ir(irsb
, Iend_LE
);
19107 // Invalidate the current insn. The reason is that the IRop we're
19108 // injecting here can change. In which case the translation has to
19109 // be redone. For ease of handling, we simply invalidate all the
19111 stmt(IRStmt_Put(OFFB_CMSTART
, mkU32(guest_R15_curr_instr_notENC
)));
19112 stmt(IRStmt_Put(OFFB_CMLEN
, mkU32(20)));
19113 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC
+ 20) | 1 ));
19114 dres
.whatNext
= Dis_StopHere
;
19115 dres
.jk_StopHere
= Ijk_InvalICache
;
19116 goto decode_success
;
19118 /* We don't know what it is. Set insn0 so decode_failure
19119 can print the insn following the Special-insn preamble. */
19120 insn0
= getUShortLittleEndianly(code
+16);
19121 goto decode_failure
;
19127 /* ----------------------------------------------------------- */
19129 /* Main Thumb instruction decoder starts here. It's a series of
19130 switches which examine ever longer bit sequences at the MSB of
19131 the instruction word, first for 16-bit insns, then for 32-bit
19134 /* --- BEGIN ITxxx optimisation analysis --- */
19135 /* This is a crucial optimisation for the ITState boilerplate that
19136 follows. Examine the 9 halfwords preceding this instruction,
19137 and if we are absolutely sure that none of them constitute an
19138 'it' instruction, then we can be sure that this instruction is
19139 not under the control of any 'it' instruction, and so
19140 guest_ITSTATE must be zero. So write zero into ITSTATE right
19141 now, so that iropt can fold out almost all of the resulting
19144 If we aren't sure, we can always safely skip this step. So be a
19145 bit conservative about it: only poke around in the same page as
19146 this instruction, lest we get a fault from the previous page
19147 that would not otherwise have happened. The saving grace is
19148 that such skipping is pretty rare -- it only happens,
19149 statistically, 18/4096ths of the time, so is judged unlikely to
19150 be a performance problems.
19152 FIXME: do better. Take into account the number of insns covered
19153 by any IT insns we find, to rule out cases where an IT clearly
19154 cannot cover this instruction. This would improve behaviour for
19155 branch targets immediately following an IT-guarded group that is
19156 not of full length. Eg, (and completely ignoring issues of 16-
19157 vs 32-bit insn length):
19165 The 'it' only conditionalises insn1 and insn2. However, the
19166 current analysis is conservative and considers insn3 and insn4
19167 also possibly guarded. Hence if 'label:' is the start of a hot
19168 loop we will get a big performance hit.
19171 /* Summary result of this analysis: False == safe but
19173 vassert(guaranteedUnconditional
== False
);
19175 UInt pc
= guest_R15_curr_instr_notENC
;
19176 vassert(0 == (pc
& 1));
19178 UInt pageoff
= pc
& 0xFFF;
19179 if (pageoff
>= 18) {
19180 /* It's safe to poke about in the 9 halfwords preceding this
19181 insn. So, have a look at them. */
19182 guaranteedUnconditional
= True
; /* assume no 'it' insn found,
19184 UShort
* hwp
= (UShort
*)(HWord
)pc
;
19186 for (i
= -1; i
>= -9; i
--) {
19187 /* We're in the same page. (True, but commented out due
19190 vassert( ( ((UInt)(&hwp[i])) & 0xFFFFF000 )
19191 == ( pc & 0xFFFFF000 ) );
19193 /* All valid IT instructions must have the form 0xBFxy,
19194 where x can be anything, but y must be nonzero. Find
19195 the number of insns covered by it (1 .. 4) and check to
19196 see if it can possibly reach up to the instruction in
19197 question. Some (x,y) combinations mean UNPREDICTABLE,
19198 and the table is constructed to be conservative by
19199 returning 4 for those cases, so the analysis is safe
19200 even if the code uses unpredictable IT instructions (in
19201 which case its authors are nuts, but hey.) */
19202 UShort hwp_i
= hwp
[i
];
19203 if (UNLIKELY((hwp_i
& 0xFF00) == 0xBF00 && (hwp_i
& 0xF) != 0)) {
19204 /* might be an 'it' insn. */
19205 /* # guarded insns */
19206 Int n_guarded
= (Int
)it_length_table
[hwp_i
& 0xFF];
19207 vassert(n_guarded
>= 1 && n_guarded
<= 4);
19208 if (n_guarded
* 2 /* # guarded HWs, worst case */
19209 > (-(i
+1))) /* -(i+1): # remaining HWs after the IT */
19210 /* -(i+0) also seems to work, even though I think
19211 it's wrong. I don't understand that. */
19212 guaranteedUnconditional
= False
;
19218 /* --- END ITxxx optimisation analysis --- */
19220 /* Generate the guarding condition for this insn, by examining
19221 ITSTATE. Assign it to condT. Also, generate new
19222 values for ITSTATE ready for stuffing back into the
19223 guest state, but don't actually do the Put yet, since it will
19224 need to stuffed back in only after the instruction gets to a
19225 point where it is sure to complete. Mostly we let the code at
19226 decode_success handle this, but in cases where the insn contains
19227 a side exit, we have to update them before the exit. */
19229 /* If the ITxxx optimisation analysis above could not prove that
19230 this instruction is guaranteed unconditional, we insert a
19231 lengthy IR preamble to compute the guarding condition at
19232 runtime. If it can prove it (which obviously we hope is the
19233 normal case) then we insert a minimal preamble, which is
19234 equivalent to setting guest_ITSTATE to zero and then folding
19235 that through the full preamble (which completely disappears). */
19237 IRTemp condT
= IRTemp_INVALID
;
19238 IRTemp cond_AND_notInIT_T
= IRTemp_INVALID
;
19240 IRTemp new_itstate
= IRTemp_INVALID
;
19241 vassert(old_itstate
== IRTemp_INVALID
);
19243 if (guaranteedUnconditional
) {
19244 /* BEGIN "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
19246 // ITSTATE = 0 :: I32
19247 IRTemp z32
= newTemp(Ity_I32
);
19248 assign(z32
, mkU32(0));
19251 // old_itstate = 0 :: I32
19253 // old_itstate = get_ITSTATE();
19254 old_itstate
= z32
; /* 0 :: I32 */
19256 // new_itstate = old_itstate >> 8
19260 // new_itstate = newTemp(Ity_I32);
19261 // assign(new_itstate,
19262 // binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
19265 // ITSTATE = 0 :: I32(again)
19267 // put_ITSTATE(new_itstate);
19269 // condT1 = calc_cond_dyn( xor(and(old_istate,0xF0), 0xE0) )
19270 // = calc_cond_dyn( xor(0,0xE0) )
19271 // = calc_cond_dyn ( 0xE0 )
19273 // Not that this matters, since the computed value is not used:
19274 // see condT folding below
19276 // IRTemp condT1 = newTemp(Ity_I32);
19278 // mk_armg_calculate_condition_dyn(
19279 // binop(Iop_Xor32,
19280 // binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
19285 // condT = 32to8(and32(old_itstate,0xF0)) == 0 ? 1 : condT1
19286 // = 32to8(and32(0,0xF0)) == 0 ? 1 : condT1
19287 // = 32to8(0) == 0 ? 1 : condT1
19288 // = 0 == 0 ? 1 : condT1
19291 // condT = newTemp(Ity_I32);
19292 // assign(condT, IRExpr_ITE(
19293 // unop(Iop_32to8, binop(Iop_And32,
19294 // mkexpr(old_itstate),
19299 condT
= newTemp(Ity_I32
);
19300 assign(condT
, mkU32(1));
19302 // notInITt = xor32(and32(old_itstate, 1), 1)
19303 // = xor32(and32(0, 1), 1)
19307 // IRTemp notInITt = newTemp(Ity_I32);
19308 // assign(notInITt,
19309 // binop(Iop_Xor32,
19310 // binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
19313 // cond_AND_notInIT_T = and32(notInITt, condT)
19317 // cond_AND_notInIT_T = newTemp(Ity_I32);
19318 // assign(cond_AND_notInIT_T,
19319 // binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
19320 cond_AND_notInIT_T
= condT
; /* 1 :: I32 */
19322 /* END "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
19324 /* BEGIN { STANDARD PREAMBLE; } */
19326 old_itstate
= get_ITSTATE();
19328 new_itstate
= newTemp(Ity_I32
);
19329 assign(new_itstate
,
19330 binop(Iop_Shr32
, mkexpr(old_itstate
), mkU8(8)));
19332 put_ITSTATE(new_itstate
);
19334 /* Same strategy as for ARM insns: generate a condition
19335 temporary at this point (or IRTemp_INVALID, meaning
19336 unconditional). We leave it to lower-level instruction
19337 decoders to decide whether they can generate straight-line
19338 code, or whether they must generate a side exit before the
19339 instruction. condT :: Ity_I32 and is always either zero or
19341 IRTemp condT1
= newTemp(Ity_I32
);
19343 mk_armg_calculate_condition_dyn(
19345 binop(Iop_And32
, mkexpr(old_itstate
), mkU32(0xF0)),
19350 /* This is a bit complex, but needed to make Memcheck understand
19351 that, if the condition in old_itstate[7:4] denotes AL (that
19352 is, if this instruction is to be executed unconditionally),
19353 then condT does not depend on the results of calling the
19356 We test explicitly for old_itstate[7:4] == AL ^ 0xE, and in
19357 that case set condT directly to 1. Else we use the results
19358 of the helper. Since old_itstate is always defined and
19359 because Memcheck does lazy V-bit propagation through ITE,
19360 this will cause condT to always be a defined 1 if the
19361 condition is 'AL'. From an execution semantics point of view
19362 this is irrelevant since we're merely duplicating part of the
19363 behaviour of the helper. But it makes it clear to Memcheck,
19364 in this case, that condT does not in fact depend on the
19365 contents of the condition code thunk. Without it, we get
19366 quite a lot of false errors.
19368 So, just to clarify: from a straight semantics point of view,
19369 we can simply do "assign(condT, mkexpr(condT1))", and the
19370 simulator still runs fine. It's just that we get loads of
19371 false errors from Memcheck. */
19372 condT
= newTemp(Ity_I32
);
19373 assign(condT
, IRExpr_ITE(
19374 binop(Iop_CmpNE32
, binop(Iop_And32
,
19375 mkexpr(old_itstate
),
19382 /* Something we don't have in ARM: generate a 0 or 1 value
19383 indicating whether or not we are in an IT block (NB: 0 = in
19384 IT block, 1 = not in IT block). This is used to gate
19385 condition code updates in 16-bit Thumb instructions. */
19386 IRTemp notInITt
= newTemp(Ity_I32
);
19389 binop(Iop_And32
, mkexpr(old_itstate
), mkU32(1)),
19392 /* Compute 'condT && notInITt' -- that is, the instruction is
19393 going to execute, and we're not in an IT block. This is the
19394 gating condition for updating condition codes in 16-bit Thumb
19395 instructions, except for CMP, CMN and TST. */
19396 cond_AND_notInIT_T
= newTemp(Ity_I32
);
19397 assign(cond_AND_notInIT_T
,
19398 binop(Iop_And32
, mkexpr(notInITt
), mkexpr(condT
)));
19399 /* END { STANDARD PREAMBLE; } */
19404 * ITSTATE has been updated
19405 * condT holds the guarding condition for this instruction (0 or 1),
19406 * notInITt is 1 if we're in "normal" code, 0 if in an IT block
19407 * cond_AND_notInIT_T is the AND of the above two.
19409 If the instruction proper can't trap, then there's nothing else
19410 to do w.r.t. ITSTATE -- just go and and generate IR for the
19411 insn, taking into account the guarding condition.
19413 If, however, the instruction might trap, then we must back up
19414 ITSTATE to the old value, and re-update it after the potentially
19415 trapping IR section. A trap can happen either via a memory
19416 reference or because we need to throw SIGILL.
19418 If an instruction has a side exit, we need to be sure that any
19419 ITSTATE backup is re-updated before the side exit.
19422 /* ----------------------------------------------------------- */
19424 /* -- Thumb 16-bit integer instructions -- */
19426 /* -- IMPORTANT: references to insn1 or INSN1 are -- */
19427 /* -- not allowed in this section -- */
19429 /* ----------------------------------------------------------- */
19431 /* 16-bit instructions inside an IT block, apart from CMP, CMN and
19432 TST, do not set the condition codes. Hence we must dynamically
19433 test for this case for every condition code update. */
19435 IROp anOp
= Iop_INVALID
;
19436 const HChar
* anOpNm
= NULL
;
19438 /* ================ 16-bit 15:6 cases ================ */
19440 switch (INSN0(15,6)) {
19443 case 0x10b: { // CMN
19444 /* ---------------- CMP Rn, Rm ---------------- */
19445 Bool isCMN
= INSN0(15,6) == 0x10b;
19446 UInt rN
= INSN0(2,0);
19447 UInt rM
= INSN0(5,3);
19448 IRTemp argL
= newTemp(Ity_I32
);
19449 IRTemp argR
= newTemp(Ity_I32
);
19450 assign( argL
, getIRegT(rN
) );
19451 assign( argR
, getIRegT(rM
) );
19452 /* Update flags regardless of whether in an IT block or not. */
19453 setFlags_D1_D2( isCMN
? ARMG_CC_OP_ADD
: ARMG_CC_OP_SUB
,
19454 argL
, argR
, condT
);
19455 DIP("%s r%u, r%u\n", isCMN
? "cmn" : "cmp", rN
, rM
);
19456 goto decode_success
;
19460 /* ---------------- TST Rn, Rm ---------------- */
19461 UInt rN
= INSN0(2,0);
19462 UInt rM
= INSN0(5,3);
19463 IRTemp oldC
= newTemp(Ity_I32
);
19464 IRTemp oldV
= newTemp(Ity_I32
);
19465 IRTemp res
= newTemp(Ity_I32
);
19466 assign( oldC
, mk_armg_calculate_flag_c() );
19467 assign( oldV
, mk_armg_calculate_flag_v() );
19468 assign( res
, binop(Iop_And32
, getIRegT(rN
), getIRegT(rM
)) );
19469 /* Update flags regardless of whether in an IT block or not. */
19470 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
, condT
);
19471 DIP("tst r%u, r%u\n", rN
, rM
);
19472 goto decode_success
;
19476 /* ---------------- NEGS Rd, Rm ---------------- */
19478 UInt rM
= INSN0(5,3);
19479 UInt rD
= INSN0(2,0);
19480 IRTemp arg
= newTemp(Ity_I32
);
19481 IRTemp zero
= newTemp(Ity_I32
);
19482 assign(arg
, getIRegT(rM
));
19483 assign(zero
, mkU32(0));
19484 // rD can never be r15
19485 putIRegT(rD
, binop(Iop_Sub32
, mkexpr(zero
), mkexpr(arg
)), condT
);
19486 setFlags_D1_D2( ARMG_CC_OP_SUB
, zero
, arg
, cond_AND_notInIT_T
);
19487 DIP("negs r%u, r%u\n", rD
, rM
);
19488 goto decode_success
;
19492 /* ---------------- MVNS Rd, Rm ---------------- */
19494 UInt rM
= INSN0(5,3);
19495 UInt rD
= INSN0(2,0);
19496 IRTemp oldV
= newTemp(Ity_I32
);
19497 IRTemp oldC
= newTemp(Ity_I32
);
19498 IRTemp res
= newTemp(Ity_I32
);
19499 assign( oldV
, mk_armg_calculate_flag_v() );
19500 assign( oldC
, mk_armg_calculate_flag_c() );
19501 assign(res
, unop(Iop_Not32
, getIRegT(rM
)));
19502 // rD can never be r15
19503 putIRegT(rD
, mkexpr(res
), condT
);
19504 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
19505 cond_AND_notInIT_T
);
19506 DIP("mvns r%u, r%u\n", rD
, rM
);
19507 goto decode_success
;
19511 /* ---------------- ORRS Rd, Rm ---------------- */
19512 anOp
= Iop_Or32
; anOpNm
= "orr"; goto and_orr_eor_mul
;
19514 /* ---------------- ANDS Rd, Rm ---------------- */
19515 anOp
= Iop_And32
; anOpNm
= "and"; goto and_orr_eor_mul
;
19517 /* ---------------- EORS Rd, Rm ---------------- */
19518 anOp
= Iop_Xor32
; anOpNm
= "eor"; goto and_orr_eor_mul
;
19520 /* ---------------- MULS Rd, Rm ---------------- */
19521 anOp
= Iop_Mul32
; anOpNm
= "mul"; goto and_orr_eor_mul
;
19523 /* Rd = Rd `op` Rm */
19524 UInt rM
= INSN0(5,3);
19525 UInt rD
= INSN0(2,0);
19526 IRTemp res
= newTemp(Ity_I32
);
19527 IRTemp oldV
= newTemp(Ity_I32
);
19528 IRTemp oldC
= newTemp(Ity_I32
);
19529 assign( oldV
, mk_armg_calculate_flag_v() );
19530 assign( oldC
, mk_armg_calculate_flag_c() );
19531 assign( res
, binop(anOp
, getIRegT(rD
), getIRegT(rM
) ));
19532 // not safe to read guest state after here
19533 // rD can never be r15
19534 putIRegT(rD
, mkexpr(res
), condT
);
19535 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
19536 cond_AND_notInIT_T
);
19537 DIP("%s r%u, r%u\n", anOpNm
, rD
, rM
);
19538 goto decode_success
;
19542 /* ---------------- BICS Rd, Rm ---------------- */
19543 /* Rd = Rd & ~Rm */
19544 UInt rM
= INSN0(5,3);
19545 UInt rD
= INSN0(2,0);
19546 IRTemp res
= newTemp(Ity_I32
);
19547 IRTemp oldV
= newTemp(Ity_I32
);
19548 IRTemp oldC
= newTemp(Ity_I32
);
19549 assign( oldV
, mk_armg_calculate_flag_v() );
19550 assign( oldC
, mk_armg_calculate_flag_c() );
19551 assign( res
, binop(Iop_And32
, getIRegT(rD
),
19552 unop(Iop_Not32
, getIRegT(rM
) )));
19553 // not safe to read guest state after here
19554 // rD can never be r15
19555 putIRegT(rD
, mkexpr(res
), condT
);
19556 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
19557 cond_AND_notInIT_T
);
19558 DIP("bics r%u, r%u\n", rD
, rM
);
19559 goto decode_success
;
19563 /* ---------------- ADCS Rd, Rm ---------------- */
19564 /* Rd = Rd + Rm + oldC */
19565 UInt rM
= INSN0(5,3);
19566 UInt rD
= INSN0(2,0);
19567 IRTemp argL
= newTemp(Ity_I32
);
19568 IRTemp argR
= newTemp(Ity_I32
);
19569 IRTemp oldC
= newTemp(Ity_I32
);
19570 IRTemp res
= newTemp(Ity_I32
);
19571 assign(argL
, getIRegT(rD
));
19572 assign(argR
, getIRegT(rM
));
19573 assign(oldC
, mk_armg_calculate_flag_c());
19574 assign(res
, binop(Iop_Add32
,
19575 binop(Iop_Add32
, mkexpr(argL
), mkexpr(argR
)),
19577 // rD can never be r15
19578 putIRegT(rD
, mkexpr(res
), condT
);
19579 setFlags_D1_D2_ND( ARMG_CC_OP_ADC
, argL
, argR
, oldC
,
19580 cond_AND_notInIT_T
);
19581 DIP("adcs r%u, r%u\n", rD
, rM
);
19582 goto decode_success
;
19586 /* ---------------- SBCS Rd, Rm ---------------- */
19587 /* Rd = Rd - Rm - (oldC ^ 1) */
19588 UInt rM
= INSN0(5,3);
19589 UInt rD
= INSN0(2,0);
19590 IRTemp argL
= newTemp(Ity_I32
);
19591 IRTemp argR
= newTemp(Ity_I32
);
19592 IRTemp oldC
= newTemp(Ity_I32
);
19593 IRTemp res
= newTemp(Ity_I32
);
19594 assign(argL
, getIRegT(rD
));
19595 assign(argR
, getIRegT(rM
));
19596 assign(oldC
, mk_armg_calculate_flag_c());
19597 assign(res
, binop(Iop_Sub32
,
19598 binop(Iop_Sub32
, mkexpr(argL
), mkexpr(argR
)),
19599 binop(Iop_Xor32
, mkexpr(oldC
), mkU32(1))));
19600 // rD can never be r15
19601 putIRegT(rD
, mkexpr(res
), condT
);
19602 setFlags_D1_D2_ND( ARMG_CC_OP_SBB
, argL
, argR
, oldC
,
19603 cond_AND_notInIT_T
);
19604 DIP("sbcs r%u, r%u\n", rD
, rM
);
19605 goto decode_success
;
19609 /* ---------------- UXTB Rd, Rm ---------------- */
19610 /* Rd = 8Uto32(Rm) */
19611 UInt rM
= INSN0(5,3);
19612 UInt rD
= INSN0(2,0);
19613 putIRegT(rD
, binop(Iop_And32
, getIRegT(rM
), mkU32(0xFF)),
19615 DIP("uxtb r%u, r%u\n", rD
, rM
);
19616 goto decode_success
;
19620 /* ---------------- SXTB Rd, Rm ---------------- */
19621 /* Rd = 8Sto32(Rm) */
19622 UInt rM
= INSN0(5,3);
19623 UInt rD
= INSN0(2,0);
19624 putIRegT(rD
, binop(Iop_Sar32
,
19625 binop(Iop_Shl32
, getIRegT(rM
), mkU8(24)),
19628 DIP("sxtb r%u, r%u\n", rD
, rM
);
19629 goto decode_success
;
19633 /* ---------------- UXTH Rd, Rm ---------------- */
19634 /* Rd = 16Uto32(Rm) */
19635 UInt rM
= INSN0(5,3);
19636 UInt rD
= INSN0(2,0);
19637 putIRegT(rD
, binop(Iop_And32
, getIRegT(rM
), mkU32(0xFFFF)),
19639 DIP("uxth r%u, r%u\n", rD
, rM
);
19640 goto decode_success
;
19644 /* ---------------- SXTH Rd, Rm ---------------- */
19645 /* Rd = 16Sto32(Rm) */
19646 UInt rM
= INSN0(5,3);
19647 UInt rD
= INSN0(2,0);
19648 putIRegT(rD
, binop(Iop_Sar32
,
19649 binop(Iop_Shl32
, getIRegT(rM
), mkU8(16)),
19652 DIP("sxth r%u, r%u\n", rD
, rM
);
19653 goto decode_success
;
19656 case 0x102: // LSLS
19657 case 0x103: // LSRS
19658 case 0x104: // ASRS
19659 case 0x107: { // RORS
19660 /* ---------------- LSLS Rs, Rd ---------------- */
19661 /* ---------------- LSRS Rs, Rd ---------------- */
19662 /* ---------------- ASRS Rs, Rd ---------------- */
19663 /* ---------------- RORS Rs, Rd ---------------- */
19664 /* Rd = Rd `op` Rs, and set flags */
19665 UInt rS
= INSN0(5,3);
19666 UInt rD
= INSN0(2,0);
19667 IRTemp oldV
= newTemp(Ity_I32
);
19668 IRTemp rDt
= newTemp(Ity_I32
);
19669 IRTemp rSt
= newTemp(Ity_I32
);
19670 IRTemp res
= newTemp(Ity_I32
);
19671 IRTemp resC
= newTemp(Ity_I32
);
19672 const HChar
* wot
= "???";
19673 assign(rSt
, getIRegT(rS
));
19674 assign(rDt
, getIRegT(rD
));
19675 assign(oldV
, mk_armg_calculate_flag_v());
19676 /* Does not appear to be the standard 'how' encoding. */
19677 switch (INSN0(15,6)) {
19679 compute_result_and_C_after_LSL_by_reg(
19680 dis_buf
, &res
, &resC
, rDt
, rSt
, rD
, rS
19685 compute_result_and_C_after_LSR_by_reg(
19686 dis_buf
, &res
, &resC
, rDt
, rSt
, rD
, rS
19691 compute_result_and_C_after_ASR_by_reg(
19692 dis_buf
, &res
, &resC
, rDt
, rSt
, rD
, rS
19697 compute_result_and_C_after_ROR_by_reg(
19698 dis_buf
, &res
, &resC
, rDt
, rSt
, rD
, rS
19703 /*NOTREACHED*/vassert(0);
19705 // not safe to read guest state after this point
19706 putIRegT(rD
, mkexpr(res
), condT
);
19707 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, resC
, oldV
,
19708 cond_AND_notInIT_T
);
19709 DIP("%ss r%u, r%u\n", wot
, rS
, rD
);
19710 goto decode_success
;
19714 case 0x2E9: { // REV16
19715 /* ---------------- REV Rd, Rm ---------------- */
19716 /* ---------------- REV16 Rd, Rm ---------------- */
19717 UInt rM
= INSN0(5,3);
19718 UInt rD
= INSN0(2,0);
19719 Bool isREV
= INSN0(15,6) == 0x2E8;
19720 IRTemp arg
= newTemp(Ity_I32
);
19721 assign(arg
, getIRegT(rM
));
19722 IRTemp res
= isREV
? gen_REV(arg
) : gen_REV16(arg
);
19723 putIRegT(rD
, mkexpr(res
), condT
);
19724 DIP("rev%s r%u, r%u\n", isREV
? "" : "16", rD
, rM
);
19725 goto decode_success
;
19728 case 0x2EB: { // REVSH
19729 /* ---------------- REVSH Rd, Rn ---------------- */
19730 UInt rM
= INSN0(5,3);
19731 UInt rD
= INSN0(2,0);
19732 IRTemp irt_rM
= newTemp(Ity_I32
);
19733 IRTemp irt_hi
= newTemp(Ity_I32
);
19734 IRTemp irt_low
= newTemp(Ity_I32
);
19735 IRTemp irt_res
= newTemp(Ity_I32
);
19736 assign(irt_rM
, getIRegT(rM
));
19739 binop(Iop_Shl32
, mkexpr(irt_rM
), mkU8(24)),
19745 binop(Iop_Shr32
, mkexpr(irt_rM
), mkU8(8)),
19750 binop(Iop_Or32
, mkexpr(irt_hi
), mkexpr(irt_low
))
19752 putIRegT(rD
, mkexpr(irt_res
), condT
);
19753 DIP("revsh r%u, r%u\n", rD
, rM
);
19754 goto decode_success
;
19758 break; /* examine the next shortest prefix */
19763 /* ================ 16-bit 15:7 cases ================ */
19765 switch (INSN0(15,7)) {
19767 case BITS9(1,0,1,1,0,0,0,0,0): {
19768 /* ------------ ADD SP, #imm7 * 4 ------------ */
19769 UInt uimm7
= INSN0(6,0);
19770 putIRegT(13, binop(Iop_Add32
, getIRegT(13), mkU32(uimm7
* 4)),
19772 DIP("add sp, #%u\n", uimm7
* 4);
19773 goto decode_success
;
19776 case BITS9(1,0,1,1,0,0,0,0,1): {
19777 /* ------------ SUB SP, #imm7 * 4 ------------ */
19778 UInt uimm7
= INSN0(6,0);
19779 putIRegT(13, binop(Iop_Sub32
, getIRegT(13), mkU32(uimm7
* 4)),
19781 DIP("sub sp, #%u\n", uimm7
* 4);
19782 goto decode_success
;
19785 case BITS9(0,1,0,0,0,1,1,1,0): {
19786 /* ---------------- BX rM ---------------- */
19787 /* Branch to reg, and optionally switch modes. Reg contains a
19788 suitably encoded address therefore (w CPSR.T at the bottom).
19789 Have to special-case r15, as usual. */
19790 UInt rM
= (INSN0(6,6) << 3) | INSN0(5,3);
19791 if (BITS3(0,0,0) == INSN0(2,0)) {
19792 IRTemp dst
= newTemp(Ity_I32
);
19793 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
19794 mk_skip_over_T16_if_cond_is_false(condT
);
19795 condT
= IRTemp_INVALID
;
19798 assign( dst
, getIRegT(rM
) );
19801 assign( dst
, mkU32(guest_R15_curr_instr_notENC
+ 4) );
19803 llPutIReg(15, mkexpr(dst
));
19804 dres
.jk_StopHere
= rM
== 14 ? Ijk_Ret
: Ijk_Boring
;
19805 dres
.whatNext
= Dis_StopHere
;
19806 DIP("bx r%u (possibly switch to ARM mode)\n", rM
);
19807 goto decode_success
;
19812 /* ---------------- BLX rM ---------------- */
19813 /* Branch and link to interworking address in rM. */
19814 case BITS9(0,1,0,0,0,1,1,1,1): {
19815 if (BITS3(0,0,0) == INSN0(2,0)) {
19816 UInt rM
= (INSN0(6,6) << 3) | INSN0(5,3);
19817 IRTemp dst
= newTemp(Ity_I32
);
19819 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
19820 mk_skip_over_T16_if_cond_is_false(condT
);
19821 condT
= IRTemp_INVALID
;
19823 /* We're returning to Thumb code, hence "| 1" */
19824 assign( dst
, getIRegT(rM
) );
19825 putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC
+ 2) | 1 ),
19827 llPutIReg(15, mkexpr(dst
));
19828 dres
.jk_StopHere
= Ijk_Call
;
19829 dres
.whatNext
= Dis_StopHere
;
19830 DIP("blx r%u (possibly switch to ARM mode)\n", rM
);
19831 goto decode_success
;
19833 /* else unpredictable, fall through */
19839 break; /* examine the next shortest prefix */
19844 /* ================ 16-bit 15:8 cases ================ */
19846 switch (INSN0(15,8)) {
19848 case BITS8(1,1,0,1,1,1,1,1): {
19849 /* ---------------- SVC ---------------- */
19850 UInt imm8
= INSN0(7,0);
19852 /* A syscall. We can't do this conditionally, hence: */
19853 mk_skip_over_T16_if_cond_is_false( condT
);
19854 // FIXME: what if we have to back up and restart this insn?
19855 // then ITSTATE will be wrong (we'll have it as "used")
19856 // when it isn't. Correct is to save ITSTATE in a
19857 // stash pseudo-reg, and back up from that if we have to
19859 // uncond after here
19860 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC
+ 2) | 1 ));
19861 dres
.jk_StopHere
= Ijk_Sys_syscall
;
19862 dres
.whatNext
= Dis_StopHere
;
19863 DIP("svc #0x%08x\n", imm8
);
19864 goto decode_success
;
19866 /* else fall through */
19870 case BITS8(0,1,0,0,0,1,0,0): {
19871 /* ---------------- ADD(HI) Rd, Rm ---------------- */
19872 UInt h1
= INSN0(7,7);
19873 UInt h2
= INSN0(6,6);
19874 UInt rM
= (h2
<< 3) | INSN0(5,3);
19875 UInt rD
= (h1
<< 3) | INSN0(2,0);
19876 //if (h1 == 0 && h2 == 0) { // Original T1 was more restrictive
19877 if (rD
== 15 && rM
== 15) {
19878 // then it's invalid
19880 IRTemp res
= newTemp(Ity_I32
);
19881 assign( res
, binop(Iop_Add32
, getIRegT(rD
), getIRegT(rM
) ));
19883 putIRegT( rD
, mkexpr(res
), condT
);
19885 /* Only allowed outside or last-in IT block; SIGILL if not so. */
19886 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
19887 /* jump over insn if not selected */
19888 mk_skip_over_T16_if_cond_is_false(condT
);
19889 condT
= IRTemp_INVALID
;
19891 /* non-interworking branch */
19892 llPutIReg(15, binop(Iop_Or32
, mkexpr(res
), mkU32(1)));
19893 dres
.jk_StopHere
= Ijk_Boring
;
19894 dres
.whatNext
= Dis_StopHere
;
19896 DIP("add(hi) r%u, r%u\n", rD
, rM
);
19897 goto decode_success
;
19902 case BITS8(0,1,0,0,0,1,0,1): {
19903 /* ---------------- CMP(HI) Rd, Rm ---------------- */
19904 UInt h1
= INSN0(7,7);
19905 UInt h2
= INSN0(6,6);
19906 UInt rM
= (h2
<< 3) | INSN0(5,3);
19907 UInt rN
= (h1
<< 3) | INSN0(2,0);
19908 if (h1
!= 0 || h2
!= 0) {
19909 IRTemp argL
= newTemp(Ity_I32
);
19910 IRTemp argR
= newTemp(Ity_I32
);
19911 assign( argL
, getIRegT(rN
) );
19912 assign( argR
, getIRegT(rM
) );
19913 /* Update flags regardless of whether in an IT block or not. */
19914 setFlags_D1_D2( ARMG_CC_OP_SUB
, argL
, argR
, condT
);
19915 DIP("cmphi r%u, r%u\n", rN
, rM
);
19916 goto decode_success
;
19921 case BITS8(0,1,0,0,0,1,1,0): {
19922 /* ---------------- MOV(HI) Rd, Rm ---------------- */
19923 UInt h1
= INSN0(7,7);
19924 UInt h2
= INSN0(6,6);
19925 UInt rM
= (h2
<< 3) | INSN0(5,3);
19926 UInt rD
= (h1
<< 3) | INSN0(2,0);
19927 /* The old ARM ARM seems to disallow the case where both Rd and
19928 Rm are "low" registers, but newer versions allow it. */
19929 if (1 /*h1 != 0 || h2 != 0*/) {
19930 IRTemp val
= newTemp(Ity_I32
);
19931 assign( val
, getIRegT(rM
) );
19933 putIRegT( rD
, mkexpr(val
), condT
);
19935 /* Only allowed outside or last-in IT block; SIGILL if not so. */
19936 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
19937 /* jump over insn if not selected */
19938 mk_skip_over_T16_if_cond_is_false(condT
);
19939 condT
= IRTemp_INVALID
;
19941 /* non-interworking branch */
19942 llPutIReg(15, binop(Iop_Or32
, mkexpr(val
), mkU32(1)));
19943 dres
.jk_StopHere
= rM
== 14 ? Ijk_Ret
: Ijk_Boring
;
19944 dres
.whatNext
= Dis_StopHere
;
19946 DIP("mov r%u, r%u\n", rD
, rM
);
19947 goto decode_success
;
19952 case BITS8(1,0,1,1,1,1,1,1): {
19953 /* ---------------- IT (if-then) ---------------- */
19954 UInt firstcond
= INSN0(7,4);
19955 UInt mask
= INSN0(3,0);
19956 UInt newITSTATE
= 0;
19957 /* This is the ITSTATE represented as described in
19958 libvex_guest_arm.h. It is not the ARM ARM representation. */
19962 Bool valid
= compute_ITSTATE( &newITSTATE
, &c1
, &c2
, &c3
,
19964 if (valid
&& firstcond
!= 0xF/*NV*/) {
19965 /* Not allowed in an IT block; SIGILL if so. */
19966 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
19968 IRTemp t
= newTemp(Ity_I32
);
19969 assign(t
, mkU32(newITSTATE
));
19972 DIP("it%c%c%c %s\n", c1
, c2
, c3
, nCC(firstcond
));
19973 goto decode_success
;
19978 case BITS8(1,0,1,1,0,0,0,1):
19979 case BITS8(1,0,1,1,0,0,1,1):
19980 case BITS8(1,0,1,1,1,0,0,1):
19981 case BITS8(1,0,1,1,1,0,1,1): {
19982 /* ---------------- CB{N}Z ---------------- */
19983 UInt rN
= INSN0(2,0);
19984 UInt bOP
= INSN0(11,11);
19985 UInt imm32
= (INSN0(9,9) << 6) | (INSN0(7,3) << 1);
19986 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
19987 /* It's a conditional branch forward. */
19988 IRTemp kond
= newTemp(Ity_I1
);
19989 assign( kond
, binop(bOP
? Iop_CmpNE32
: Iop_CmpEQ32
,
19990 getIRegT(rN
), mkU32(0)) );
19992 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
19993 /* Looks like the nearest insn we can branch to is the one after
19994 next. That makes sense, as there's no point in being able to
19995 encode a conditional branch to the next instruction. */
19996 UInt dst
= (guest_R15_curr_instr_notENC
+ 4 + imm32
) | 1;
19997 stmt(IRStmt_Exit( mkexpr(kond
),
19999 IRConst_U32(toUInt(dst
)),
20001 DIP("cb%s r%u, 0x%x\n", bOP
? "nz" : "z", rN
, dst
- 1);
20002 goto decode_success
;
20006 break; /* examine the next shortest prefix */
20011 /* ================ 16-bit 15:9 cases ================ */
20013 switch (INSN0(15,9)) {
20015 case BITS7(1,0,1,1,0,1,0): {
20016 /* ---------------- PUSH ---------------- */
20017 /* This is a bit like STMxx, but way simpler. Complications we
20018 don't have to deal with:
20019 * SP being one of the transferred registers
20020 * direction (increment vs decrement)
20021 * before-vs-after-ness
20024 UInt bitR
= INSN0(8,8);
20025 UInt regList
= INSN0(7,0);
20026 if (bitR
) regList
|= (1 << 14);
20028 /* At least one register must be transferred, else result is
20030 if (regList
!= 0) {
20031 /* Since we can't generate a guaranteed non-trapping IR
20032 sequence, (1) jump over the insn if it is gated false, and
20033 (2) back out the ITSTATE update. */
20034 mk_skip_over_T16_if_cond_is_false(condT
);
20035 condT
= IRTemp_INVALID
;
20036 put_ITSTATE(old_itstate
);
20040 for (i
= 0; i
< 16; i
++) {
20041 if ((regList
& (1 << i
)) != 0)
20044 vassert(nRegs
>= 1 && nRegs
<= 9);
20046 /* Move SP down first of all, so we're "covered". And don't
20047 mess with its alignment. */
20048 IRTemp newSP
= newTemp(Ity_I32
);
20049 assign(newSP
, binop(Iop_Sub32
, getIRegT(13), mkU32(4 * nRegs
)));
20050 putIRegT(13, mkexpr(newSP
), IRTemp_INVALID
);
20052 /* Generate a transfer base address as a forced-aligned
20053 version of the final SP value. */
20054 IRTemp base
= newTemp(Ity_I32
);
20055 assign(base
, binop(Iop_And32
, mkexpr(newSP
), mkU32(~3)));
20057 /* Now the transfers */
20059 for (i
= 0; i
< 16; i
++) {
20060 if ((regList
& (1 << i
)) != 0) {
20061 storeLE( binop(Iop_Add32
, mkexpr(base
), mkU32(4 * nRegs
)),
20067 /* Reinstate the ITSTATE update. */
20068 put_ITSTATE(new_itstate
);
20070 DIP("push {%s0x%04x}\n", bitR
? "lr," : "", regList
& 0xFF);
20071 goto decode_success
;
20076 case BITS7(1,0,1,1,1,1,0): {
20077 /* ---------------- POP ---------------- */
20079 UInt bitR
= INSN0(8,8);
20080 UInt regList
= INSN0(7,0);
20082 /* At least one register must be transferred, else result is
20084 if (regList
!= 0 || bitR
) {
20085 /* Since we can't generate a guaranteed non-trapping IR
20086 sequence, (1) jump over the insn if it is gated false, and
20087 (2) back out the ITSTATE update. */
20088 mk_skip_over_T16_if_cond_is_false(condT
);
20089 condT
= IRTemp_INVALID
;
20090 put_ITSTATE(old_itstate
);
20094 for (i
= 0; i
< 8; i
++) {
20095 if ((regList
& (1 << i
)) != 0)
20098 vassert(nRegs
>= 0 && nRegs
<= 8);
20099 vassert(bitR
== 0 || bitR
== 1);
20101 IRTemp oldSP
= newTemp(Ity_I32
);
20102 assign(oldSP
, getIRegT(13));
20104 /* Generate a transfer base address as a forced-aligned
20105 version of the original SP value. */
20106 IRTemp base
= newTemp(Ity_I32
);
20107 assign(base
, binop(Iop_And32
, mkexpr(oldSP
), mkU32(~3)));
20109 /* Compute a new value for SP, but don't install it yet, so
20110 that we're "covered" until all the transfers are done.
20111 And don't mess with its alignment. */
20112 IRTemp newSP
= newTemp(Ity_I32
);
20113 assign(newSP
, binop(Iop_Add32
, mkexpr(oldSP
),
20114 mkU32(4 * (nRegs
+ bitR
))));
20116 /* Now the transfers, not including PC */
20118 for (i
= 0; i
< 8; i
++) {
20119 if ((regList
& (1 << i
)) != 0) {
20120 putIRegT(i
, loadLE( Ity_I32
,
20121 binop(Iop_Add32
, mkexpr(base
),
20122 mkU32(4 * nRegs
))),
20128 IRTemp newPC
= IRTemp_INVALID
;
20130 newPC
= newTemp(Ity_I32
);
20131 assign( newPC
, loadLE( Ity_I32
,
20132 binop(Iop_Add32
, mkexpr(base
),
20133 mkU32(4 * nRegs
))));
20136 /* Now we can safely install the new SP value */
20137 putIRegT(13, mkexpr(newSP
), IRTemp_INVALID
);
20139 /* Reinstate the ITSTATE update. */
20140 put_ITSTATE(new_itstate
);
20142 /* now, do we also have to do a branch? If so, it turns out
20143 that the new PC value is encoded exactly as we need it to
20144 be -- with CPSR.T in the bottom bit. So we can simply use
20145 it as is, no need to mess with it. Note, therefore, this
20146 is an interworking return. */
20148 llPutIReg(15, mkexpr(newPC
));
20149 dres
.jk_StopHere
= Ijk_Ret
;
20150 dres
.whatNext
= Dis_StopHere
;
20153 DIP("pop {%s0x%04x}\n", bitR
? "pc," : "", regList
& 0xFF);
20154 goto decode_success
;
20159 case BITS7(0,0,0,1,1,1,0): /* ADDS */
20160 case BITS7(0,0,0,1,1,1,1): { /* SUBS */
20161 /* ---------------- ADDS Rd, Rn, #uimm3 ---------------- */
20162 /* ---------------- SUBS Rd, Rn, #uimm3 ---------------- */
20163 UInt uimm3
= INSN0(8,6);
20164 UInt rN
= INSN0(5,3);
20165 UInt rD
= INSN0(2,0);
20166 UInt isSub
= INSN0(9,9);
20167 IRTemp argL
= newTemp(Ity_I32
);
20168 IRTemp argR
= newTemp(Ity_I32
);
20169 assign( argL
, getIRegT(rN
) );
20170 assign( argR
, mkU32(uimm3
) );
20171 putIRegT(rD
, binop(isSub
? Iop_Sub32
: Iop_Add32
,
20172 mkexpr(argL
), mkexpr(argR
)),
20174 setFlags_D1_D2( isSub
? ARMG_CC_OP_SUB
: ARMG_CC_OP_ADD
,
20175 argL
, argR
, cond_AND_notInIT_T
);
20176 DIP("%s r%u, r%u, #%u\n", isSub
? "subs" : "adds", rD
, rN
, uimm3
);
20177 goto decode_success
;
20180 case BITS7(0,0,0,1,1,0,0): /* ADDS */
20181 case BITS7(0,0,0,1,1,0,1): { /* SUBS */
20182 /* ---------------- ADDS Rd, Rn, Rm ---------------- */
20183 /* ---------------- SUBS Rd, Rn, Rm ---------------- */
20184 UInt rM
= INSN0(8,6);
20185 UInt rN
= INSN0(5,3);
20186 UInt rD
= INSN0(2,0);
20187 UInt isSub
= INSN0(9,9);
20188 IRTemp argL
= newTemp(Ity_I32
);
20189 IRTemp argR
= newTemp(Ity_I32
);
20190 assign( argL
, getIRegT(rN
) );
20191 assign( argR
, getIRegT(rM
) );
20192 putIRegT( rD
, binop(isSub
? Iop_Sub32
: Iop_Add32
,
20193 mkexpr(argL
), mkexpr(argR
)),
20195 setFlags_D1_D2( isSub
? ARMG_CC_OP_SUB
: ARMG_CC_OP_ADD
,
20196 argL
, argR
, cond_AND_notInIT_T
);
20197 DIP("%s r%u, r%u, r%u\n", isSub
? "subs" : "adds", rD
, rN
, rM
);
20198 goto decode_success
;
20201 case BITS7(0,1,0,1,0,0,0): /* STR */
20202 case BITS7(0,1,0,1,1,0,0): { /* LDR */
20203 /* ------------- LDR Rd, [Rn, Rm] ------------- */
20204 /* ------------- STR Rd, [Rn, Rm] ------------- */
20205 /* LDR/STR Rd, [Rn + Rm] */
20206 UInt rD
= INSN0(2,0);
20207 UInt rN
= INSN0(5,3);
20208 UInt rM
= INSN0(8,6);
20209 UInt isLD
= INSN0(11,11);
20211 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), getIRegT(rM
));
20212 put_ITSTATE(old_itstate
); // backout
20214 IRTemp tD
= newTemp(Ity_I32
);
20215 loadGuardedLE( tD
, ILGop_Ident32
, ea
, llGetIReg(rD
), condT
);
20216 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20218 storeGuardedLE(ea
, getIRegT(rD
), condT
);
20220 put_ITSTATE(new_itstate
); // restore
20222 DIP("%s r%u, [r%u, r%u]\n", isLD
? "ldr" : "str", rD
, rN
, rM
);
20223 goto decode_success
;
20226 case BITS7(0,1,0,1,0,0,1):
20227 case BITS7(0,1,0,1,1,0,1): {
20228 /* ------------- LDRH Rd, [Rn, Rm] ------------- */
20229 /* ------------- STRH Rd, [Rn, Rm] ------------- */
20230 /* LDRH/STRH Rd, [Rn + Rm] */
20231 UInt rD
= INSN0(2,0);
20232 UInt rN
= INSN0(5,3);
20233 UInt rM
= INSN0(8,6);
20234 UInt isLD
= INSN0(11,11);
20236 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), getIRegT(rM
));
20237 put_ITSTATE(old_itstate
); // backout
20239 IRTemp tD
= newTemp(Ity_I32
);
20240 loadGuardedLE(tD
, ILGop_16Uto32
, ea
, llGetIReg(rD
), condT
);
20241 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20243 storeGuardedLE( ea
, unop(Iop_32to16
, getIRegT(rD
)), condT
);
20245 put_ITSTATE(new_itstate
); // restore
20247 DIP("%sh r%u, [r%u, r%u]\n", isLD
? "ldr" : "str", rD
, rN
, rM
);
20248 goto decode_success
;
20251 case BITS7(0,1,0,1,1,1,1): {
20252 /* ------------- LDRSH Rd, [Rn, Rm] ------------- */
20253 /* LDRSH Rd, [Rn + Rm] */
20254 UInt rD
= INSN0(2,0);
20255 UInt rN
= INSN0(5,3);
20256 UInt rM
= INSN0(8,6);
20258 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), getIRegT(rM
));
20259 put_ITSTATE(old_itstate
); // backout
20260 IRTemp tD
= newTemp(Ity_I32
);
20261 loadGuardedLE(tD
, ILGop_16Sto32
, ea
, llGetIReg(rD
), condT
);
20262 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20263 put_ITSTATE(new_itstate
); // restore
20265 DIP("ldrsh r%u, [r%u, r%u]\n", rD
, rN
, rM
);
20266 goto decode_success
;
20269 case BITS7(0,1,0,1,0,1,1): {
20270 /* ------------- LDRSB Rd, [Rn, Rm] ------------- */
20271 /* LDRSB Rd, [Rn + Rm] */
20272 UInt rD
= INSN0(2,0);
20273 UInt rN
= INSN0(5,3);
20274 UInt rM
= INSN0(8,6);
20276 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), getIRegT(rM
));
20277 put_ITSTATE(old_itstate
); // backout
20278 IRTemp tD
= newTemp(Ity_I32
);
20279 loadGuardedLE(tD
, ILGop_8Sto32
, ea
, llGetIReg(rD
), condT
);
20280 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20281 put_ITSTATE(new_itstate
); // restore
20283 DIP("ldrsb r%u, [r%u, r%u]\n", rD
, rN
, rM
);
20284 goto decode_success
;
20287 case BITS7(0,1,0,1,0,1,0):
20288 case BITS7(0,1,0,1,1,1,0): {
20289 /* ------------- LDRB Rd, [Rn, Rm] ------------- */
20290 /* ------------- STRB Rd, [Rn, Rm] ------------- */
20291 /* LDRB/STRB Rd, [Rn + Rm] */
20292 UInt rD
= INSN0(2,0);
20293 UInt rN
= INSN0(5,3);
20294 UInt rM
= INSN0(8,6);
20295 UInt isLD
= INSN0(11,11);
20297 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), getIRegT(rM
));
20298 put_ITSTATE(old_itstate
); // backout
20300 IRTemp tD
= newTemp(Ity_I32
);
20301 loadGuardedLE(tD
, ILGop_8Uto32
, ea
, llGetIReg(rD
), condT
);
20302 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20304 storeGuardedLE( ea
, unop(Iop_32to8
, getIRegT(rD
)), condT
);
20306 put_ITSTATE(new_itstate
); // restore
20308 DIP("%sb r%u, [r%u, r%u]\n", isLD
? "ldr" : "str", rD
, rN
, rM
);
20309 goto decode_success
;
20313 break; /* examine the next shortest prefix */
20318 /* ================ 16-bit 15:11 cases ================ */
20320 switch (INSN0(15,11)) {
20322 case BITS5(0,0,1,1,0):
20323 case BITS5(0,0,1,1,1): {
20324 /* ---------------- ADDS Rn, #uimm8 ---------------- */
20325 /* ---------------- SUBS Rn, #uimm8 ---------------- */
20326 UInt isSub
= INSN0(11,11);
20327 UInt rN
= INSN0(10,8);
20328 UInt uimm8
= INSN0(7,0);
20329 IRTemp argL
= newTemp(Ity_I32
);
20330 IRTemp argR
= newTemp(Ity_I32
);
20331 assign( argL
, getIRegT(rN
) );
20332 assign( argR
, mkU32(uimm8
) );
20333 putIRegT( rN
, binop(isSub
? Iop_Sub32
: Iop_Add32
,
20334 mkexpr(argL
), mkexpr(argR
)), condT
);
20335 setFlags_D1_D2( isSub
? ARMG_CC_OP_SUB
: ARMG_CC_OP_ADD
,
20336 argL
, argR
, cond_AND_notInIT_T
);
20337 DIP("%s r%u, #%u\n", isSub
? "subs" : "adds", rN
, uimm8
);
20338 goto decode_success
;
20341 case BITS5(1,0,1,0,0): {
20342 /* ---------------- ADD rD, PC, #imm8 * 4 ---------------- */
20344 /* rD = align4(PC) + imm8 * 4 */
20345 UInt rD
= INSN0(10,8);
20346 UInt imm8
= INSN0(7,0);
20347 putIRegT(rD
, binop(Iop_Add32
,
20348 binop(Iop_And32
, getIRegT(15), mkU32(~3U)),
20351 DIP("add r%u, pc, #%u\n", rD
, imm8
* 4);
20352 goto decode_success
;
20355 case BITS5(1,0,1,0,1): {
20356 /* ---------------- ADD rD, SP, #imm8 * 4 ---------------- */
20357 UInt rD
= INSN0(10,8);
20358 UInt imm8
= INSN0(7,0);
20359 putIRegT(rD
, binop(Iop_Add32
, getIRegT(13), mkU32(imm8
* 4)),
20361 DIP("add r%u, r13, #%u\n", rD
, imm8
* 4);
20362 goto decode_success
;
20365 case BITS5(0,0,1,0,1): {
20366 /* ---------------- CMP Rn, #uimm8 ---------------- */
20367 UInt rN
= INSN0(10,8);
20368 UInt uimm8
= INSN0(7,0);
20369 IRTemp argL
= newTemp(Ity_I32
);
20370 IRTemp argR
= newTemp(Ity_I32
);
20371 assign( argL
, getIRegT(rN
) );
20372 assign( argR
, mkU32(uimm8
) );
20373 /* Update flags regardless of whether in an IT block or not. */
20374 setFlags_D1_D2( ARMG_CC_OP_SUB
, argL
, argR
, condT
);
20375 DIP("cmp r%u, #%u\n", rN
, uimm8
);
20376 goto decode_success
;
20379 case BITS5(0,0,1,0,0): {
20380 /* -------------- (T1) MOVS Rn, #uimm8 -------------- */
20381 UInt rD
= INSN0(10,8);
20382 UInt uimm8
= INSN0(7,0);
20383 IRTemp oldV
= newTemp(Ity_I32
);
20384 IRTemp oldC
= newTemp(Ity_I32
);
20385 IRTemp res
= newTemp(Ity_I32
);
20386 assign( oldV
, mk_armg_calculate_flag_v() );
20387 assign( oldC
, mk_armg_calculate_flag_c() );
20388 assign( res
, mkU32(uimm8
) );
20389 putIRegT(rD
, mkexpr(res
), condT
);
20390 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
20391 cond_AND_notInIT_T
);
20392 DIP("movs r%u, #%u\n", rD
, uimm8
);
20393 goto decode_success
;
20396 case BITS5(0,1,0,0,1): {
20397 /* ------------- LDR Rd, [PC, #imm8 * 4] ------------- */
20398 /* LDR Rd, [align4(PC) + imm8 * 4] */
20399 UInt rD
= INSN0(10,8);
20400 UInt imm8
= INSN0(7,0);
20401 IRTemp ea
= newTemp(Ity_I32
);
20403 assign(ea
, binop(Iop_Add32
,
20404 binop(Iop_And32
, getIRegT(15), mkU32(~3U)),
20406 put_ITSTATE(old_itstate
); // backout
20407 IRTemp tD
= newTemp(Ity_I32
);
20408 loadGuardedLE( tD
, ILGop_Ident32
, mkexpr(ea
), llGetIReg(rD
), condT
);
20409 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20410 put_ITSTATE(new_itstate
); // restore
20412 DIP("ldr r%u, [pc, #%u]\n", rD
, imm8
* 4);
20413 goto decode_success
;
20416 case BITS5(0,1,1,0,0): /* STR */
20417 case BITS5(0,1,1,0,1): { /* LDR */
20418 /* ------------- LDR Rd, [Rn, #imm5 * 4] ------------- */
20419 /* ------------- STR Rd, [Rn, #imm5 * 4] ------------- */
20420 /* LDR/STR Rd, [Rn + imm5 * 4] */
20421 UInt rD
= INSN0(2,0);
20422 UInt rN
= INSN0(5,3);
20423 UInt imm5
= INSN0(10,6);
20424 UInt isLD
= INSN0(11,11);
20426 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm5
* 4));
20427 put_ITSTATE(old_itstate
); // backout
20429 IRTemp tD
= newTemp(Ity_I32
);
20430 loadGuardedLE( tD
, ILGop_Ident32
, ea
, llGetIReg(rD
), condT
);
20431 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20433 storeGuardedLE( ea
, getIRegT(rD
), condT
);
20435 put_ITSTATE(new_itstate
); // restore
20437 DIP("%s r%u, [r%u, #%u]\n", isLD
? "ldr" : "str", rD
, rN
, imm5
* 4);
20438 goto decode_success
;
20441 case BITS5(1,0,0,0,0): /* STRH */
20442 case BITS5(1,0,0,0,1): { /* LDRH */
20443 /* ------------- LDRH Rd, [Rn, #imm5 * 2] ------------- */
20444 /* ------------- STRH Rd, [Rn, #imm5 * 2] ------------- */
20445 /* LDRH/STRH Rd, [Rn + imm5 * 2] */
20446 UInt rD
= INSN0(2,0);
20447 UInt rN
= INSN0(5,3);
20448 UInt imm5
= INSN0(10,6);
20449 UInt isLD
= INSN0(11,11);
20451 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm5
* 2));
20452 put_ITSTATE(old_itstate
); // backout
20454 IRTemp tD
= newTemp(Ity_I32
);
20455 loadGuardedLE( tD
, ILGop_16Uto32
, ea
, llGetIReg(rD
), condT
);
20456 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20458 storeGuardedLE( ea
, unop(Iop_32to16
, getIRegT(rD
)), condT
);
20460 put_ITSTATE(new_itstate
); // restore
20462 DIP("%sh r%u, [r%u, #%u]\n", isLD
? "ldr" : "str", rD
, rN
, imm5
* 2);
20463 goto decode_success
;
20466 case BITS5(0,1,1,1,0): /* STRB */
20467 case BITS5(0,1,1,1,1): { /* LDRB */
20468 /* ------------- LDRB Rd, [Rn, #imm5] ------------- */
20469 /* ------------- STRB Rd, [Rn, #imm5] ------------- */
20470 /* LDRB/STRB Rd, [Rn + imm5] */
20471 UInt rD
= INSN0(2,0);
20472 UInt rN
= INSN0(5,3);
20473 UInt imm5
= INSN0(10,6);
20474 UInt isLD
= INSN0(11,11);
20476 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm5
));
20477 put_ITSTATE(old_itstate
); // backout
20479 IRTemp tD
= newTemp(Ity_I32
);
20480 loadGuardedLE( tD
, ILGop_8Uto32
, ea
, llGetIReg(rD
), condT
);
20481 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20483 storeGuardedLE( ea
, unop(Iop_32to8
, getIRegT(rD
)), condT
);
20485 put_ITSTATE(new_itstate
); // restore
20487 DIP("%sb r%u, [r%u, #%u]\n", isLD
? "ldr" : "str", rD
, rN
, imm5
);
20488 goto decode_success
;
20491 case BITS5(1,0,0,1,0): /* STR */
20492 case BITS5(1,0,0,1,1): { /* LDR */
20493 /* ------------- LDR Rd, [SP, #imm8 * 4] ------------- */
20494 /* ------------- STR Rd, [SP, #imm8 * 4] ------------- */
20495 /* LDR/STR Rd, [SP + imm8 * 4] */
20496 UInt rD
= INSN0(10,8);
20497 UInt imm8
= INSN0(7,0);
20498 UInt isLD
= INSN0(11,11);
20500 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(13), mkU32(imm8
* 4));
20501 put_ITSTATE(old_itstate
); // backout
20503 IRTemp tD
= newTemp(Ity_I32
);
20504 loadGuardedLE( tD
, ILGop_Ident32
, ea
, llGetIReg(rD
), condT
);
20505 putIRegT(rD
, mkexpr(tD
), IRTemp_INVALID
);
20507 storeGuardedLE(ea
, getIRegT(rD
), condT
);
20509 put_ITSTATE(new_itstate
); // restore
20511 DIP("%s r%u, [sp, #%u]\n", isLD
? "ldr" : "str", rD
, imm8
* 4);
20512 goto decode_success
;
20515 case BITS5(1,1,0,0,1): {
20516 /* ------------- LDMIA Rn!, {reglist} ------------- */
20518 UInt rN
= INSN0(10,8);
20519 UInt list
= INSN0(7,0);
20520 /* Empty lists aren't allowed. */
20522 mk_skip_over_T16_if_cond_is_false(condT
);
20523 condT
= IRTemp_INVALID
;
20524 put_ITSTATE(old_itstate
);
20527 IRTemp oldRn
= newTemp(Ity_I32
);
20528 IRTemp base
= newTemp(Ity_I32
);
20529 assign(oldRn
, getIRegT(rN
));
20530 assign(base
, binop(Iop_And32
, mkexpr(oldRn
), mkU32(~3U)));
20531 for (i
= 0; i
< 8; i
++) {
20532 if (0 == (list
& (1 << i
)))
20537 binop(Iop_Add32
, mkexpr(base
),
20538 mkU32(nRegs
* 4 - 4))),
20542 /* Only do the writeback for rN if it isn't in the list of
20543 registers to be transferred. */
20544 if (0 == (list
& (1 << rN
))) {
20546 binop(Iop_Add32
, mkexpr(oldRn
),
20552 /* Reinstate the ITSTATE update. */
20553 put_ITSTATE(new_itstate
);
20555 DIP("ldmia r%u!, {0x%04x}\n", rN
, list
);
20556 goto decode_success
;
20561 case BITS5(1,1,0,0,0): {
20562 /* ------------- STMIA Rn!, {reglist} ------------- */
20564 UInt rN
= INSN0(10,8);
20565 UInt list
= INSN0(7,0);
20566 /* Empty lists aren't allowed. Also, if rN is in the list then
20567 it must be the lowest numbered register in the list. */
20568 Bool valid
= list
!= 0;
20569 if (valid
&& 0 != (list
& (1 << rN
))) {
20570 for (i
= 0; i
< rN
; i
++) {
20571 if (0 != (list
& (1 << i
)))
20576 mk_skip_over_T16_if_cond_is_false(condT
);
20577 condT
= IRTemp_INVALID
;
20578 put_ITSTATE(old_itstate
);
20581 IRTemp oldRn
= newTemp(Ity_I32
);
20582 IRTemp base
= newTemp(Ity_I32
);
20583 assign(oldRn
, getIRegT(rN
));
20584 assign(base
, binop(Iop_And32
, mkexpr(oldRn
), mkU32(~3U)));
20585 for (i
= 0; i
< 8; i
++) {
20586 if (0 == (list
& (1 << i
)))
20589 storeLE( binop(Iop_Add32
, mkexpr(base
), mkU32(nRegs
* 4 - 4)),
20592 /* Always do the writeback. */
20594 binop(Iop_Add32
, mkexpr(oldRn
),
20598 /* Reinstate the ITSTATE update. */
20599 put_ITSTATE(new_itstate
);
20601 DIP("stmia r%u!, {0x%04x}\n", rN
, list
);
20602 goto decode_success
;
20607 case BITS5(0,0,0,0,0): /* LSLS */
20608 case BITS5(0,0,0,0,1): /* LSRS */
20609 case BITS5(0,0,0,1,0): { /* ASRS */
20610 /* ---------------- LSLS Rd, Rm, #imm5 ---------------- */
20611 /* ---------------- LSRS Rd, Rm, #imm5 ---------------- */
20612 /* ---------------- ASRS Rd, Rm, #imm5 ---------------- */
20613 UInt rD
= INSN0(2,0);
20614 UInt rM
= INSN0(5,3);
20615 UInt imm5
= INSN0(10,6);
20616 IRTemp res
= newTemp(Ity_I32
);
20617 IRTemp resC
= newTemp(Ity_I32
);
20618 IRTemp rMt
= newTemp(Ity_I32
);
20619 IRTemp oldV
= newTemp(Ity_I32
);
20620 const HChar
* wot
= "???";
20621 assign(rMt
, getIRegT(rM
));
20622 assign(oldV
, mk_armg_calculate_flag_v());
20623 /* Looks like INSN0(12,11) are the standard 'how' encoding.
20624 Could compactify if the ROR case later appears. */
20625 switch (INSN0(15,11)) {
20626 case BITS5(0,0,0,0,0):
20627 compute_result_and_C_after_LSL_by_imm5(
20628 dis_buf
, &res
, &resC
, rMt
, imm5
, rM
20632 case BITS5(0,0,0,0,1):
20633 compute_result_and_C_after_LSR_by_imm5(
20634 dis_buf
, &res
, &resC
, rMt
, imm5
, rM
20638 case BITS5(0,0,0,1,0):
20639 compute_result_and_C_after_ASR_by_imm5(
20640 dis_buf
, &res
, &resC
, rMt
, imm5
, rM
20645 /*NOTREACHED*/vassert(0);
20647 // not safe to read guest state after this point
20648 putIRegT(rD
, mkexpr(res
), condT
);
20649 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, resC
, oldV
,
20650 cond_AND_notInIT_T
);
20651 /* ignore buf and roll our own output */
20652 DIP("%ss r%u, r%u, #%u\n", wot
, rD
, rM
, imm5
);
20653 goto decode_success
;
20656 case BITS5(1,1,1,0,0): {
20657 /* ---------------- B #simm11 ---------------- */
20658 UInt uimm11
= INSN0(10,0); uimm11
<<= 21;
20659 Int simm11
= (Int
)uimm11
; simm11
>>= 20;
20660 UInt dst
= simm11
+ guest_R15_curr_instr_notENC
+ 4;
20661 /* Only allowed outside or last-in IT block; SIGILL if not so. */
20662 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
20663 // and skip this insn if not selected; being cleverer is too
20665 mk_skip_over_T16_if_cond_is_false(condT
);
20666 condT
= IRTemp_INVALID
;
20668 llPutIReg(15, mkU32( dst
| 1 /*CPSR.T*/ ));
20669 dres
.jk_StopHere
= Ijk_Boring
;
20670 dres
.whatNext
= Dis_StopHere
;
20671 DIP("b 0x%x\n", dst
);
20672 goto decode_success
;
20676 break; /* examine the next shortest prefix */
20681 /* ================ 16-bit 15:12 cases ================ */
20683 switch (INSN0(15,12)) {
20685 case BITS4(1,1,0,1): {
20686 /* ---------------- Bcond #simm8 ---------------- */
20687 UInt cond
= INSN0(11,8);
20688 UInt uimm8
= INSN0(7,0); uimm8
<<= 24;
20689 Int simm8
= (Int
)uimm8
; simm8
>>= 23;
20690 UInt dst
= simm8
+ guest_R15_curr_instr_notENC
+ 4;
20691 if (cond
!= ARMCondAL
&& cond
!= ARMCondNV
) {
20692 /* Not allowed in an IT block; SIGILL if so. */
20693 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
20695 IRTemp kondT
= newTemp(Ity_I32
);
20696 assign( kondT
, mk_armg_calculate_condition(cond
) );
20697 stmt( IRStmt_Exit( unop(Iop_32to1
, mkexpr(kondT
)),
20699 IRConst_U32(dst
| 1/*CPSR.T*/),
20701 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC
+ 2)
20703 dres
.jk_StopHere
= Ijk_Boring
;
20704 dres
.whatNext
= Dis_StopHere
;
20705 DIP("b%s 0x%x\n", nCC(cond
), dst
);
20706 goto decode_success
;
20712 break; /* hmm, nothing matched */
20716 /* ================ 16-bit misc cases ================ */
20718 switch (INSN0(15,0)) {
20720 /* ------ NOP ------ */
20722 goto decode_success
;
20723 case 0xBF10: // YIELD
20724 case 0xBF20: // WFE
20725 /* ------ WFE, YIELD ------ */
20726 /* Both appear to get used as a spin-loop hints. Do the usual thing,
20727 which is to continue after yielding. */
20728 stmt( IRStmt_Exit( unop(Iop_32to1
, mkexpr(condT
)),
20730 IRConst_U32((guest_R15_curr_instr_notENC
+ 2)
20733 Bool isWFE
= INSN0(15,0) == 0xBF20;
20734 DIP(isWFE
? "wfe\n" : "yield\n");
20735 goto decode_success
;
20737 /* ------ SEV ------ */
20738 /* Treat this as a no-op. Any matching WFEs won't really
20739 cause the host CPU to snooze; they just cause V to try to
20740 run some other thread for a while. So there's no point in
20741 really doing anything for SEV. */
20743 goto decode_success
;
20745 break; /* fall through */
20748 /* ----------------------------------------------------------- */
20750 /* -- Thumb 32-bit integer instructions -- */
20752 /* ----------------------------------------------------------- */
20754 # define INSN1(_bMax,_bMin) SLICE_UInt(((UInt)insn1), (_bMax), (_bMin))
20756 /* second 16 bits of the instruction, if any */
20757 vassert(insn1
== 0);
20758 insn1
= getUShortLittleEndianly( guest_instr
+2 );
20760 anOp
= Iop_INVALID
; /* paranoia */
20761 anOpNm
= NULL
; /* paranoia */
20763 /* Change result defaults to suit 32-bit insns. */
20764 vassert(dres
.whatNext
== Dis_Continue
);
20765 vassert(dres
.len
== 2);
20766 vassert(dres
.continueAt
== 0);
20769 /* ---------------- BL/BLX simm26 ---------------- */
20770 if (BITS5(1,1,1,1,0) == INSN0(15,11) && BITS2(1,1) == INSN1(15,14)) {
20771 UInt isBL
= INSN1(12,12);
20772 UInt bS
= INSN0(10,10);
20773 UInt bJ1
= INSN1(13,13);
20774 UInt bJ2
= INSN1(11,11);
20775 UInt bI1
= 1 ^ (bJ1
^ bS
);
20776 UInt bI2
= 1 ^ (bJ2
^ bS
);
20778 = (bS
<< (1 + 1 + 10 + 11 + 1))
20779 | (bI1
<< (1 + 10 + 11 + 1))
20780 | (bI2
<< (10 + 11 + 1))
20781 | (INSN0(9,0) << (11 + 1))
20782 | (INSN1(10,0) << 1);
20784 Int simm25
= (Int
)uimm25
;
20787 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
20788 UInt dst
= simm25
+ guest_R15_curr_instr_notENC
+ 4;
20790 /* One further validity case to check: in the case of BLX
20791 (not-BL), that insn1[0] must be zero. */
20793 if (isBL
== 0 && INSN1(0,0) == 1) valid
= False
;
20795 /* Only allowed outside or last-in IT block; SIGILL if not so. */
20796 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
20797 // and skip this insn if not selected; being cleverer is too
20799 mk_skip_over_T32_if_cond_is_false(condT
);
20800 condT
= IRTemp_INVALID
;
20803 /* We're returning to Thumb code, hence "| 1" */
20804 putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC
+ 4) | 1 ),
20807 /* BL: unconditional T -> T call */
20808 /* we're calling Thumb code, hence "| 1" */
20809 llPutIReg(15, mkU32( dst
| 1 ));
20810 DIP("bl 0x%x (stay in Thumb mode)\n", dst
);
20812 /* BLX: unconditional T -> A call */
20813 /* we're calling ARM code, hence "& 3" to align to a
20814 valid ARM insn address */
20815 llPutIReg(15, mkU32( dst
& ~3 ));
20816 DIP("blx 0x%x (switch to ARM mode)\n", dst
& ~3);
20818 dres
.whatNext
= Dis_StopHere
;
20819 dres
.jk_StopHere
= Ijk_Call
;
20820 goto decode_success
;
20824 /* ---------------- {LD,ST}M{IA,DB} ---------------- */
20825 if (0x3a2 == INSN0(15,6) // {LD,ST}MIA
20826 || 0x3a4 == INSN0(15,6)) { // {LD,ST}MDB
20827 UInt bW
= INSN0(5,5); /* writeback Rn ? */
20828 UInt bL
= INSN0(4,4);
20829 UInt rN
= INSN0(3,0);
20830 UInt bP
= INSN1(15,15); /* reglist entry for r15 */
20831 UInt bM
= INSN1(14,14); /* reglist entry for r14 */
20832 UInt rLmost
= INSN1(12,0); /* reglist entry for r0 .. 12 */
20833 UInt rL13
= INSN1(13,13); /* must be zero */
20839 if (INSN0(15,6) == 0x3a4) {
20844 /* detect statically invalid cases, and construct the final
20850 regList
= (bP
<< 15) | (bM
<< 14) | rLmost
;
20851 if (rN
== 15) valid
= False
;
20852 if (popcount32(regList
) < 2) valid
= False
;
20853 if (bP
== 1 && bM
== 1) valid
= False
;
20854 if (bW
== 1 && (regList
& (1<<rN
))) valid
= False
;
20856 regList
= (bM
<< 14) | rLmost
;
20857 if (bP
== 1) valid
= False
;
20858 if (rN
== 15) valid
= False
;
20859 if (popcount32(regList
) < 2) valid
= False
;
20860 if (bW
== 1 && (regList
& (1<<rN
))) valid
= False
;
20864 if (bL
== 1 && bP
== 1) {
20865 // We'll be writing the PC. Hence:
20866 /* Only allowed outside or last-in IT block; SIGILL if not so. */
20867 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
20871 mk_skip_over_T32_if_cond_is_false(condT
);
20872 condT
= IRTemp_INVALID
;
20875 /* Generate the IR. This might generate a write to R15. */
20876 mk_ldm_stm(False
/*!arm*/, rN
, bINC
, bBEFORE
, bW
, bL
, regList
);
20878 if (bL
== 1 && (regList
& (1<<15))) {
20879 // If we wrote to R15, we have an interworking return to
20881 llPutIReg(15, llGetIReg(15));
20882 dres
.jk_StopHere
= Ijk_Ret
;
20883 dres
.whatNext
= Dis_StopHere
;
20886 DIP("%sm%c%c r%u%s, {0x%04x}\n",
20887 bL
== 1 ? "ld" : "st", bINC
? 'i' : 'd', bBEFORE
? 'b' : 'a',
20888 rN
, bW
? "!" : "", regList
);
20890 goto decode_success
;
20894 /* -------------- (T3) ADD{S}.W Rd, Rn, #constT -------------- */
20895 if (INSN0(15,11) == BITS5(1,1,1,1,0)
20896 && INSN0(9,5) == BITS5(0,1,0,0,0)
20897 && INSN1(15,15) == 0) {
20898 UInt bS
= INSN0(4,4);
20899 UInt rN
= INSN0(3,0);
20900 UInt rD
= INSN1(11,8);
20901 Bool valid
= !isBadRegT(rN
) && !isBadRegT(rD
);
20902 /* but allow "add.w reg, sp, #constT" for reg != PC */
20903 if (!valid
&& rD
<= 14 && rN
== 13)
20906 IRTemp argL
= newTemp(Ity_I32
);
20907 IRTemp argR
= newTemp(Ity_I32
);
20908 IRTemp res
= newTemp(Ity_I32
);
20909 UInt imm32
= thumbExpandImm_from_I0_I1(NULL
, insn0
, insn1
);
20910 assign(argL
, getIRegT(rN
));
20911 assign(argR
, mkU32(imm32
));
20912 assign(res
, binop(Iop_Add32
, mkexpr(argL
), mkexpr(argR
)));
20913 putIRegT(rD
, mkexpr(res
), condT
);
20915 setFlags_D1_D2( ARMG_CC_OP_ADD
, argL
, argR
, condT
);
20916 DIP("add%s.w r%u, r%u, #%u\n",
20917 bS
== 1 ? "s" : "", rD
, rN
, imm32
);
20918 goto decode_success
;
20922 /* ---------------- (T4) ADDW Rd, Rn, #uimm12 -------------- */
20923 if (INSN0(15,11) == BITS5(1,1,1,1,0)
20924 && INSN0(9,4) == BITS6(1,0,0,0,0,0)
20925 && INSN1(15,15) == 0) {
20926 UInt rN
= INSN0(3,0);
20927 UInt rD
= INSN1(11,8);
20928 Bool valid
= !isBadRegT(rN
) && !isBadRegT(rD
);
20929 /* but allow "addw reg, sp, #uimm12" for reg != PC */
20930 if (!valid
&& rD
<= 14 && rN
== 13)
20933 IRTemp argL
= newTemp(Ity_I32
);
20934 IRTemp argR
= newTemp(Ity_I32
);
20935 IRTemp res
= newTemp(Ity_I32
);
20936 UInt imm12
= (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
20937 assign(argL
, getIRegT(rN
));
20938 assign(argR
, mkU32(imm12
));
20939 assign(res
, binop(Iop_Add32
, mkexpr(argL
), mkexpr(argR
)));
20940 putIRegT(rD
, mkexpr(res
), condT
);
20941 DIP("addw r%u, r%u, #%u\n", rD
, rN
, imm12
);
20942 goto decode_success
;
20946 /* ---------------- (T2) CMP.W Rn, #constT ---------------- */
20947 /* ---------------- (T2) CMN.W Rn, #constT ---------------- */
20948 if (INSN0(15,11) == BITS5(1,1,1,1,0)
20949 && ( INSN0(9,4) == BITS6(0,1,1,0,1,1) // CMP
20950 || INSN0(9,4) == BITS6(0,1,0,0,0,1)) // CMN
20951 && INSN1(15,15) == 0
20952 && INSN1(11,8) == BITS4(1,1,1,1)) {
20953 UInt rN
= INSN0(3,0);
20955 IRTemp argL
= newTemp(Ity_I32
);
20956 IRTemp argR
= newTemp(Ity_I32
);
20957 Bool isCMN
= INSN0(9,4) == BITS6(0,1,0,0,0,1);
20958 UInt imm32
= thumbExpandImm_from_I0_I1(NULL
, insn0
, insn1
);
20959 assign(argL
, getIRegT(rN
));
20960 assign(argR
, mkU32(imm32
));
20961 setFlags_D1_D2( isCMN
? ARMG_CC_OP_ADD
: ARMG_CC_OP_SUB
,
20962 argL
, argR
, condT
);
20963 DIP("%s.w r%u, #%u\n", isCMN
? "cmn" : "cmp", rN
, imm32
);
20964 goto decode_success
;
20968 /* -------------- (T1) TST.W Rn, #constT -------------- */
20969 /* -------------- (T1) TEQ.W Rn, #constT -------------- */
20970 if (INSN0(15,11) == BITS5(1,1,1,1,0)
20971 && ( INSN0(9,4) == BITS6(0,0,0,0,0,1) // TST
20972 || INSN0(9,4) == BITS6(0,0,1,0,0,1)) // TEQ
20973 && INSN1(15,15) == 0
20974 && INSN1(11,8) == BITS4(1,1,1,1)) {
20975 UInt rN
= INSN0(3,0);
20976 if (!isBadRegT(rN
)) { // yes, really, it's inconsistent with CMP.W
20977 Bool isTST
= INSN0(9,4) == BITS6(0,0,0,0,0,1);
20978 IRTemp argL
= newTemp(Ity_I32
);
20979 IRTemp argR
= newTemp(Ity_I32
);
20980 IRTemp res
= newTemp(Ity_I32
);
20981 IRTemp oldV
= newTemp(Ity_I32
);
20982 IRTemp oldC
= newTemp(Ity_I32
);
20984 UInt imm32
= thumbExpandImm_from_I0_I1(&updC
, insn0
, insn1
);
20985 assign(argL
, getIRegT(rN
));
20986 assign(argR
, mkU32(imm32
));
20987 assign(res
, binop(isTST
? Iop_And32
: Iop_Xor32
,
20988 mkexpr(argL
), mkexpr(argR
)));
20989 assign( oldV
, mk_armg_calculate_flag_v() );
20991 ? mkU32((imm32
>> 31) & 1)
20992 : mk_armg_calculate_flag_c() );
20993 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
, condT
);
20994 DIP("%s.w r%u, #%u\n", isTST
? "tst" : "teq", rN
, imm32
);
20995 goto decode_success
;
20999 /* -------------- (T3) SUB{S}.W Rd, Rn, #constT -------------- */
21000 /* -------------- (T3) RSB{S}.W Rd, Rn, #constT -------------- */
21001 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21002 && (INSN0(9,5) == BITS5(0,1,1,0,1) // SUB
21003 || INSN0(9,5) == BITS5(0,1,1,1,0)) // RSB
21004 && INSN1(15,15) == 0) {
21005 Bool isRSB
= INSN0(9,5) == BITS5(0,1,1,1,0);
21006 UInt bS
= INSN0(4,4);
21007 UInt rN
= INSN0(3,0);
21008 UInt rD
= INSN1(11,8);
21009 Bool valid
= !isBadRegT(rN
) && !isBadRegT(rD
);
21010 /* but allow "sub{s}.w reg, sp, #constT
21011 this is (T2) of "SUB (SP minus immediate)" */
21012 if (!valid
&& !isRSB
&& rN
== 13 && rD
!= 15)
21015 IRTemp argL
= newTemp(Ity_I32
);
21016 IRTemp argR
= newTemp(Ity_I32
);
21017 IRTemp res
= newTemp(Ity_I32
);
21018 UInt imm32
= thumbExpandImm_from_I0_I1(NULL
, insn0
, insn1
);
21019 assign(argL
, getIRegT(rN
));
21020 assign(argR
, mkU32(imm32
));
21022 ? binop(Iop_Sub32
, mkexpr(argR
), mkexpr(argL
))
21023 : binop(Iop_Sub32
, mkexpr(argL
), mkexpr(argR
)));
21024 putIRegT(rD
, mkexpr(res
), condT
);
21027 setFlags_D1_D2( ARMG_CC_OP_SUB
, argR
, argL
, condT
);
21029 setFlags_D1_D2( ARMG_CC_OP_SUB
, argL
, argR
, condT
);
21031 DIP("%s%s.w r%u, r%u, #%u\n",
21032 isRSB
? "rsb" : "sub", bS
== 1 ? "s" : "", rD
, rN
, imm32
);
21033 goto decode_success
;
21037 /* -------------- (T4) SUBW Rd, Rn, #uimm12 ------------------- */
21038 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21039 && INSN0(9,4) == BITS6(1,0,1,0,1,0)
21040 && INSN1(15,15) == 0) {
21041 UInt rN
= INSN0(3,0);
21042 UInt rD
= INSN1(11,8);
21043 Bool valid
= !isBadRegT(rN
) && !isBadRegT(rD
);
21044 /* but allow "subw sp, sp, #uimm12" */
21045 if (!valid
&& rD
== 13 && rN
== 13)
21048 IRTemp argL
= newTemp(Ity_I32
);
21049 IRTemp argR
= newTemp(Ity_I32
);
21050 IRTemp res
= newTemp(Ity_I32
);
21051 UInt imm12
= (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
21052 assign(argL
, getIRegT(rN
));
21053 assign(argR
, mkU32(imm12
));
21054 assign(res
, binop(Iop_Sub32
, mkexpr(argL
), mkexpr(argR
)));
21055 putIRegT(rD
, mkexpr(res
), condT
);
21056 DIP("subw r%u, r%u, #%u\n", rD
, rN
, imm12
);
21057 goto decode_success
;
21061 /* -------------- (T1) ADC{S}.W Rd, Rn, #constT -------------- */
21062 /* -------------- (T1) SBC{S}.W Rd, Rn, #constT -------------- */
21063 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21064 && ( INSN0(9,5) == BITS5(0,1,0,1,0) // ADC
21065 || INSN0(9,5) == BITS5(0,1,0,1,1)) // SBC
21066 && INSN1(15,15) == 0) {
21067 /* ADC: Rd = Rn + constT + oldC */
21068 /* SBC: Rd = Rn - constT - (oldC ^ 1) */
21069 UInt bS
= INSN0(4,4);
21070 UInt rN
= INSN0(3,0);
21071 UInt rD
= INSN1(11,8);
21072 if (!isBadRegT(rN
) && !isBadRegT(rD
)) {
21073 IRTemp argL
= newTemp(Ity_I32
);
21074 IRTemp argR
= newTemp(Ity_I32
);
21075 IRTemp res
= newTemp(Ity_I32
);
21076 IRTemp oldC
= newTemp(Ity_I32
);
21077 UInt imm32
= thumbExpandImm_from_I0_I1(NULL
, insn0
, insn1
);
21078 assign(argL
, getIRegT(rN
));
21079 assign(argR
, mkU32(imm32
));
21080 assign(oldC
, mk_armg_calculate_flag_c() );
21081 const HChar
* nm
= "???";
21082 switch (INSN0(9,5)) {
21083 case BITS5(0,1,0,1,0): // ADC
21087 binop(Iop_Add32
, mkexpr(argL
), mkexpr(argR
)),
21089 putIRegT(rD
, mkexpr(res
), condT
);
21091 setFlags_D1_D2_ND( ARMG_CC_OP_ADC
,
21092 argL
, argR
, oldC
, condT
);
21094 case BITS5(0,1,0,1,1): // SBC
21098 binop(Iop_Sub32
, mkexpr(argL
), mkexpr(argR
)),
21099 binop(Iop_Xor32
, mkexpr(oldC
), mkU32(1)) ));
21100 putIRegT(rD
, mkexpr(res
), condT
);
21102 setFlags_D1_D2_ND( ARMG_CC_OP_SBB
,
21103 argL
, argR
, oldC
, condT
);
21108 DIP("%s%s.w r%u, r%u, #%u\n",
21109 nm
, bS
== 1 ? "s" : "", rD
, rN
, imm32
);
21110 goto decode_success
;
21114 /* -------------- (T1) ORR{S}.W Rd, Rn, #constT -------------- */
21115 /* -------------- (T1) AND{S}.W Rd, Rn, #constT -------------- */
21116 /* -------------- (T1) BIC{S}.W Rd, Rn, #constT -------------- */
21117 /* -------------- (T1) EOR{S}.W Rd, Rn, #constT -------------- */
21118 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21119 && ( INSN0(9,5) == BITS5(0,0,0,1,0) // ORR
21120 || INSN0(9,5) == BITS5(0,0,0,0,0) // AND
21121 || INSN0(9,5) == BITS5(0,0,0,0,1) // BIC
21122 || INSN0(9,5) == BITS5(0,0,1,0,0) // EOR
21123 || INSN0(9,5) == BITS5(0,0,0,1,1)) // ORN
21124 && INSN1(15,15) == 0) {
21125 UInt bS
= INSN0(4,4);
21126 UInt rN
= INSN0(3,0);
21127 UInt rD
= INSN1(11,8);
21128 if (!isBadRegT(rN
) && !isBadRegT(rD
)) {
21129 Bool notArgR
= False
;
21130 IROp op
= Iop_INVALID
;
21131 const HChar
* nm
= "???";
21132 switch (INSN0(9,5)) {
21133 case BITS5(0,0,0,1,0): op
= Iop_Or32
; nm
= "orr"; break;
21134 case BITS5(0,0,0,0,0): op
= Iop_And32
; nm
= "and"; break;
21135 case BITS5(0,0,0,0,1): op
= Iop_And32
; nm
= "bic";
21136 notArgR
= True
; break;
21137 case BITS5(0,0,1,0,0): op
= Iop_Xor32
; nm
= "eor"; break;
21138 case BITS5(0,0,0,1,1): op
= Iop_Or32
; nm
= "orn";
21139 notArgR
= True
; break;
21140 default: vassert(0);
21142 IRTemp argL
= newTemp(Ity_I32
);
21143 IRTemp argR
= newTemp(Ity_I32
);
21144 IRTemp res
= newTemp(Ity_I32
);
21146 UInt imm32
= thumbExpandImm_from_I0_I1(&updC
, insn0
, insn1
);
21147 assign(argL
, getIRegT(rN
));
21148 assign(argR
, mkU32(notArgR
? ~imm32
: imm32
));
21149 assign(res
, binop(op
, mkexpr(argL
), mkexpr(argR
)));
21150 putIRegT(rD
, mkexpr(res
), condT
);
21152 IRTemp oldV
= newTemp(Ity_I32
);
21153 IRTemp oldC
= newTemp(Ity_I32
);
21154 assign( oldV
, mk_armg_calculate_flag_v() );
21156 ? mkU32((imm32
>> 31) & 1)
21157 : mk_armg_calculate_flag_c() );
21158 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
21161 DIP("%s%s.w r%u, r%u, #%u\n",
21162 nm
, bS
== 1 ? "s" : "", rD
, rN
, imm32
);
21163 goto decode_success
;
21167 /* ---------- (T3) ADD{S}.W Rd, Rn, Rm, {shift} ---------- */
21168 /* ---------- (T3) SUB{S}.W Rd, Rn, Rm, {shift} ---------- */
21169 /* ---------- (T3) RSB{S}.W Rd, Rn, Rm, {shift} ---------- */
21170 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
21171 && ( INSN0(8,5) == BITS4(1,0,0,0) // add subopc
21172 || INSN0(8,5) == BITS4(1,1,0,1) // sub subopc
21173 || INSN0(8,5) == BITS4(1,1,1,0)) // rsb subopc
21174 && INSN1(15,15) == 0) {
21175 UInt rN
= INSN0(3,0);
21176 UInt rD
= INSN1(11,8);
21177 UInt rM
= INSN1(3,0);
21178 UInt bS
= INSN0(4,4);
21179 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21180 UInt how
= INSN1(5,4);
21182 Bool valid
= !isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
);
21183 /* but allow "add.w reg, sp, reg, lsl #N for N=0..31
21184 (T3) "ADD (SP plus register) */
21185 if (!valid
&& INSN0(8,5) == BITS4(1,0,0,0) // add
21186 && rD
!= 15 && rN
== 13 && imm5
<= 31 && how
== 0) {
21189 /* also allow "sub.w reg, sp, reg lsl #N for N=0 .. 5
21190 (T1) "SUB (SP minus register) */
21191 if (!valid
&& INSN0(8,5) == BITS4(1,1,0,1) // sub
21192 && rD
!= 15 && rN
== 13 && imm5
<= 5 && how
== 0) {
21197 IROp op
= Iop_INVALID
;
21198 const HChar
* nm
= "???";
21199 switch (INSN0(8,5)) {
21200 case BITS4(1,0,0,0): op
= Iop_Add32
; nm
= "add"; break;
21201 case BITS4(1,1,0,1): op
= Iop_Sub32
; nm
= "sub"; break;
21202 case BITS4(1,1,1,0): op
= Iop_Sub32
; nm
= "rsb";
21203 swap
= True
; break;
21204 default: vassert(0);
21207 IRTemp argL
= newTemp(Ity_I32
);
21208 assign(argL
, getIRegT(rN
));
21210 IRTemp rMt
= newTemp(Ity_I32
);
21211 assign(rMt
, getIRegT(rM
));
21213 IRTemp argR
= newTemp(Ity_I32
);
21214 compute_result_and_C_after_shift_by_imm5(
21215 dis_buf
, &argR
, NULL
, rMt
, how
, imm5
, rM
21218 IRTemp res
= newTemp(Ity_I32
);
21220 ? binop(op
, mkexpr(argR
), mkexpr(argL
))
21221 : binop(op
, mkexpr(argL
), mkexpr(argR
)));
21223 putIRegT(rD
, mkexpr(res
), condT
);
21227 setFlags_D1_D2( ARMG_CC_OP_ADD
, argL
, argR
, condT
);
21231 setFlags_D1_D2( ARMG_CC_OP_SUB
, argR
, argL
, condT
);
21233 setFlags_D1_D2( ARMG_CC_OP_SUB
, argL
, argR
, condT
);
21240 DIP("%s%s.w r%u, r%u, %s\n",
21241 nm
, bS
? "s" : "", rD
, rN
, dis_buf
);
21242 goto decode_success
;
21246 /* ---------- (T3) ADC{S}.W Rd, Rn, Rm, {shift} ---------- */
21247 /* ---------- (T2) SBC{S}.W Rd, Rn, Rm, {shift} ---------- */
21248 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
21249 && ( INSN0(8,5) == BITS4(1,0,1,0) // adc subopc
21250 || INSN0(8,5) == BITS4(1,0,1,1)) // sbc subopc
21251 && INSN1(15,15) == 0) {
21252 /* ADC: Rd = Rn + shifter_operand + oldC */
21253 /* SBC: Rd = Rn - shifter_operand - (oldC ^ 1) */
21254 UInt rN
= INSN0(3,0);
21255 UInt rD
= INSN1(11,8);
21256 UInt rM
= INSN1(3,0);
21257 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
21258 UInt bS
= INSN0(4,4);
21259 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21260 UInt how
= INSN1(5,4);
21262 IRTemp argL
= newTemp(Ity_I32
);
21263 assign(argL
, getIRegT(rN
));
21265 IRTemp rMt
= newTemp(Ity_I32
);
21266 assign(rMt
, getIRegT(rM
));
21268 IRTemp oldC
= newTemp(Ity_I32
);
21269 assign(oldC
, mk_armg_calculate_flag_c());
21271 IRTemp argR
= newTemp(Ity_I32
);
21272 compute_result_and_C_after_shift_by_imm5(
21273 dis_buf
, &argR
, NULL
, rMt
, how
, imm5
, rM
21276 const HChar
* nm
= "???";
21277 IRTemp res
= newTemp(Ity_I32
);
21278 switch (INSN0(8,5)) {
21279 case BITS4(1,0,1,0): // ADC
21283 binop(Iop_Add32
, mkexpr(argL
), mkexpr(argR
)),
21285 putIRegT(rD
, mkexpr(res
), condT
);
21287 setFlags_D1_D2_ND( ARMG_CC_OP_ADC
,
21288 argL
, argR
, oldC
, condT
);
21290 case BITS4(1,0,1,1): // SBC
21294 binop(Iop_Sub32
, mkexpr(argL
), mkexpr(argR
)),
21295 binop(Iop_Xor32
, mkexpr(oldC
), mkU32(1)) ));
21296 putIRegT(rD
, mkexpr(res
), condT
);
21298 setFlags_D1_D2_ND( ARMG_CC_OP_SBB
,
21299 argL
, argR
, oldC
, condT
);
21305 DIP("%s%s.w r%u, r%u, %s\n",
21306 nm
, bS
? "s" : "", rD
, rN
, dis_buf
);
21307 goto decode_success
;
21311 /* ---------- (T3) AND{S}.W Rd, Rn, Rm, {shift} ---------- */
21312 /* ---------- (T3) ORR{S}.W Rd, Rn, Rm, {shift} ---------- */
21313 /* ---------- (T3) EOR{S}.W Rd, Rn, Rm, {shift} ---------- */
21314 /* ---------- (T3) BIC{S}.W Rd, Rn, Rm, {shift} ---------- */
21315 /* ---------- (T1) ORN{S}.W Rd, Rn, Rm, {shift} ---------- */
21316 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
21317 && ( INSN0(8,5) == BITS4(0,0,0,0) // and subopc
21318 || INSN0(8,5) == BITS4(0,0,1,0) // orr subopc
21319 || INSN0(8,5) == BITS4(0,1,0,0) // eor subopc
21320 || INSN0(8,5) == BITS4(0,0,0,1) // bic subopc
21321 || INSN0(8,5) == BITS4(0,0,1,1)) // orn subopc
21322 && INSN1(15,15) == 0) {
21323 UInt rN
= INSN0(3,0);
21324 UInt rD
= INSN1(11,8);
21325 UInt rM
= INSN1(3,0);
21326 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
21327 Bool notArgR
= False
;
21328 IROp op
= Iop_INVALID
;
21329 const HChar
* nm
= "???";
21330 switch (INSN0(8,5)) {
21331 case BITS4(0,0,0,0): op
= Iop_And32
; nm
= "and"; break;
21332 case BITS4(0,0,1,0): op
= Iop_Or32
; nm
= "orr"; break;
21333 case BITS4(0,1,0,0): op
= Iop_Xor32
; nm
= "eor"; break;
21334 case BITS4(0,0,0,1): op
= Iop_And32
; nm
= "bic";
21335 notArgR
= True
; break;
21336 case BITS4(0,0,1,1): op
= Iop_Or32
; nm
= "orn";
21337 notArgR
= True
; break;
21338 default: vassert(0);
21340 UInt bS
= INSN0(4,4);
21341 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21342 UInt how
= INSN1(5,4);
21344 IRTemp rNt
= newTemp(Ity_I32
);
21345 assign(rNt
, getIRegT(rN
));
21347 IRTemp rMt
= newTemp(Ity_I32
);
21348 assign(rMt
, getIRegT(rM
));
21350 IRTemp argR
= newTemp(Ity_I32
);
21351 IRTemp oldC
= bS
? newTemp(Ity_I32
) : IRTemp_INVALID
;
21353 compute_result_and_C_after_shift_by_imm5(
21354 dis_buf
, &argR
, bS
? &oldC
: NULL
, rMt
, how
, imm5
, rM
21357 IRTemp res
= newTemp(Ity_I32
);
21359 vassert(op
== Iop_And32
|| op
== Iop_Or32
);
21360 assign(res
, binop(op
, mkexpr(rNt
),
21361 unop(Iop_Not32
, mkexpr(argR
))));
21363 assign(res
, binop(op
, mkexpr(rNt
), mkexpr(argR
)));
21366 putIRegT(rD
, mkexpr(res
), condT
);
21368 IRTemp oldV
= newTemp(Ity_I32
);
21369 assign( oldV
, mk_armg_calculate_flag_v() );
21370 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
21374 DIP("%s%s.w r%u, r%u, %s\n",
21375 nm
, bS
? "s" : "", rD
, rN
, dis_buf
);
21376 goto decode_success
;
21380 /* -------------- (T?) LSL{S}.W Rd, Rn, Rm -------------- */
21381 /* -------------- (T?) LSR{S}.W Rd, Rn, Rm -------------- */
21382 /* -------------- (T?) ASR{S}.W Rd, Rn, Rm -------------- */
21383 /* -------------- (T?) ROR{S}.W Rd, Rn, Rm -------------- */
21384 if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,0,0)
21385 && INSN1(15,12) == BITS4(1,1,1,1)
21386 && INSN1(7,4) == BITS4(0,0,0,0)) {
21387 UInt how
= INSN0(6,5); // standard encoding
21388 UInt rN
= INSN0(3,0);
21389 UInt rD
= INSN1(11,8);
21390 UInt rM
= INSN1(3,0);
21391 UInt bS
= INSN0(4,4);
21392 Bool valid
= !isBadRegT(rN
) && !isBadRegT(rM
) && !isBadRegT(rD
);
21394 IRTemp rNt
= newTemp(Ity_I32
);
21395 IRTemp rMt
= newTemp(Ity_I32
);
21396 IRTemp res
= newTemp(Ity_I32
);
21397 IRTemp oldC
= bS
? newTemp(Ity_I32
) : IRTemp_INVALID
;
21398 IRTemp oldV
= bS
? newTemp(Ity_I32
) : IRTemp_INVALID
;
21399 const HChar
* nms
[4] = { "lsl", "lsr", "asr", "ror" };
21400 const HChar
* nm
= nms
[how
];
21401 assign(rNt
, getIRegT(rN
));
21402 assign(rMt
, getIRegT(rM
));
21403 compute_result_and_C_after_shift_by_reg(
21404 dis_buf
, &res
, bS
? &oldC
: NULL
,
21405 rNt
, how
, rMt
, rN
, rM
21408 assign(oldV
, mk_armg_calculate_flag_v());
21409 putIRegT(rD
, mkexpr(res
), condT
);
21411 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
21414 DIP("%s%s.w r%u, r%u, r%u\n",
21415 nm
, bS
? "s" : "", rD
, rN
, rM
);
21416 goto decode_success
;
21420 /* ------------ (T?) MOV{S}.W Rd, Rn, {shift} ------------ */
21421 /* ------------ (T?) MVN{S}.W Rd, Rn, {shift} ------------ */
21422 if ((INSN0(15,0) & 0xFFCF) == 0xEA4F
21423 && INSN1(15,15) == 0) {
21424 UInt rD
= INSN1(11,8);
21425 UInt rN
= INSN1(3,0);
21426 UInt bS
= INSN0(4,4);
21427 UInt isMVN
= INSN0(5,5);
21428 Bool regsOK
= (bS
|| isMVN
)
21429 ? (!isBadRegT(rD
) && !isBadRegT(rN
))
21430 : (rD
!= 15 && rN
!= 15 && (rD
!= 13 || rN
!= 13));
21432 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21433 UInt how
= INSN1(5,4);
21435 IRTemp rNt
= newTemp(Ity_I32
);
21436 assign(rNt
, getIRegT(rN
));
21438 IRTemp oldRn
= newTemp(Ity_I32
);
21439 IRTemp oldC
= bS
? newTemp(Ity_I32
) : IRTemp_INVALID
;
21440 compute_result_and_C_after_shift_by_imm5(
21441 dis_buf
, &oldRn
, bS
? &oldC
: NULL
, rNt
, how
, imm5
, rN
21444 IRTemp res
= newTemp(Ity_I32
);
21445 assign(res
, isMVN
? unop(Iop_Not32
, mkexpr(oldRn
))
21448 putIRegT(rD
, mkexpr(res
), condT
);
21450 IRTemp oldV
= newTemp(Ity_I32
);
21451 assign( oldV
, mk_armg_calculate_flag_v() );
21452 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
, condT
);
21454 DIP("%s%s.w r%u, %s\n",
21455 isMVN
? "mvn" : "mov", bS
? "s" : "", rD
, dis_buf
);
21456 goto decode_success
;
21460 /* -------------- (T?) TST.W Rn, Rm, {shift} -------------- */
21461 /* -------------- (T?) TEQ.W Rn, Rm, {shift} -------------- */
21462 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
21463 && ( INSN0(8,4) == BITS5(0,0,0,0,1) // TST
21464 || INSN0(8,4) == BITS5(0,1,0,0,1)) // TEQ
21465 && INSN1(15,15) == 0
21466 && INSN1(11,8) == BITS4(1,1,1,1)) {
21467 UInt rN
= INSN0(3,0);
21468 UInt rM
= INSN1(3,0);
21469 if (!isBadRegT(rN
) && !isBadRegT(rM
)) {
21470 Bool isTST
= INSN0(8,4) == BITS5(0,0,0,0,1);
21472 UInt how
= INSN1(5,4);
21473 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21475 IRTemp argL
= newTemp(Ity_I32
);
21476 assign(argL
, getIRegT(rN
));
21478 IRTemp rMt
= newTemp(Ity_I32
);
21479 assign(rMt
, getIRegT(rM
));
21481 IRTemp argR
= newTemp(Ity_I32
);
21482 IRTemp oldC
= newTemp(Ity_I32
);
21483 compute_result_and_C_after_shift_by_imm5(
21484 dis_buf
, &argR
, &oldC
, rMt
, how
, imm5
, rM
21487 IRTemp oldV
= newTemp(Ity_I32
);
21488 assign( oldV
, mk_armg_calculate_flag_v() );
21490 IRTemp res
= newTemp(Ity_I32
);
21491 assign(res
, binop(isTST
? Iop_And32
: Iop_Xor32
,
21492 mkexpr(argL
), mkexpr(argR
)));
21494 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
21496 DIP("%s.w r%u, %s\n", isTST
? "tst" : "teq", rN
, dis_buf
);
21497 goto decode_success
;
21501 /* -------------- (T3) CMP.W Rn, Rm, {shift} -------------- */
21502 /* -------------- (T2) CMN.W Rn, Rm, {shift} -------------- */
21503 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
21504 && ( INSN0(8,4) == BITS5(1,1,0,1,1) // CMP
21505 || INSN0(8,4) == BITS5(1,0,0,0,1)) // CMN
21506 && INSN1(15,15) == 0
21507 && INSN1(11,8) == BITS4(1,1,1,1)) {
21508 UInt rN
= INSN0(3,0);
21509 UInt rM
= INSN1(3,0);
21510 if (!isBadRegT(rN
) && !isBadRegT(rM
)) {
21511 Bool isCMN
= INSN0(8,4) == BITS5(1,0,0,0,1);
21512 UInt how
= INSN1(5,4);
21513 UInt imm5
= (INSN1(14,12) << 2) | INSN1(7,6);
21515 IRTemp argL
= newTemp(Ity_I32
);
21516 assign(argL
, getIRegT(rN
));
21518 IRTemp rMt
= newTemp(Ity_I32
);
21519 assign(rMt
, getIRegT(rM
));
21521 IRTemp argR
= newTemp(Ity_I32
);
21522 compute_result_and_C_after_shift_by_imm5(
21523 dis_buf
, &argR
, NULL
, rMt
, how
, imm5
, rM
21526 setFlags_D1_D2( isCMN
? ARMG_CC_OP_ADD
: ARMG_CC_OP_SUB
,
21527 argL
, argR
, condT
);
21529 DIP("%s.w r%u, %s\n", isCMN
? "cmn" : "cmp", rN
, dis_buf
);
21530 goto decode_success
;
21534 /* -------------- (T2) MOV{S}.W Rd, #constT -------------- */
21535 /* -------------- (T2) MVN{S}.W Rd, #constT -------------- */
21536 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21537 && ( INSN0(9,5) == BITS5(0,0,0,1,0) // MOV
21538 || INSN0(9,5) == BITS5(0,0,0,1,1)) // MVN
21539 && INSN0(3,0) == BITS4(1,1,1,1)
21540 && INSN1(15,15) == 0) {
21541 UInt rD
= INSN1(11,8);
21542 if (!isBadRegT(rD
)) {
21544 UInt bS
= INSN0(4,4);
21545 Bool isMVN
= INSN0(5,5) == 1;
21546 UInt imm32
= thumbExpandImm_from_I0_I1(&updC
, insn0
, insn1
);
21547 IRTemp res
= newTemp(Ity_I32
);
21548 assign(res
, mkU32(isMVN
? ~imm32
: imm32
));
21549 putIRegT(rD
, mkexpr(res
), condT
);
21551 IRTemp oldV
= newTemp(Ity_I32
);
21552 IRTemp oldC
= newTemp(Ity_I32
);
21553 assign( oldV
, mk_armg_calculate_flag_v() );
21555 ? mkU32((imm32
>> 31) & 1)
21556 : mk_armg_calculate_flag_c() );
21557 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC
, res
, oldC
, oldV
,
21560 DIP("%s%s.w r%u, #%u\n",
21561 isMVN
? "mvn" : "mov", bS
? "s" : "", rD
, imm32
);
21562 goto decode_success
;
21566 /* -------------- (T3) MOVW Rd, #imm16 -------------- */
21567 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21568 && INSN0(9,4) == BITS6(1,0,0,1,0,0)
21569 && INSN1(15,15) == 0) {
21570 UInt rD
= INSN1(11,8);
21571 if (!isBadRegT(rD
)) {
21572 UInt imm16
= (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
21573 | (INSN1(14,12) << 8) | INSN1(7,0);
21574 putIRegT(rD
, mkU32(imm16
), condT
);
21575 DIP("movw r%u, #%u\n", rD
, imm16
);
21576 goto decode_success
;
21580 /* ---------------- MOVT Rd, #imm16 ---------------- */
21581 if (INSN0(15,11) == BITS5(1,1,1,1,0)
21582 && INSN0(9,4) == BITS6(1,0,1,1,0,0)
21583 && INSN1(15,15) == 0) {
21584 UInt rD
= INSN1(11,8);
21585 if (!isBadRegT(rD
)) {
21586 UInt imm16
= (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
21587 | (INSN1(14,12) << 8) | INSN1(7,0);
21588 IRTemp res
= newTemp(Ity_I32
);
21591 binop(Iop_And32
, getIRegT(rD
), mkU32(0xFFFF)),
21592 mkU32(imm16
<< 16)));
21593 putIRegT(rD
, mkexpr(res
), condT
);
21594 DIP("movt r%u, #%u\n", rD
, imm16
);
21595 goto decode_success
;
21599 /* ---------------- LD/ST reg+/-#imm8 ---------------- */
21600 /* Loads and stores of the form:
21601 op Rt, [Rn, #-imm8] or
21602 op Rt, [Rn], #+/-imm8 or
21603 op Rt, [Rn, #+/-imm8]!
21605 ldrb ldrh ldr ldrsb ldrsh
21608 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) && INSN1(11,11) == 1) {
21610 Bool syned
= False
;
21612 IRType ty
= Ity_I8
;
21613 const HChar
* nm
= "???";
21615 switch (INSN0(8,4)) {
21616 case BITS5(0,0,0,0,0): // strb
21617 nm
= "strb"; isST
= True
; break;
21618 case BITS5(0,0,0,0,1): // ldrb
21619 nm
= "ldrb"; break;
21620 case BITS5(1,0,0,0,1): // ldrsb
21621 nm
= "ldrsb"; syned
= True
; break;
21622 case BITS5(0,0,0,1,0): // strh
21623 nm
= "strh"; ty
= Ity_I16
; isST
= True
; break;
21624 case BITS5(0,0,0,1,1): // ldrh
21625 nm
= "ldrh"; ty
= Ity_I16
; break;
21626 case BITS5(1,0,0,1,1): // ldrsh
21627 nm
= "ldrsh"; ty
= Ity_I16
; syned
= True
; break;
21628 case BITS5(0,0,1,0,0): // str
21629 nm
= "str"; ty
= Ity_I32
; isST
= True
; break;
21630 case BITS5(0,0,1,0,1):
21631 nm
= "ldr"; ty
= Ity_I32
; break; // ldr
21633 valid
= False
; break;
21636 UInt rN
= INSN0(3,0);
21637 UInt rT
= INSN1(15,12);
21638 UInt bP
= INSN1(10,10);
21639 UInt bU
= INSN1(9,9);
21640 UInt bW
= INSN1(8,8);
21641 UInt imm8
= INSN1(7,0);
21642 Bool loadsPC
= False
;
21645 if (bP
== 1 && bU
== 1 && bW
== 0)
21647 if (bP
== 0 && bW
== 0)
21651 if (bW
== 1 && rN
== rT
)
21653 if (ty
== Ity_I8
|| ty
== Ity_I16
) {
21657 /* ty == Ity_I32 */
21658 if (isST
&& rT
== 15)
21660 if (!isST
&& rT
== 15)
21666 // if it's a branch, it can't happen in the middle of an IT block
21667 // Also, if it is a branch, make it unconditional at this point.
21668 // Doing conditional branches in-line is too complex (for now)
21670 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
21672 mk_skip_over_T32_if_cond_is_false(condT
);
21673 condT
= IRTemp_INVALID
;
21677 IRTemp preAddr
= newTemp(Ity_I32
);
21678 assign(preAddr
, getIRegT(rN
));
21680 IRTemp postAddr
= newTemp(Ity_I32
);
21681 assign(postAddr
, binop(bU
== 1 ? Iop_Add32
: Iop_Sub32
,
21682 mkexpr(preAddr
), mkU32(imm8
)));
21684 IRTemp transAddr
= bP
== 1 ? postAddr
: preAddr
;
21688 /* Store. If necessary, update the base register before
21689 the store itself, so that the common idiom of "str rX,
21690 [sp, #-4]!" (store rX at sp-4, then do new sp = sp-4,
21691 a.k.a "push rX") doesn't cause Memcheck to complain
21692 that the access is below the stack pointer. Also, not
21693 updating sp before the store confuses Valgrind's
21694 dynamic stack-extending logic. So do it before the
21695 store. Hence we need to snarf the store data before
21696 doing the basereg update. */
21698 /* get hold of the data to be stored */
21699 IRTemp oldRt
= newTemp(Ity_I32
);
21700 assign(oldRt
, getIRegT(rT
));
21702 /* Update Rn if necessary. */
21704 vassert(rN
!= rT
); // assured by validity check above
21705 putIRegT(rN
, mkexpr(postAddr
), condT
);
21708 /* generate the transfer */
21709 IRExpr
* data
= NULL
;
21712 data
= unop(Iop_32to8
, mkexpr(oldRt
));
21715 data
= unop(Iop_32to16
, mkexpr(oldRt
));
21718 data
= mkexpr(oldRt
);
21723 storeGuardedLE(mkexpr(transAddr
), data
, condT
);
21728 IRTemp llOldRt
= newTemp(Ity_I32
);
21729 assign(llOldRt
, llGetIReg(rT
));
21731 /* generate the transfer */
21732 IRTemp newRt
= newTemp(Ity_I32
);
21733 IRLoadGOp widen
= ILGop_INVALID
;
21736 widen
= syned
? ILGop_8Sto32
: ILGop_8Uto32
; break;
21738 widen
= syned
? ILGop_16Sto32
: ILGop_16Uto32
; break;
21740 widen
= ILGop_Ident32
; break;
21744 loadGuardedLE(newRt
, widen
,
21745 mkexpr(transAddr
), mkexpr(llOldRt
), condT
);
21748 /* We'll do the write to the PC just below */
21751 /* IRTemp_INVALID is OK here because in the case where
21752 condT is false at run time, we're just putting the
21753 old rT value back. */
21754 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
21757 /* Update Rn if necessary. */
21759 vassert(rN
!= rT
); // assured by validity check above
21760 putIRegT(rN
, mkexpr(postAddr
), condT
);
21764 /* Presumably this is an interworking branch. */
21765 vassert(rN
!= 15); // assured by validity check above
21767 vassert(condT
== IRTemp_INVALID
); /* due to check above */
21768 llPutIReg(15, mkexpr(newRt
));
21769 dres
.jk_StopHere
= Ijk_Boring
; /* or _Ret ? */
21770 dres
.whatNext
= Dis_StopHere
;
21774 if (bP
== 1 && bW
== 0) {
21775 DIP("%s.w r%u, [r%u, #%c%u]\n",
21776 nm
, rT
, rN
, bU
? '+' : '-', imm8
);
21778 else if (bP
== 1 && bW
== 1) {
21779 DIP("%s.w r%u, [r%u, #%c%u]!\n",
21780 nm
, rT
, rN
, bU
? '+' : '-', imm8
);
21783 vassert(bP
== 0 && bW
== 1);
21784 DIP("%s.w r%u, [r%u], #%c%u\n",
21785 nm
, rT
, rN
, bU
? '+' : '-', imm8
);
21788 goto decode_success
;
21792 /* ------------- LD/ST reg+(reg<<imm2) ------------- */
21793 /* Loads and stores of the form:
21794 op Rt, [Rn, Rm, LSL #imm8]
21796 ldrb ldrh ldr ldrsb ldrsh
21799 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)
21800 && INSN1(11,6) == BITS6(0,0,0,0,0,0)) {
21802 Bool syned
= False
;
21804 IRType ty
= Ity_I8
;
21805 const HChar
* nm
= "???";
21807 switch (INSN0(8,4)) {
21808 case BITS5(0,0,0,0,0): // strb
21809 nm
= "strb"; isST
= True
; break;
21810 case BITS5(0,0,0,0,1): // ldrb
21811 nm
= "ldrb"; break;
21812 case BITS5(1,0,0,0,1): // ldrsb
21813 nm
= "ldrsb"; syned
= True
; break;
21814 case BITS5(0,0,0,1,0): // strh
21815 nm
= "strh"; ty
= Ity_I16
; isST
= True
; break;
21816 case BITS5(0,0,0,1,1): // ldrh
21817 nm
= "ldrh"; ty
= Ity_I16
; break;
21818 case BITS5(1,0,0,1,1): // ldrsh
21819 nm
= "ldrsh"; ty
= Ity_I16
; syned
= True
; break;
21820 case BITS5(0,0,1,0,0): // str
21821 nm
= "str"; ty
= Ity_I32
; isST
= True
; break;
21822 case BITS5(0,0,1,0,1):
21823 nm
= "ldr"; ty
= Ity_I32
; break; // ldr
21825 valid
= False
; break;
21828 UInt rN
= INSN0(3,0);
21829 UInt rM
= INSN1(3,0);
21830 UInt rT
= INSN1(15,12);
21831 UInt imm2
= INSN1(5,4);
21832 Bool loadsPC
= False
;
21834 if (ty
== Ity_I8
|| ty
== Ity_I16
) {
21835 /* all 8- and 16-bit load and store cases have the
21836 same exclusion set. */
21837 if (rN
== 15 || isBadRegT(rT
) || isBadRegT(rM
))
21840 vassert(ty
== Ity_I32
);
21841 if (rN
== 15 || isBadRegT(rM
))
21843 if (isST
&& rT
== 15)
21845 /* If it is a load and rT is 15, that's only allowable if we
21846 not in an IT block, or are the last in it. Need to insert
21847 a dynamic check for that. */
21848 if (!isST
&& rT
== 15)
21853 // if it's a branch, it can't happen in the middle of an IT block
21854 // Also, if it is a branch, make it unconditional at this point.
21855 // Doing conditional branches in-line is too complex (for now)
21857 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
21859 mk_skip_over_T32_if_cond_is_false(condT
);
21860 condT
= IRTemp_INVALID
;
21864 IRTemp transAddr
= newTemp(Ity_I32
);
21868 binop(Iop_Shl32
, getIRegT(rM
), mkU8(imm2
)) ));
21872 /* get hold of the data to be stored */
21873 IRTemp oldRt
= newTemp(Ity_I32
);
21874 assign(oldRt
, getIRegT(rT
));
21876 /* generate the transfer */
21877 IRExpr
* data
= NULL
;
21880 data
= unop(Iop_32to8
, mkexpr(oldRt
));
21883 data
= unop(Iop_32to16
, mkexpr(oldRt
));
21886 data
= mkexpr(oldRt
);
21891 storeGuardedLE(mkexpr(transAddr
), data
, condT
);
21896 IRTemp llOldRt
= newTemp(Ity_I32
);
21897 assign(llOldRt
, llGetIReg(rT
));
21899 /* generate the transfer */
21900 IRTemp newRt
= newTemp(Ity_I32
);
21901 IRLoadGOp widen
= ILGop_INVALID
;
21904 widen
= syned
? ILGop_8Sto32
: ILGop_8Uto32
; break;
21906 widen
= syned
? ILGop_16Sto32
: ILGop_16Uto32
; break;
21908 widen
= ILGop_Ident32
; break;
21912 loadGuardedLE(newRt
, widen
,
21913 mkexpr(transAddr
), mkexpr(llOldRt
), condT
);
21917 /* We'll do the write to the PC just below */
21920 /* IRTemp_INVALID is OK here because in the case where
21921 condT is false at run time, we're just putting the
21922 old rT value back. */
21923 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
21927 /* Presumably this is an interworking branch. */
21928 vassert(rN
!= 15); // assured by validity check above
21930 vassert(condT
== IRTemp_INVALID
); /* due to check above */
21931 llPutIReg(15, mkexpr(newRt
));
21932 dres
.jk_StopHere
= Ijk_Boring
; /* or _Ret ? */
21933 dres
.whatNext
= Dis_StopHere
;
21937 DIP("%s.w r%u, [r%u, r%u, LSL #%u]\n",
21938 nm
, rT
, rN
, rM
, imm2
);
21940 goto decode_success
;
21944 /* --------------- LD/ST reg+imm12 --------------- */
21945 /* Loads and stores of the form:
21946 op Rt, [Rn, #+-imm12]
21948 ldrb ldrh ldr ldrsb ldrsh
21951 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)) {
21953 Bool syned
= INSN0(8,8) == 1;
21955 IRType ty
= Ity_I8
;
21956 UInt bU
= INSN0(7,7); // 1: +imm 0: -imm
21957 // -imm is only supported by literal versions
21958 const HChar
* nm
= "???";
21960 switch (INSN0(6,4)) {
21961 case BITS3(0,0,0): // strb
21962 nm
= "strb"; isST
= True
; break;
21963 case BITS3(0,0,1): // ldrb
21964 nm
= syned
? "ldrsb" : "ldrb"; break;
21965 case BITS3(0,1,0): // strh
21966 nm
= "strh"; ty
= Ity_I16
; isST
= True
; break;
21967 case BITS3(0,1,1): // ldrh
21968 nm
= syned
? "ldrsh" : "ldrh"; ty
= Ity_I16
; break;
21969 case BITS3(1,0,0): // str
21970 nm
= "str"; ty
= Ity_I32
; isST
= True
; break;
21972 nm
= "ldr"; ty
= Ity_I32
; break; // ldr
21974 valid
= False
; break;
21977 UInt rN
= INSN0(3,0);
21978 UInt rT
= INSN1(15,12);
21979 UInt imm12
= INSN1(11,0);
21980 Bool loadsPC
= False
;
21982 if (rN
!= 15 && bU
== 0) {
21983 // only pc supports #-imm12
21988 if (syned
) valid
= False
;
21989 if (rN
== 15 || rT
== 15)
21992 /* For a 32-bit load, rT == 15 is only allowable if we are not
21993 in an IT block, or are the last in it. Need to insert
21994 a dynamic check for that. Also, in this particular
21995 case, rN == 15 is allowable. In this case however, the
21996 value obtained for rN is (apparently)
21997 "word-align(address of current insn + 4)". */
22001 else // Can't do it for B/H loads
22007 // if it's a branch, it can't happen in the middle of an IT block
22008 // Also, if it is a branch, make it unconditional at this point.
22009 // Doing conditional branches in-line is too complex (for now)
22011 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
22013 mk_skip_over_T32_if_cond_is_false(condT
);
22014 condT
= IRTemp_INVALID
;
22018 IRTemp rNt
= newTemp(Ity_I32
);
22021 assign(rNt
, binop(Iop_And32
, getIRegT(15), mkU32(~3)));
22023 assign(rNt
, getIRegT(rN
));
22026 IRTemp transAddr
= newTemp(Ity_I32
);
22028 binop(bU
== 1 ? Iop_Add32
: Iop_Sub32
,
22029 mkexpr(rNt
), mkU32(imm12
)));
22031 IRTemp oldRt
= newTemp(Ity_I32
);
22032 assign(oldRt
, getIRegT(rT
));
22034 IRTemp llOldRt
= newTemp(Ity_I32
);
22035 assign(llOldRt
, llGetIReg(rT
));
22038 IRExpr
* data
= NULL
;
22041 data
= unop(Iop_32to8
, mkexpr(oldRt
));
22044 data
= unop(Iop_32to16
, mkexpr(oldRt
));
22047 data
= mkexpr(oldRt
);
22052 storeGuardedLE(mkexpr(transAddr
), data
, condT
);
22054 IRTemp newRt
= newTemp(Ity_I32
);
22055 IRLoadGOp widen
= ILGop_INVALID
;
22058 widen
= syned
? ILGop_8Sto32
: ILGop_8Uto32
; break;
22060 widen
= syned
? ILGop_16Sto32
: ILGop_16Uto32
; break;
22062 widen
= ILGop_Ident32
; break;
22066 loadGuardedLE(newRt
, widen
,
22067 mkexpr(transAddr
), mkexpr(llOldRt
), condT
);
22070 /* We'll do the write to the PC just below */
22073 /* IRTemp_INVALID is OK here because in the case where
22074 condT is false at run time, we're just putting the
22075 old rT value back. */
22076 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
22080 /* Presumably this is an interworking branch. */
22082 vassert(condT
== IRTemp_INVALID
); /* due to check above */
22083 llPutIReg(15, mkexpr(newRt
));
22084 dres
.jk_StopHere
= Ijk_Boring
;
22085 dres
.whatNext
= Dis_StopHere
;
22089 DIP("%s.w r%u, [r%u, +#%u]\n", nm
, rT
, rN
, imm12
);
22091 goto decode_success
;
22095 /* -------------- LDRD/STRD reg+/-#imm8 -------------- */
22096 /* Doubleword loads and stores of the form:
22097 ldrd/strd Rt, Rt2, [Rn, #+/-imm8] or
22098 ldrd/strd Rt, Rt2, [Rn], #+/-imm8 or
22099 ldrd/strd Rt, Rt2, [Rn, #+/-imm8]!
22101 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,0) && INSN0(6,6) == 1) {
22102 UInt bP
= INSN0(8,8);
22103 UInt bU
= INSN0(7,7);
22104 UInt bW
= INSN0(5,5);
22105 UInt bL
= INSN0(4,4); // 1: load 0: store
22106 UInt rN
= INSN0(3,0);
22107 UInt rT
= INSN1(15,12);
22108 UInt rT2
= INSN1(11,8);
22109 UInt imm8
= INSN1(7,0);
22112 if (bP
== 0 && bW
== 0) valid
= False
;
22113 if (bW
== 1 && (rN
== rT
|| rN
== rT2
)) valid
= False
;
22114 if (isBadRegT(rT
) || isBadRegT(rT2
)) valid
= False
;
22115 if (bL
== 1 && rT
== rT2
) valid
= False
;
22116 /* It's OK to use PC as the base register only in the
22117 following case: ldrd Rt, Rt2, [PC, #+/-imm8] */
22118 if (rN
== 15 && (bL
== 0/*store*/
22119 || bW
== 1/*wb*/)) valid
= False
;
22122 IRTemp preAddr
= newTemp(Ity_I32
);
22123 assign(preAddr
, 15 == rN
22124 ? binop(Iop_And32
, getIRegT(15), mkU32(~3U))
22127 IRTemp postAddr
= newTemp(Ity_I32
);
22128 assign(postAddr
, binop(bU
== 1 ? Iop_Add32
: Iop_Sub32
,
22129 mkexpr(preAddr
), mkU32(imm8
<< 2)));
22131 IRTemp transAddr
= bP
== 1 ? postAddr
: preAddr
;
22133 /* For almost all cases, we do the writeback after the transfers.
22134 However, that leaves the stack "uncovered" in cases like:
22136 strd rD, [sp, #-16]
22137 In which case, do the writeback to SP now, instead of later.
22138 This is bad in that it makes the insn non-restartable if the
22139 accesses fault, but at least keeps Memcheck happy. */
22140 Bool writeback_already_done
= False
;
22141 if (bL
== 0/*store*/ && bW
== 1/*wb*/
22142 && rN
== 13 && rN
!= rT
&& rN
!= rT2
22143 && bU
== 0/*minus*/
22144 && ((imm8
<< 2) == 8 || (imm8
<< 2) == 16)) {
22145 putIRegT(rN
, mkexpr(postAddr
), condT
);
22146 writeback_already_done
= True
;
22150 IRTemp oldRt
= newTemp(Ity_I32
);
22151 IRTemp oldRt2
= newTemp(Ity_I32
);
22152 assign(oldRt
, getIRegT(rT
));
22153 assign(oldRt2
, getIRegT(rT2
));
22154 storeGuardedLE( mkexpr(transAddr
),
22155 mkexpr(oldRt
), condT
);
22156 storeGuardedLE( binop(Iop_Add32
, mkexpr(transAddr
), mkU32(4)),
22157 mkexpr(oldRt2
), condT
);
22159 IRTemp oldRt
= newTemp(Ity_I32
);
22160 IRTemp oldRt2
= newTemp(Ity_I32
);
22161 IRTemp newRt
= newTemp(Ity_I32
);
22162 IRTemp newRt2
= newTemp(Ity_I32
);
22163 assign(oldRt
, llGetIReg(rT
));
22164 assign(oldRt2
, llGetIReg(rT2
));
22165 loadGuardedLE( newRt
, ILGop_Ident32
,
22167 mkexpr(oldRt
), condT
);
22168 loadGuardedLE( newRt2
, ILGop_Ident32
,
22169 binop(Iop_Add32
, mkexpr(transAddr
), mkU32(4)),
22170 mkexpr(oldRt2
), condT
);
22171 /* Put unconditionally, since we already switched on the condT
22172 in the guarded loads. */
22173 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
22174 putIRegT(rT2
, mkexpr(newRt2
), IRTemp_INVALID
);
22177 if (bW
== 1 && !writeback_already_done
) {
22178 putIRegT(rN
, mkexpr(postAddr
), condT
);
22181 const HChar
* nm
= bL
? "ldrd" : "strd";
22183 if (bP
== 1 && bW
== 0) {
22184 DIP("%s.w r%u, r%u, [r%u, #%c%u]\n",
22185 nm
, rT
, rT2
, rN
, bU
? '+' : '-', imm8
<< 2);
22187 else if (bP
== 1 && bW
== 1) {
22188 DIP("%s.w r%u, r%u, [r%u, #%c%u]!\n",
22189 nm
, rT
, rT2
, rN
, bU
? '+' : '-', imm8
<< 2);
22192 vassert(bP
== 0 && bW
== 1);
22193 DIP("%s.w r%u, r%u, [r%u], #%c%u\n",
22194 nm
, rT
, rT2
, rN
, bU
? '+' : '-', imm8
<< 2);
22197 goto decode_success
;
22201 /* -------------- (T3) Bcond.W label -------------- */
22202 /* This variant carries its own condition, so can't be part of an
22204 if (INSN0(15,11) == BITS5(1,1,1,1,0)
22205 && INSN1(15,14) == BITS2(1,0)
22206 && INSN1(12,12) == 0) {
22207 UInt cond
= INSN0(9,6);
22208 if (cond
!= ARMCondAL
&& cond
!= ARMCondNV
) {
22210 = (INSN0(10,10) << (1 + 1 + 6 + 11 + 1))
22211 | (INSN1(11,11) << (1 + 6 + 11 + 1))
22212 | (INSN1(13,13) << (6 + 11 + 1))
22213 | (INSN0(5,0) << (11 + 1))
22214 | (INSN1(10,0) << 1);
22216 Int simm21
= (Int
)uimm21
;
22219 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
22220 UInt dst
= simm21
+ guest_R15_curr_instr_notENC
+ 4;
22222 /* Not allowed in an IT block; SIGILL if so. */
22223 gen_SIGILL_T_if_in_ITBlock(old_itstate
, new_itstate
);
22225 IRTemp kondT
= newTemp(Ity_I32
);
22226 assign( kondT
, mk_armg_calculate_condition(cond
) );
22227 stmt( IRStmt_Exit( unop(Iop_32to1
, mkexpr(kondT
)),
22229 IRConst_U32(dst
| 1/*CPSR.T*/),
22231 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC
+ 4)
22233 dres
.jk_StopHere
= Ijk_Boring
;
22234 dres
.whatNext
= Dis_StopHere
;
22235 DIP("b%s.w 0x%x\n", nCC(cond
), dst
);
22236 goto decode_success
;
22240 /* ---------------- (T4) B.W label ---------------- */
22241 /* ... whereas this variant doesn't carry its own condition, so it
22242 has to be either unconditional or the conditional by virtue of
22243 being the last in an IT block. The upside is that there's 4
22244 more bits available for the jump offset, so it has a 16-times
22245 greater branch range than the T3 variant. */
22246 if (INSN0(15,11) == BITS5(1,1,1,1,0)
22247 && INSN1(15,14) == BITS2(1,0)
22248 && INSN1(12,12) == 1) {
22250 UInt bS
= INSN0(10,10);
22251 UInt bJ1
= INSN1(13,13);
22252 UInt bJ2
= INSN1(11,11);
22253 UInt bI1
= 1 ^ (bJ1
^ bS
);
22254 UInt bI2
= 1 ^ (bJ2
^ bS
);
22256 = (bS
<< (1 + 1 + 10 + 11 + 1))
22257 | (bI1
<< (1 + 10 + 11 + 1))
22258 | (bI2
<< (10 + 11 + 1))
22259 | (INSN0(9,0) << (11 + 1))
22260 | (INSN1(10,0) << 1);
22262 Int simm25
= (Int
)uimm25
;
22265 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
22266 UInt dst
= simm25
+ guest_R15_curr_instr_notENC
+ 4;
22268 /* If in an IT block, must be the last insn. */
22269 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
22272 mk_skip_over_T32_if_cond_is_false(condT
);
22273 condT
= IRTemp_INVALID
;
22277 llPutIReg(15, mkU32( dst
| 1 /*CPSR.T*/ ));
22278 dres
.jk_StopHere
= Ijk_Boring
;
22279 dres
.whatNext
= Dis_StopHere
;
22280 DIP("b.w 0x%x\n", dst
);
22281 goto decode_success
;
22285 /* ------------------ TBB, TBH ------------------ */
22286 if (INSN0(15,4) == 0xE8D && INSN1(15,5) == 0x780) {
22287 UInt rN
= INSN0(3,0);
22288 UInt rM
= INSN1(3,0);
22289 UInt bH
= INSN1(4,4);
22290 if (bH
/*ATC*/ || (rN
!= 13 && !isBadRegT(rM
))) {
22291 /* Must be last or not-in IT block */
22292 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate
, new_itstate
);
22294 mk_skip_over_T32_if_cond_is_false(condT
);
22295 condT
= IRTemp_INVALID
;
22300 bH
? binop(Iop_Shl32
, getIRegT(rM
), mkU8(1))
22303 IRTemp delta
= newTemp(Ity_I32
);
22305 assign(delta
, unop(Iop_16Uto32
, loadLE(Ity_I16
, ea
)));
22307 assign(delta
, unop(Iop_8Uto32
, loadLE(Ity_I8
, ea
)));
22315 binop(Iop_Shl32
, mkexpr(delta
), mkU8(1))
22319 dres
.jk_StopHere
= Ijk_Boring
;
22320 dres
.whatNext
= Dis_StopHere
;
22321 DIP("tb%c [r%u, r%u%s]\n",
22322 bH
? 'h' : 'b', rN
, rM
, bH
? ", LSL #1" : "");
22323 goto decode_success
;
22327 /* ------------------ UBFX ------------------ */
22328 /* ------------------ SBFX ------------------ */
22329 /* There's also ARM versions of same, but it doesn't seem worth the
22330 hassle to common up the handling (it's only a couple of C
22332 if ((INSN0(15,4) == 0xF3C // UBFX
22333 || INSN0(15,4) == 0xF34) // SBFX
22334 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
22335 UInt rN
= INSN0(3,0);
22336 UInt rD
= INSN1(11,8);
22337 UInt lsb
= (INSN1(14,12) << 2) | INSN1(7,6);
22338 UInt wm1
= INSN1(4,0);
22339 UInt msb
= lsb
+ wm1
;
22340 if (!isBadRegT(rD
) && !isBadRegT(rN
) && msb
<= 31) {
22341 Bool isU
= INSN0(15,4) == 0xF3C;
22342 IRTemp src
= newTemp(Ity_I32
);
22343 IRTemp tmp
= newTemp(Ity_I32
);
22344 IRTemp res
= newTemp(Ity_I32
);
22345 UInt mask
= ((1 << wm1
) - 1) + (1 << wm1
);
22346 vassert(msb
>= 0 && msb
<= 31);
22347 vassert(mask
!= 0); // guaranteed by msb being in 0 .. 31 inclusive
22349 assign(src
, getIRegT(rN
));
22350 assign(tmp
, binop(Iop_And32
,
22351 binop(Iop_Shr32
, mkexpr(src
), mkU8(lsb
)),
22353 assign(res
, binop(isU
? Iop_Shr32
: Iop_Sar32
,
22354 binop(Iop_Shl32
, mkexpr(tmp
), mkU8(31-wm1
)),
22357 putIRegT(rD
, mkexpr(res
), condT
);
22359 DIP("%s r%u, r%u, #%u, #%u\n",
22360 isU
? "ubfx" : "sbfx", rD
, rN
, lsb
, wm1
+ 1);
22361 goto decode_success
;
22365 /* ------------------ UXTB ------------------ */
22366 /* ------------------ UXTH ------------------ */
22367 /* ------------------ SXTB ------------------ */
22368 /* ------------------ SXTH ------------------ */
22369 /* ----------------- UXTB16 ----------------- */
22370 /* ----------------- SXTB16 ----------------- */
22371 /* FIXME: this is an exact duplicate of the ARM version. They
22372 should be commoned up. */
22373 if ((INSN0(15,0) == 0xFA5F // UXTB
22374 || INSN0(15,0) == 0xFA1F // UXTH
22375 || INSN0(15,0) == 0xFA4F // SXTB
22376 || INSN0(15,0) == 0xFA0F // SXTH
22377 || INSN0(15,0) == 0xFA3F // UXTB16
22378 || INSN0(15,0) == 0xFA2F) // SXTB16
22379 && INSN1(15,12) == BITS4(1,1,1,1)
22380 && INSN1(7,6) == BITS2(1,0)) {
22381 UInt rD
= INSN1(11,8);
22382 UInt rM
= INSN1(3,0);
22383 UInt rot
= INSN1(5,4);
22384 if (!isBadRegT(rD
) && !isBadRegT(rM
)) {
22385 const HChar
* nm
= "???";
22386 IRTemp srcT
= newTemp(Ity_I32
);
22387 IRTemp rotT
= newTemp(Ity_I32
);
22388 IRTemp dstT
= newTemp(Ity_I32
);
22389 assign(srcT
, getIRegT(rM
));
22390 assign(rotT
, genROR32(srcT
, 8 * rot
));
22391 switch (INSN0(15,0)) {
22392 case 0xFA5F: // UXTB
22394 assign(dstT
, unop(Iop_8Uto32
,
22395 unop(Iop_32to8
, mkexpr(rotT
))));
22397 case 0xFA1F: // UXTH
22399 assign(dstT
, unop(Iop_16Uto32
,
22400 unop(Iop_32to16
, mkexpr(rotT
))));
22402 case 0xFA4F: // SXTB
22404 assign(dstT
, unop(Iop_8Sto32
,
22405 unop(Iop_32to8
, mkexpr(rotT
))));
22407 case 0xFA0F: // SXTH
22409 assign(dstT
, unop(Iop_16Sto32
,
22410 unop(Iop_32to16
, mkexpr(rotT
))));
22412 case 0xFA3F: // UXTB16
22414 assign(dstT
, binop(Iop_And32
, mkexpr(rotT
),
22415 mkU32(0x00FF00FF)));
22417 case 0xFA2F: { // SXTB16
22419 IRTemp lo32
= newTemp(Ity_I32
);
22420 IRTemp hi32
= newTemp(Ity_I32
);
22421 assign(lo32
, binop(Iop_And32
, mkexpr(rotT
), mkU32(0xFF)));
22422 assign(hi32
, binop(Iop_Shr32
, mkexpr(rotT
), mkU8(16)));
22428 unop(Iop_32to8
, mkexpr(lo32
))),
22432 unop(Iop_32to8
, mkexpr(hi32
))),
22440 putIRegT(rD
, mkexpr(dstT
), condT
);
22441 DIP("%s r%u, r%u, ror #%u\n", nm
, rD
, rM
, 8 * rot
);
22442 goto decode_success
;
22446 /* -------------- MUL.W Rd, Rn, Rm -------------- */
22447 if (INSN0(15,4) == 0xFB0
22448 && (INSN1(15,0) & 0xF0F0) == 0xF000) {
22449 UInt rN
= INSN0(3,0);
22450 UInt rD
= INSN1(11,8);
22451 UInt rM
= INSN1(3,0);
22452 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22453 IRTemp res
= newTemp(Ity_I32
);
22454 assign(res
, binop(Iop_Mul32
, getIRegT(rN
), getIRegT(rM
)));
22455 putIRegT(rD
, mkexpr(res
), condT
);
22456 DIP("mul.w r%u, r%u, r%u\n", rD
, rN
, rM
);
22457 goto decode_success
;
22461 /* -------------- SDIV.W Rd, Rn, Rm -------------- */
22462 if (INSN0(15,4) == 0xFB9
22463 && (INSN1(15,0) & 0xF0F0) == 0xF0F0) {
22464 UInt rN
= INSN0(3,0);
22465 UInt rD
= INSN1(11,8);
22466 UInt rM
= INSN1(3,0);
22467 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22468 IRTemp res
= newTemp(Ity_I32
);
22469 IRTemp argL
= newTemp(Ity_I32
);
22470 IRTemp argR
= newTemp(Ity_I32
);
22471 assign(argL
, getIRegT(rN
));
22472 assign(argR
, getIRegT(rM
));
22473 assign(res
, binop(Iop_DivS32
, mkexpr(argL
), mkexpr(argR
)));
22474 putIRegT(rD
, mkexpr(res
), condT
);
22475 DIP("sdiv.w r%u, r%u, r%u\n", rD
, rN
, rM
);
22476 goto decode_success
;
22480 /* -------------- UDIV.W Rd, Rn, Rm -------------- */
22481 if (INSN0(15,4) == 0xFBB
22482 && (INSN1(15,0) & 0xF0F0) == 0xF0F0) {
22483 UInt rN
= INSN0(3,0);
22484 UInt rD
= INSN1(11,8);
22485 UInt rM
= INSN1(3,0);
22486 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22487 IRTemp res
= newTemp(Ity_I32
);
22488 IRTemp argL
= newTemp(Ity_I32
);
22489 IRTemp argR
= newTemp(Ity_I32
);
22490 assign(argL
, getIRegT(rN
));
22491 assign(argR
, getIRegT(rM
));
22492 assign(res
, binop(Iop_DivU32
, mkexpr(argL
), mkexpr(argR
)));
22493 putIRegT(rD
, mkexpr(res
), condT
);
22494 DIP("udiv.w r%u, r%u, r%u\n", rD
, rN
, rM
);
22495 goto decode_success
;
22499 /* ------------------ {U,S}MULL ------------------ */
22500 if ((INSN0(15,4) == 0xFB8 || INSN0(15,4) == 0xFBA)
22501 && INSN1(7,4) == BITS4(0,0,0,0)) {
22502 UInt isU
= INSN0(5,5);
22503 UInt rN
= INSN0(3,0);
22504 UInt rDlo
= INSN1(15,12);
22505 UInt rDhi
= INSN1(11,8);
22506 UInt rM
= INSN1(3,0);
22507 if (!isBadRegT(rDhi
) && !isBadRegT(rDlo
)
22508 && !isBadRegT(rN
) && !isBadRegT(rM
) && rDlo
!= rDhi
) {
22509 IRTemp res
= newTemp(Ity_I64
);
22510 assign(res
, binop(isU
? Iop_MullU32
: Iop_MullS32
,
22511 getIRegT(rN
), getIRegT(rM
)));
22512 putIRegT( rDhi
, unop(Iop_64HIto32
, mkexpr(res
)), condT
);
22513 putIRegT( rDlo
, unop(Iop_64to32
, mkexpr(res
)), condT
);
22514 DIP("%cmull r%u, r%u, r%u, r%u\n",
22515 isU
? 'u' : 's', rDlo
, rDhi
, rN
, rM
);
22516 goto decode_success
;
22520 /* ------------------ ML{A,S} ------------------ */
22521 if (INSN0(15,4) == 0xFB0
22522 && ( INSN1(7,4) == BITS4(0,0,0,0) // MLA
22523 || INSN1(7,4) == BITS4(0,0,0,1))) { // MLS
22524 UInt rN
= INSN0(3,0);
22525 UInt rA
= INSN1(15,12);
22526 UInt rD
= INSN1(11,8);
22527 UInt rM
= INSN1(3,0);
22528 if (!isBadRegT(rD
) && !isBadRegT(rN
)
22529 && !isBadRegT(rM
) && !isBadRegT(rA
)) {
22530 Bool isMLA
= INSN1(7,4) == BITS4(0,0,0,0);
22531 IRTemp res
= newTemp(Ity_I32
);
22533 binop(isMLA
? Iop_Add32
: Iop_Sub32
,
22535 binop(Iop_Mul32
, getIRegT(rN
), getIRegT(rM
))));
22536 putIRegT(rD
, mkexpr(res
), condT
);
22537 DIP("%s r%u, r%u, r%u, r%u\n",
22538 isMLA
? "mla" : "mls", rD
, rN
, rM
, rA
);
22539 goto decode_success
;
22543 /* ------------------ (T3) ADR ------------------ */
22544 if ((INSN0(15,0) == 0xF20F || INSN0(15,0) == 0xF60F)
22545 && INSN1(15,15) == 0) {
22546 /* rD = align4(PC) + imm32 */
22547 UInt rD
= INSN1(11,8);
22548 if (!isBadRegT(rD
)) {
22549 UInt imm32
= (INSN0(10,10) << 11)
22550 | (INSN1(14,12) << 8) | INSN1(7,0);
22551 putIRegT(rD
, binop(Iop_Add32
,
22552 binop(Iop_And32
, getIRegT(15), mkU32(~3U)),
22555 DIP("add r%u, pc, #%u\n", rD
, imm32
);
22556 goto decode_success
;
22560 /* ----------------- (T1) UMLAL ----------------- */
22561 /* ----------------- (T1) SMLAL ----------------- */
22562 if ((INSN0(15,4) == 0xFBE // UMLAL
22563 || INSN0(15,4) == 0xFBC) // SMLAL
22564 && INSN1(7,4) == BITS4(0,0,0,0)) {
22565 UInt rN
= INSN0(3,0);
22566 UInt rDlo
= INSN1(15,12);
22567 UInt rDhi
= INSN1(11,8);
22568 UInt rM
= INSN1(3,0);
22569 if (!isBadRegT(rDlo
) && !isBadRegT(rDhi
) && !isBadRegT(rN
)
22570 && !isBadRegT(rM
) && rDhi
!= rDlo
) {
22571 Bool isS
= INSN0(15,4) == 0xFBC;
22572 IRTemp argL
= newTemp(Ity_I32
);
22573 IRTemp argR
= newTemp(Ity_I32
);
22574 IRTemp old
= newTemp(Ity_I64
);
22575 IRTemp res
= newTemp(Ity_I64
);
22576 IRTemp resHi
= newTemp(Ity_I32
);
22577 IRTemp resLo
= newTemp(Ity_I32
);
22578 IROp mulOp
= isS
? Iop_MullS32
: Iop_MullU32
;
22579 assign( argL
, getIRegT(rM
));
22580 assign( argR
, getIRegT(rN
));
22581 assign( old
, binop(Iop_32HLto64
, getIRegT(rDhi
), getIRegT(rDlo
)) );
22582 assign( res
, binop(Iop_Add64
,
22584 binop(mulOp
, mkexpr(argL
), mkexpr(argR
))) );
22585 assign( resHi
, unop(Iop_64HIto32
, mkexpr(res
)) );
22586 assign( resLo
, unop(Iop_64to32
, mkexpr(res
)) );
22587 putIRegT( rDhi
, mkexpr(resHi
), condT
);
22588 putIRegT( rDlo
, mkexpr(resLo
), condT
);
22589 DIP("%cmlal r%u, r%u, r%u, r%u\n",
22590 isS
? 's' : 'u', rDlo
, rDhi
, rN
, rM
);
22591 goto decode_success
;
22595 /* ------------------ (T1) UMAAL ------------------ */
22596 if (INSN0(15,4) == 0xFBE && INSN1(7,4) == BITS4(0,1,1,0)) {
22597 UInt rN
= INSN0(3,0);
22598 UInt rDlo
= INSN1(15,12);
22599 UInt rDhi
= INSN1(11,8);
22600 UInt rM
= INSN1(3,0);
22601 if (!isBadRegT(rDlo
) && !isBadRegT(rDhi
) && !isBadRegT(rN
)
22602 && !isBadRegT(rM
) && rDhi
!= rDlo
) {
22603 IRTemp argN
= newTemp(Ity_I32
);
22604 IRTemp argM
= newTemp(Ity_I32
);
22605 IRTemp argDhi
= newTemp(Ity_I32
);
22606 IRTemp argDlo
= newTemp(Ity_I32
);
22607 IRTemp res
= newTemp(Ity_I64
);
22608 IRTemp resHi
= newTemp(Ity_I32
);
22609 IRTemp resLo
= newTemp(Ity_I32
);
22610 assign( argN
, getIRegT(rN
) );
22611 assign( argM
, getIRegT(rM
) );
22612 assign( argDhi
, getIRegT(rDhi
) );
22613 assign( argDlo
, getIRegT(rDlo
) );
22617 binop(Iop_MullU32
, mkexpr(argN
), mkexpr(argM
)),
22618 unop(Iop_32Uto64
, mkexpr(argDhi
))),
22619 unop(Iop_32Uto64
, mkexpr(argDlo
))) );
22620 assign( resHi
, unop(Iop_64HIto32
, mkexpr(res
)) );
22621 assign( resLo
, unop(Iop_64to32
, mkexpr(res
)) );
22622 putIRegT( rDhi
, mkexpr(resHi
), condT
);
22623 putIRegT( rDlo
, mkexpr(resLo
), condT
);
22624 DIP("umaal r%u, r%u, r%u, r%u\n", rDlo
, rDhi
, rN
, rM
);
22625 goto decode_success
;
22629 /* ------------------- (T1) SMMUL{R} ------------------ */
22630 if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
22631 && INSN0(6,4) == BITS3(1,0,1)
22632 && INSN1(15,12) == BITS4(1,1,1,1)
22633 && INSN1(7,5) == BITS3(0,0,0)) {
22634 UInt bitR
= INSN1(4,4);
22635 UInt rD
= INSN1(11,8);
22636 UInt rM
= INSN1(3,0);
22637 UInt rN
= INSN0(3,0);
22638 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22640 = unop(Iop_64HIto32
,
22642 binop(Iop_MullS32
, getIRegT(rN
), getIRegT(rM
)),
22643 mkU64(bitR
? 0x80000000ULL
: 0ULL)));
22644 putIRegT(rD
, res
, condT
);
22645 DIP("smmul%s r%u, r%u, r%u\n",
22646 bitR
? "r" : "", rD
, rN
, rM
);
22647 goto decode_success
;
22651 /* ------------------- (T1) SMMLA{R} ------------------ */
22652 if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
22653 && INSN0(6,4) == BITS3(1,0,1)
22654 && INSN1(7,5) == BITS3(0,0,0)) {
22655 UInt bitR
= INSN1(4,4);
22656 UInt rA
= INSN1(15,12);
22657 UInt rD
= INSN1(11,8);
22658 UInt rM
= INSN1(3,0);
22659 UInt rN
= INSN0(3,0);
22660 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
) && (rA
!= 13)) {
22662 = unop(Iop_64HIto32
,
22665 binop(Iop_32HLto64
, getIRegT(rA
), mkU32(0)),
22666 binop(Iop_MullS32
, getIRegT(rN
), getIRegT(rM
))),
22667 mkU64(bitR
? 0x80000000ULL
: 0ULL)));
22668 putIRegT(rD
, res
, condT
);
22669 DIP("smmla%s r%u, r%u, r%u, r%u\n",
22670 bitR
? "r" : "", rD
, rN
, rM
, rA
);
22671 goto decode_success
;
22675 /* ------------------ (T2) ADR ------------------ */
22676 if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF)
22677 && INSN1(15,15) == 0) {
22678 /* rD = align4(PC) - imm32 */
22679 UInt rD
= INSN1(11,8);
22680 if (!isBadRegT(rD
)) {
22681 UInt imm32
= (INSN0(10,10) << 11)
22682 | (INSN1(14,12) << 8) | INSN1(7,0);
22683 putIRegT(rD
, binop(Iop_Sub32
,
22684 binop(Iop_And32
, getIRegT(15), mkU32(~3U)),
22687 DIP("sub r%u, pc, #%u\n", rD
, imm32
);
22688 goto decode_success
;
22692 /* ------------------- (T1) BFI ------------------- */
22693 /* ------------------- (T1) BFC ------------------- */
22694 if (INSN0(15,4) == 0xF36 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
22695 UInt rD
= INSN1(11,8);
22696 UInt rN
= INSN0(3,0);
22697 UInt msb
= INSN1(4,0);
22698 UInt lsb
= (INSN1(14,12) << 2) | INSN1(7,6);
22699 if (isBadRegT(rD
) || rN
== 13 || msb
< lsb
) {
22700 /* undecodable; fall through */
22702 IRTemp src
= newTemp(Ity_I32
);
22703 IRTemp olddst
= newTemp(Ity_I32
);
22704 IRTemp newdst
= newTemp(Ity_I32
);
22705 UInt mask
= ((UInt
)1) << (msb
- lsb
);
22706 mask
= (mask
- 1) + mask
;
22707 vassert(mask
!= 0); // guaranteed by "msb < lsb" check above
22710 assign(src
, rN
== 15 ? mkU32(0) : getIRegT(rN
));
22711 assign(olddst
, getIRegT(rD
));
22715 binop(Iop_Shl32
, mkexpr(src
), mkU8(lsb
)),
22722 putIRegT(rD
, mkexpr(newdst
), condT
);
22725 DIP("bfc r%u, #%u, #%u\n",
22726 rD
, lsb
, msb
-lsb
+1);
22728 DIP("bfi r%u, r%u, #%u, #%u\n",
22729 rD
, rN
, lsb
, msb
-lsb
+1);
22731 goto decode_success
;
22735 /* ------------------- (T1) SXTAH ------------------- */
22736 /* ------------------- (T1) UXTAH ------------------- */
22737 if ((INSN0(15,4) == 0xFA1 // UXTAH
22738 || INSN0(15,4) == 0xFA0) // SXTAH
22739 && INSN1(15,12) == BITS4(1,1,1,1)
22740 && INSN1(7,6) == BITS2(1,0)) {
22741 Bool isU
= INSN0(15,4) == 0xFA1;
22742 UInt rN
= INSN0(3,0);
22743 UInt rD
= INSN1(11,8);
22744 UInt rM
= INSN1(3,0);
22745 UInt rot
= INSN1(5,4);
22746 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22747 IRTemp srcL
= newTemp(Ity_I32
);
22748 IRTemp srcR
= newTemp(Ity_I32
);
22749 IRTemp res
= newTemp(Ity_I32
);
22750 assign(srcR
, getIRegT(rM
));
22751 assign(srcL
, getIRegT(rN
));
22752 assign(res
, binop(Iop_Add32
,
22754 unop(isU
? Iop_16Uto32
: Iop_16Sto32
,
22756 genROR32(srcR
, 8 * rot
)))));
22757 putIRegT(rD
, mkexpr(res
), condT
);
22758 DIP("%cxtah r%u, r%u, r%u, ror #%u\n",
22759 isU
? 'u' : 's', rD
, rN
, rM
, rot
);
22760 goto decode_success
;
22764 /* ------------------- (T1) SXTAB ------------------- */
22765 /* ------------------- (T1) UXTAB ------------------- */
22766 if ((INSN0(15,4) == 0xFA5 // UXTAB
22767 || INSN0(15,4) == 0xFA4) // SXTAB
22768 && INSN1(15,12) == BITS4(1,1,1,1)
22769 && INSN1(7,6) == BITS2(1,0)) {
22770 Bool isU
= INSN0(15,4) == 0xFA5;
22771 UInt rN
= INSN0(3,0);
22772 UInt rD
= INSN1(11,8);
22773 UInt rM
= INSN1(3,0);
22774 UInt rot
= INSN1(5,4);
22775 if (!isBadRegT(rD
) && !isBadRegT(rN
) && !isBadRegT(rM
)) {
22776 IRTemp srcL
= newTemp(Ity_I32
);
22777 IRTemp srcR
= newTemp(Ity_I32
);
22778 IRTemp res
= newTemp(Ity_I32
);
22779 assign(srcR
, getIRegT(rM
));
22780 assign(srcL
, getIRegT(rN
));
22781 assign(res
, binop(Iop_Add32
,
22783 unop(isU
? Iop_8Uto32
: Iop_8Sto32
,
22785 genROR32(srcR
, 8 * rot
)))));
22786 putIRegT(rD
, mkexpr(res
), condT
);
22787 DIP("%cxtab r%u, r%u, r%u, ror #%u\n",
22788 isU
? 'u' : 's', rD
, rN
, rM
, rot
);
22789 goto decode_success
;
22793 /* ------------------- (T1) CLZ ------------------- */
22794 if (INSN0(15,4) == 0xFAB
22795 && INSN1(15,12) == BITS4(1,1,1,1)
22796 && INSN1(7,4) == BITS4(1,0,0,0)) {
22797 UInt rM1
= INSN0(3,0);
22798 UInt rD
= INSN1(11,8);
22799 UInt rM2
= INSN1(3,0);
22800 if (!isBadRegT(rD
) && !isBadRegT(rM1
) && rM1
== rM2
) {
22801 IRTemp arg
= newTemp(Ity_I32
);
22802 IRTemp res
= newTemp(Ity_I32
);
22803 assign(arg
, getIRegT(rM1
));
22804 assign(res
, IRExpr_ITE(
22805 binop(Iop_CmpEQ32
, mkexpr(arg
), mkU32(0)),
22807 unop(Iop_Clz32
, mkexpr(arg
))
22809 putIRegT(rD
, mkexpr(res
), condT
);
22810 DIP("clz r%u, r%u\n", rD
, rM1
);
22811 goto decode_success
;
22815 /* ------------------- (T1) RBIT ------------------- */
22816 if (INSN0(15,4) == 0xFA9
22817 && INSN1(15,12) == BITS4(1,1,1,1)
22818 && INSN1(7,4) == BITS4(1,0,1,0)) {
22819 UInt rM1
= INSN0(3,0);
22820 UInt rD
= INSN1(11,8);
22821 UInt rM2
= INSN1(3,0);
22822 if (!isBadRegT(rD
) && !isBadRegT(rM1
) && rM1
== rM2
) {
22823 IRTemp arg
= newTemp(Ity_I32
);
22824 assign(arg
, getIRegT(rM1
));
22825 IRTemp res
= gen_BITREV(arg
);
22826 putIRegT(rD
, mkexpr(res
), condT
);
22827 DIP("rbit r%u, r%u\n", rD
, rM1
);
22828 goto decode_success
;
22832 /* ------------------- (T2) REV ------------------- */
22833 /* ------------------- (T2) REV16 ------------------- */
22834 if (INSN0(15,4) == 0xFA9
22835 && INSN1(15,12) == BITS4(1,1,1,1)
22836 && ( INSN1(7,4) == BITS4(1,0,0,0) // REV
22837 || INSN1(7,4) == BITS4(1,0,0,1))) { // REV16
22838 UInt rM1
= INSN0(3,0);
22839 UInt rD
= INSN1(11,8);
22840 UInt rM2
= INSN1(3,0);
22841 Bool isREV
= INSN1(7,4) == BITS4(1,0,0,0);
22842 if (!isBadRegT(rD
) && !isBadRegT(rM1
) && rM1
== rM2
) {
22843 IRTemp arg
= newTemp(Ity_I32
);
22844 assign(arg
, getIRegT(rM1
));
22845 IRTemp res
= isREV
? gen_REV(arg
) : gen_REV16(arg
);
22846 putIRegT(rD
, mkexpr(res
), condT
);
22847 DIP("rev%s r%u, r%u\n", isREV
? "" : "16", rD
, rM1
);
22848 goto decode_success
;
22852 /* ------------------- (T2) REVSH ------------------ */
22853 if (INSN0(15,4) == 0xFA9
22854 && INSN1(15,12) == BITS4(1,1,1,1)
22855 && INSN1(7,4) == BITS4(1,0,1,1)) {
22856 UInt rM1
= INSN0(3,0);
22857 UInt rM2
= INSN1(3,0);
22858 UInt rD
= INSN1(11,8);
22859 if (!isBadRegT(rD
) && !isBadRegT(rM1
) && rM1
== rM2
) {
22860 IRTemp irt_rM
= newTemp(Ity_I32
);
22861 IRTemp irt_hi
= newTemp(Ity_I32
);
22862 IRTemp irt_low
= newTemp(Ity_I32
);
22863 IRTemp irt_res
= newTemp(Ity_I32
);
22864 assign(irt_rM
, getIRegT(rM1
));
22867 binop(Iop_Shl32
, mkexpr(irt_rM
), mkU8(24)),
22873 binop(Iop_Shr32
, mkexpr(irt_rM
), mkU8(8)),
22878 binop(Iop_Or32
, mkexpr(irt_hi
), mkexpr(irt_low
))
22880 putIRegT(rD
, mkexpr(irt_res
), condT
);
22881 DIP("revsh r%u, r%u\n", rD
, rM1
);
22882 goto decode_success
;
22886 /* -------------- (T1) MSR apsr, reg -------------- */
22887 if (INSN0(15,4) == 0xF38
22888 && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) {
22889 UInt rN
= INSN0(3,0);
22890 UInt write_ge
= INSN1(10,10);
22891 UInt write_nzcvq
= INSN1(11,11);
22892 if (!isBadRegT(rN
) && (write_nzcvq
|| write_ge
)) {
22893 IRTemp rNt
= newTemp(Ity_I32
);
22894 assign(rNt
, getIRegT(rN
));
22895 desynthesise_APSR( write_nzcvq
, write_ge
, rNt
, condT
);
22896 DIP("msr cpsr_%s%s, r%u\n",
22897 write_nzcvq
? "f" : "", write_ge
? "g" : "", rN
);
22898 goto decode_success
;
22902 /* -------------- (T1) MRS reg, apsr -------------- */
22903 if (INSN0(15,0) == 0xF3EF
22904 && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(7,0) == 0x00) {
22905 UInt rD
= INSN1(11,8);
22906 if (!isBadRegT(rD
)) {
22907 IRTemp apsr
= synthesise_APSR();
22908 putIRegT( rD
, mkexpr(apsr
), condT
);
22909 DIP("mrs r%u, cpsr\n", rD
);
22910 goto decode_success
;
22914 /* ----------------- (T1) LDREX ----------------- */
22915 if (INSN0(15,4) == 0xE85 && INSN1(11,8) == BITS4(1,1,1,1)) {
22916 UInt rN
= INSN0(3,0);
22917 UInt rT
= INSN1(15,12);
22918 UInt imm8
= INSN1(7,0);
22919 if (!isBadRegT(rT
) && rN
!= 15) {
22922 mk_skip_over_T32_if_cond_is_false( condT
);
22924 res
= newTemp(Ity_I32
);
22925 stmt( IRStmt_LLSC(Iend_LE
,
22927 binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
* 4)),
22928 NULL
/*this is a load*/ ));
22929 putIRegT(rT
, mkexpr(res
), IRTemp_INVALID
);
22930 DIP("ldrex r%u, [r%u, #+%u]\n", rT
, rN
, imm8
* 4);
22931 goto decode_success
;
22935 /* --------------- (T1) LDREX{B,H} --------------- */
22936 if (INSN0(15,4) == 0xE8D
22937 && (INSN1(11,0) == 0xF4F || INSN1(11,0) == 0xF5F)) {
22938 UInt rN
= INSN0(3,0);
22939 UInt rT
= INSN1(15,12);
22940 Bool isH
= INSN1(11,0) == 0xF5F;
22941 if (!isBadRegT(rT
) && rN
!= 15) {
22944 mk_skip_over_T32_if_cond_is_false( condT
);
22946 res
= newTemp(isH
? Ity_I16
: Ity_I8
);
22947 stmt( IRStmt_LLSC(Iend_LE
, res
, getIRegT(rN
),
22948 NULL
/*this is a load*/ ));
22949 putIRegT(rT
, unop(isH
? Iop_16Uto32
: Iop_8Uto32
, mkexpr(res
)),
22951 DIP("ldrex%c r%u, [r%u]\n", isH
? 'h' : 'b', rT
, rN
);
22952 goto decode_success
;
22956 /* --------------- (T1) LDREXD --------------- */
22957 if (INSN0(15,4) == 0xE8D && INSN1(7,0) == 0x7F) {
22958 UInt rN
= INSN0(3,0);
22959 UInt rT
= INSN1(15,12);
22960 UInt rT2
= INSN1(11,8);
22961 if (!isBadRegT(rT
) && !isBadRegT(rT2
) && rT
!= rT2
&& rN
!= 15) {
22964 mk_skip_over_T32_if_cond_is_false( condT
);
22966 res
= newTemp(Ity_I64
);
22967 // FIXME: assumes little-endian guest
22968 stmt( IRStmt_LLSC(Iend_LE
, res
, getIRegT(rN
),
22969 NULL
/*this is a load*/ ));
22970 // FIXME: assumes little-endian guest
22971 putIRegT(rT
, unop(Iop_64to32
, mkexpr(res
)), IRTemp_INVALID
);
22972 putIRegT(rT2
, unop(Iop_64HIto32
, mkexpr(res
)), IRTemp_INVALID
);
22973 DIP("ldrexd r%u, r%u, [r%u]\n", rT
, rT2
, rN
);
22974 goto decode_success
;
22978 /* ----------------- (T1) STREX ----------------- */
22979 if (INSN0(15,4) == 0xE84) {
22980 UInt rN
= INSN0(3,0);
22981 UInt rT
= INSN1(15,12);
22982 UInt rD
= INSN1(11,8);
22983 UInt imm8
= INSN1(7,0);
22984 if (!isBadRegT(rD
) && !isBadRegT(rT
) && rN
!= 15
22985 && rD
!= rN
&& rD
!= rT
) {
22986 IRTemp resSC1
, resSC32
;
22988 mk_skip_over_T32_if_cond_is_false( condT
);
22990 /* Ok, now we're unconditional. Do the store. */
22991 resSC1
= newTemp(Ity_I1
);
22992 stmt( IRStmt_LLSC(Iend_LE
,
22994 binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
* 4)),
22996 /* Set rD to 1 on failure, 0 on success. Currently we have
22997 resSC1 == 0 on failure, 1 on success. */
22998 resSC32
= newTemp(Ity_I32
);
23000 unop(Iop_1Uto32
, unop(Iop_Not1
, mkexpr(resSC1
))));
23001 putIRegT(rD
, mkexpr(resSC32
), IRTemp_INVALID
);
23002 DIP("strex r%u, r%u, [r%u, #+%u]\n", rD
, rT
, rN
, imm8
* 4);
23003 goto decode_success
;
23007 /* --------------- (T1) STREX{B,H} --------------- */
23008 if (INSN0(15,4) == 0xE8C
23009 && (INSN1(11,4) == 0xF4 || INSN1(11,4) == 0xF5)) {
23010 UInt rN
= INSN0(3,0);
23011 UInt rT
= INSN1(15,12);
23012 UInt rD
= INSN1(3,0);
23013 Bool isH
= INSN1(11,4) == 0xF5;
23014 if (!isBadRegT(rD
) && !isBadRegT(rT
) && rN
!= 15
23015 && rD
!= rN
&& rD
!= rT
) {
23016 IRTemp resSC1
, resSC32
;
23018 mk_skip_over_T32_if_cond_is_false( condT
);
23020 /* Ok, now we're unconditional. Do the store. */
23021 resSC1
= newTemp(Ity_I1
);
23022 stmt( IRStmt_LLSC(Iend_LE
, resSC1
, getIRegT(rN
),
23023 unop(isH
? Iop_32to16
: Iop_32to8
,
23025 /* Set rD to 1 on failure, 0 on success. Currently we have
23026 resSC1 == 0 on failure, 1 on success. */
23027 resSC32
= newTemp(Ity_I32
);
23029 unop(Iop_1Uto32
, unop(Iop_Not1
, mkexpr(resSC1
))));
23030 putIRegT(rD
, mkexpr(resSC32
), IRTemp_INVALID
);
23031 DIP("strex%c r%u, r%u, [r%u]\n", isH
? 'h' : 'b', rD
, rT
, rN
);
23032 goto decode_success
;
23036 /* ---------------- (T1) STREXD ---------------- */
23037 if (INSN0(15,4) == 0xE8C && INSN1(7,4) == BITS4(0,1,1,1)) {
23038 UInt rN
= INSN0(3,0);
23039 UInt rT
= INSN1(15,12);
23040 UInt rT2
= INSN1(11,8);
23041 UInt rD
= INSN1(3,0);
23042 if (!isBadRegT(rD
) && !isBadRegT(rT
) && !isBadRegT(rT2
)
23043 && rN
!= 15 && rD
!= rN
&& rD
!= rT
&& rD
!= rT2
) {
23044 IRTemp resSC1
, resSC32
, data
;
23046 mk_skip_over_T32_if_cond_is_false( condT
);
23048 /* Ok, now we're unconditional. Do the store. */
23049 resSC1
= newTemp(Ity_I1
);
23050 data
= newTemp(Ity_I64
);
23051 // FIXME: assumes little-endian guest
23052 assign(data
, binop(Iop_32HLto64
, getIRegT(rT2
), getIRegT(rT
)));
23053 // FIXME: assumes little-endian guest
23054 stmt( IRStmt_LLSC(Iend_LE
, resSC1
, getIRegT(rN
), mkexpr(data
)));
23055 /* Set rD to 1 on failure, 0 on success. Currently we have
23056 resSC1 == 0 on failure, 1 on success. */
23057 resSC32
= newTemp(Ity_I32
);
23059 unop(Iop_1Uto32
, unop(Iop_Not1
, mkexpr(resSC1
))));
23060 putIRegT(rD
, mkexpr(resSC32
), IRTemp_INVALID
);
23061 DIP("strexd r%u, r%u, r%u, [r%u]\n", rD
, rT
, rT2
, rN
);
23062 goto decode_success
;
23066 /* -------------- v7 barrier insns -------------- */
23067 if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) {
23068 /* FIXME: should this be unconditional? */
23069 /* XXX this isn't really right, is it? The generated IR does
23070 them unconditionally. I guess it doesn't matter since it
23071 doesn't do any harm to do them even when the guarding
23072 condition is false -- it's just a performance loss. */
23073 switch (INSN1(7,0)) {
23074 case 0x4F: /* DSB sy */
23075 case 0x4E: /* DSB st */
23076 case 0x4B: /* DSB ish */
23077 case 0x4A: /* DSB ishst */
23078 case 0x47: /* DSB nsh */
23079 case 0x46: /* DSB nshst */
23080 case 0x43: /* DSB osh */
23081 case 0x42: /* DSB oshst */
23082 stmt( IRStmt_MBE(Imbe_Fence
) );
23084 goto decode_success
;
23085 case 0x5F: /* DMB sy */
23086 case 0x5E: /* DMB st */
23087 case 0x5B: /* DMB ish */
23088 case 0x5A: /* DMB ishst */
23089 case 0x57: /* DMB nsh */
23090 case 0x56: /* DMB nshst */
23091 case 0x53: /* DMB osh */
23092 case 0x52: /* DMB oshst */
23093 stmt( IRStmt_MBE(Imbe_Fence
) );
23095 goto decode_success
;
23096 case 0x6F: /* ISB */
23097 stmt( IRStmt_MBE(Imbe_Fence
) );
23099 goto decode_success
;
23105 /* ---------------------- PLD{,W} ---------------------- */
23106 if ((INSN0(15,4) & 0xFFD) == 0xF89 && INSN1(15,12) == 0xF) {
23107 /* FIXME: should this be unconditional? */
23108 /* PLD/PLDW immediate, encoding T1 */
23109 UInt rN
= INSN0(3,0);
23110 UInt bW
= INSN0(5,5);
23111 UInt imm12
= INSN1(11,0);
23112 DIP("pld%s [r%u, #%u]\n", bW
? "w" : "", rN
, imm12
);
23113 goto decode_success
;
23116 if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,8) == 0xFC) {
23117 /* FIXME: should this be unconditional? */
23118 /* PLD/PLDW immediate, encoding T2 */
23119 UInt rN
= INSN0(3,0);
23120 UInt bW
= INSN0(5,5);
23121 UInt imm8
= INSN1(7,0);
23122 DIP("pld%s [r%u, #-%u]\n", bW
? "w" : "", rN
, imm8
);
23123 goto decode_success
;
23126 if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,6) == 0x3C0) {
23127 /* FIXME: should this be unconditional? */
23128 /* PLD/PLDW register, encoding T1 */
23129 UInt rN
= INSN0(3,0);
23130 UInt rM
= INSN1(3,0);
23131 UInt bW
= INSN0(5,5);
23132 UInt imm2
= INSN1(5,4);
23133 if (!isBadRegT(rM
)) {
23134 DIP("pld%s [r%u, r%u, lsl %u]\n", bW
? "w" : "", rN
, rM
, imm2
);
23135 goto decode_success
;
23140 /* -------------- read CP15 TPIDRURO register ------------- */
23141 /* mrc p15, 0, r0, c13, c0, 3 up to
23142 mrc p15, 0, r14, c13, c0, 3
23144 /* I don't know whether this is really v7-only. But anyway, we
23145 have to support it since arm-linux uses TPIDRURO as a thread
23147 if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) {
23148 UInt rD
= INSN1(15,12);
23149 if (!isBadRegT(rD
)) {
23150 putIRegT(rD
, IRExpr_Get(OFFB_TPIDRURO
, Ity_I32
), condT
);
23151 DIP("mrc p15,0, r%u, c13, c0, 3\n", rD
);
23152 goto decode_success
;
23157 /* ------------ read/write CP15 TPIDRURW register ----------- */
23158 /* mcr p15, 0, r0, c13, c0, 2 (r->cr xfer) up to
23159 mcr p15, 0, r14, c13, c0, 2
23161 mrc p15, 0, r0, c13, c0, 2 (rc->r xfer) up to
23162 mrc p15, 0, r14, c13, c0, 2
23164 if ((INSN0(15,0) == 0xEE0D) && (INSN1(11,0) == 0x0F50)) {
23165 UInt rS
= INSN1(15,12);
23166 if (!isBadRegT(rS
)) {
23167 putMiscReg32(OFFB_TPIDRURW
, getIRegT(rS
), condT
);
23168 DIP("mcr p15,0, r%u, c13, c0, 2\n", rS
);
23169 goto decode_success
;
23173 if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F50)) {
23174 UInt rD
= INSN1(15,12);
23175 if (!isBadRegT(rD
)) {
23176 putIRegT(rD
, IRExpr_Get(OFFB_TPIDRURW
, Ity_I32
), condT
);
23177 DIP("mrc p15,0, r%u, c13, c0, 2\n", rD
);
23178 goto decode_success
;
23183 /* -------------- read CP15 PMUSRENR register ------------- */
23184 /* mrc p15, 0, r0, c9, c14, 0 up to
23185 mrc p15, 0, r14, c9, c14, 0
23186 See comment on the ARM equivalent of this (above) for details.
23188 if ((INSN0(15,0) == 0xEE19) && (INSN1(11,0) == 0x0F1E)) {
23189 UInt rD
= INSN1(15,12);
23190 if (!isBadRegT(rD
)) {
23191 putIRegT(rD
, mkU32(0), condT
);
23192 DIP("mrc p15,0, r%u, c9, c14, 0\n", rD
);
23193 goto decode_success
;
23198 /* ------------------- CLREX ------------------ */
23199 if (INSN0(15,0) == 0xF3BF && INSN1(15,0) == 0x8F2F) {
23200 /* AFAICS, this simply cancels a (all?) reservations made by a
23201 (any?) preceding LDREX(es). Arrange to hand it through to
23203 mk_skip_over_T32_if_cond_is_false( condT
);
23204 stmt( IRStmt_MBE(Imbe_CancelReservation
) );
23206 goto decode_success
;
23209 /* ------------------- NOP ------------------ */
23210 if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) {
23212 goto decode_success
;
23215 /* -------------- (T1) LDRT reg+#imm8 -------------- */
23216 /* Load Register Unprivileged:
23217 ldrt Rt, [Rn, #imm8]
23219 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,1) && INSN0(5,4) == BITS2(0,1)
23220 && INSN1(11,8) == BITS4(1,1,1,0)) {
23221 UInt rT
= INSN1(15,12);
23222 UInt rN
= INSN0(3,0);
23223 UInt imm8
= INSN1(7,0);
23225 if (rN
== 15 || isBadRegT(rT
)) valid
= False
;
23227 put_ITSTATE(old_itstate
);
23228 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23229 IRTemp newRt
= newTemp(Ity_I32
);
23230 loadGuardedLE( newRt
, ILGop_Ident32
, ea
, llGetIReg(rT
), condT
);
23231 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
23232 put_ITSTATE(new_itstate
);
23233 DIP("ldrt r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23234 goto decode_success
;
23238 /* -------------- (T1) STRT reg+#imm8 -------------- */
23239 /* Store Register Unprivileged:
23240 strt Rt, [Rn, #imm8]
23242 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,1) && INSN0(5,4) == BITS2(0,0)
23243 && INSN1(11,8) == BITS4(1,1,1,0)) {
23244 UInt rT
= INSN1(15,12);
23245 UInt rN
= INSN0(3,0);
23246 UInt imm8
= INSN1(7,0);
23248 if (rN
== 15 || isBadRegT(rT
)) valid
= False
;
23250 put_ITSTATE(old_itstate
);
23251 IRExpr
* address
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23252 storeGuardedLE( address
, llGetIReg(rT
), condT
);
23253 put_ITSTATE(new_itstate
);
23254 DIP("strt r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23255 goto decode_success
;
23259 /* -------------- (T1) STRBT reg+#imm8 -------------- */
23260 /* Store Register Byte Unprivileged:
23261 strbt Rt, [Rn, #imm8]
23263 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,0) && INSN0(5,4) == BITS2(0,0)
23264 && INSN1(11,8) == BITS4(1,1,1,0)) {
23265 UInt rT
= INSN1(15,12);
23266 UInt rN
= INSN0(3,0);
23267 UInt imm8
= INSN1(7,0);
23269 if (rN
== 15 || isBadRegT(rT
)) valid
= False
;
23271 put_ITSTATE(old_itstate
);
23272 IRExpr
* address
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23273 IRExpr
* data
= unop(Iop_32to8
, llGetIReg(rT
));
23274 storeGuardedLE( address
, data
, condT
);
23275 put_ITSTATE(new_itstate
);
23276 DIP("strbt r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23277 goto decode_success
;
23281 /* -------------- (T1) LDRHT reg+#imm8 -------------- */
23282 /* Load Register Halfword Unprivileged:
23283 ldrht Rt, [Rn, #imm8]
23285 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,0) && INSN0(5,4) == BITS2(1,1)
23286 && INSN1(11,8) == BITS4(1,1,1,0)) {
23287 UInt rN
= INSN0(3,0);
23290 /* In this case our instruction is LDRH (literal), in fact:
23291 LDRH (literal) was realized earlier, so we don't want to
23295 UInt rT
= INSN1(15,12);
23296 UInt imm8
= INSN1(7,0);
23297 if (isBadRegT(rT
)) valid
= False
;
23299 put_ITSTATE(old_itstate
);
23300 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23301 IRTemp newRt
= newTemp(Ity_I32
);
23302 loadGuardedLE( newRt
, ILGop_16Uto32
, ea
, llGetIReg(rT
), condT
);
23303 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
23304 put_ITSTATE(new_itstate
);
23305 DIP("ldrht r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23306 goto decode_success
;
23310 /* -------------- (T1) LDRSHT reg+#imm8 -------------- */
23311 /* Load Register Signed Halfword Unprivileged:
23312 ldrsht Rt, [Rn, #imm8]
23314 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,1,0,0) && INSN0(5,4) == BITS2(1,1)
23315 && INSN1(11,8) == BITS4(1,1,1,0)) {
23316 UInt rN
= INSN0(3,0);
23319 /* In this case our instruction is LDRSH (literal), in fact:
23320 LDRSH (literal) was realized earlier, so we don't want to
23324 UInt rT
= INSN1(15,12);
23325 UInt imm8
= INSN1(7,0);
23326 if (isBadRegT(rT
)) valid
= False
;
23328 put_ITSTATE(old_itstate
);
23329 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23330 IRTemp newRt
= newTemp(Ity_I32
);
23331 loadGuardedLE( newRt
, ILGop_16Sto32
, ea
, llGetIReg(rT
), condT
);
23332 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
23333 put_ITSTATE(new_itstate
);
23334 DIP("ldrsht r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23335 goto decode_success
;
23339 /* -------------- (T1) STRHT reg+#imm8 -------------- */
23340 /* Store Register Halfword Unprivileged:
23341 strht Rt, [Rn, #imm8]
23343 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,0) && INSN0(5,4) == BITS2(1,0)
23344 && INSN1(11,8) == BITS4(1,1,1,0)) {
23345 UInt rT
= INSN1(15,12);
23346 UInt rN
= INSN0(3,0);
23347 UInt imm8
= INSN1(7,0);
23349 if (rN
== 15 || isBadRegT(rT
)) valid
= False
;
23351 put_ITSTATE(old_itstate
);
23352 IRExpr
* address
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23353 IRExpr
* data
= unop(Iop_32to16
, llGetIReg(rT
));
23354 storeGuardedLE( address
, data
, condT
);
23355 put_ITSTATE(new_itstate
);
23356 DIP("strht r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23357 goto decode_success
;
23361 /* -------------- (T1) LDRBT reg+#imm8 -------------- */
23362 /* Load Register Byte Unprivileged:
23363 ldrbt Rt, [Rn, #imm8]
23365 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,0,0,0) && INSN0(5,4) == BITS2(0,1)
23366 && INSN1(11,8) == BITS4(1,1,1,0)) {
23367 UInt rN
= INSN0(3,0);
23368 UInt rT
= INSN1(15,12);
23369 UInt imm8
= INSN1(7,0);
23371 if (rN
== 15 /* insn is LDRB (literal) */) valid
= False
;
23372 if (isBadRegT(rT
)) valid
= False
;
23374 put_ITSTATE(old_itstate
);
23375 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23376 IRTemp newRt
= newTemp(Ity_I32
);
23377 loadGuardedLE( newRt
, ILGop_8Uto32
, ea
, llGetIReg(rT
), condT
);
23378 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
23379 put_ITSTATE(new_itstate
);
23380 DIP("ldrbt r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23381 goto decode_success
;
23385 /* -------------- (T1) LDRSBT reg+#imm8 -------------- */
23386 /* Load Register Signed Byte Unprivileged:
23387 ldrsbt Rt, [Rn, #imm8]
23389 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,1,0,0) && INSN0(5,4) == BITS2(0,1)
23390 && INSN1(11,8) == BITS4(1,1,1,0)) {
23391 UInt rN
= INSN0(3,0);
23393 UInt rT
= INSN1(15,12);
23394 UInt imm8
= INSN1(7,0);
23395 if (rN
== 15 /* insn is LDRSB (literal) */) valid
= False
;
23396 if (isBadRegT(rT
)) valid
= False
;
23398 put_ITSTATE(old_itstate
);
23399 IRExpr
* ea
= binop(Iop_Add32
, getIRegT(rN
), mkU32(imm8
));
23400 IRTemp newRt
= newTemp(Ity_I32
);
23401 loadGuardedLE( newRt
, ILGop_8Sto32
, ea
, llGetIReg(rT
), condT
);
23402 putIRegT(rT
, mkexpr(newRt
), IRTemp_INVALID
);
23403 put_ITSTATE(new_itstate
);
23404 DIP("ldrsbt r%u, [r%u, #%u]\n", rT
, rN
, imm8
);
23405 goto decode_success
;
23409 /* -------------- (T1) PLI reg+#imm12 -------------- */
23410 /* Preload Instruction:
23413 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,1,1,0) && INSN0(5,4) == BITS2(0,1)
23414 && INSN1(15,12) == BITS4(1,1,1,1)) {
23415 UInt rN
= INSN0(3,0);
23416 UInt imm12
= INSN1(11,0);
23418 DIP("pli [r%u, #%u]\n", rN
, imm12
);
23419 goto decode_success
;
23423 /* -------------- (T2) PLI reg-#imm8 -------------- */
23424 /* Preload Instruction:
23427 if (INSN0(15,6) == BITS10(1,1,1,1,1,0,0,1,0,0) && INSN0(5,4) == BITS2(0,1)
23428 && INSN1(15,8) == BITS8(1,1,1,1,1,1,0,0)) {
23429 UInt rN
= INSN0(3,0);
23430 UInt imm8
= INSN1(7,0);
23432 DIP("pli [r%u, #-%u]\n", rN
, imm8
);
23433 goto decode_success
;
23437 /* -------------- (T3) PLI PC+/-#imm12 -------------- */
23438 /* Preload Instruction:
23439 pli [PC, #+/-imm12]
23441 if (INSN0(15,8) == BITS8(1,1,1,1,1,0,0,1)
23442 && INSN0(6,0) == BITS7(0,0,1,1,1,1,1)
23443 && INSN1(15,12) == BITS4(1,1,1,1)) {
23444 UInt imm12
= INSN1(11,0);
23445 UInt bU
= INSN0(7,7);
23446 DIP("pli [pc, #%c%u]\n", bU
== 1 ? '+' : '-', imm12
);
23447 goto decode_success
;
23450 /* ----------------------------------------------------------- */
23451 /* -- VFP (CP 10, CP 11) instructions (in Thumb mode) -- */
23452 /* ----------------------------------------------------------- */
23454 if (INSN0(15,12) == BITS4(1,1,1,0)) {
23455 UInt insn28
= (INSN0(11,0) << 16) | INSN1(15,0);
23456 Bool ok_vfp
= decode_CP10_CP11_instruction (
23457 &dres
, insn28
, condT
, ARMCondAL
/*bogus*/,
23461 goto decode_success
;
23464 /* ----------------------------------------------------------- */
23465 /* -- NEON instructions (only v7 and below, in Thumb mode) -- */
23466 /* ----------------------------------------------------------- */
23468 if (archinfo
->hwcaps
& VEX_HWCAPS_ARM_NEON
) {
23469 UInt insn32
= (INSN0(15,0) << 16) | INSN1(15,0);
23470 Bool ok_neon
= decode_NEON_instruction_ARMv7_and_below(
23471 &dres
, insn32
, condT
, True
/*isT*/
23474 goto decode_success
;
23477 /* ----------------------------------------------------------- */
23478 /* -- v6 media instructions (in Thumb mode) -- */
23479 /* ----------------------------------------------------------- */
23481 { UInt insn32
= (INSN0(15,0) << 16) | INSN1(15,0);
23482 Bool ok_v6m
= decode_V6MEDIA_instruction(
23483 &dres
, insn32
, condT
, ARMCondAL
/*bogus*/,
23487 goto decode_success
;
23490 /* ----------------------------------------------------------- */
23491 /* -- v8 instructions (in Thumb mode) -- */
23492 /* ----------------------------------------------------------- */
23494 /* If we get here, it means that all attempts to decode the
23495 instruction as ARMv7 or earlier have failed. So, if we're doing
23496 ARMv8 or later, here is the point to try for it. */
23498 if (VEX_ARM_ARCHLEVEL(archinfo
->hwcaps
) >= 8) {
23499 UInt insn32
= (INSN0(15,0) << 16) | INSN1(15,0);
23501 = decode_V8_instruction( &dres
, insn32
, condT
, True
/*isT*/,
23502 old_itstate
, new_itstate
);
23504 goto decode_success
;
23507 /* ----------------------------------------------------------- */
23508 /* -- Undecodable -- */
23509 /* ----------------------------------------------------------- */
23511 goto decode_failure
;
23515 /* All decode failures end up here. */
23517 vex_printf("disInstr(thumb): unhandled instruction: "
23518 "0x%04x 0x%04x\n", (UInt
)insn0
, (UInt
)insn1
);
23520 /* Back up ITSTATE to the initial value for this instruction.
23521 If we don't do that, any subsequent restart of the instruction
23522 will restart with the wrong value. */
23523 if (old_itstate
!= IRTemp_INVALID
)
23524 put_ITSTATE(old_itstate
);
23526 /* Tell the dispatcher that this insn cannot be decoded, and so has
23527 not been executed, and (is currently) the next to be executed.
23528 R15 should be up-to-date since it made so at the start of each
23529 insn, but nevertheless be paranoid and update it again right
23531 vassert(0 == (guest_R15_curr_instr_notENC
& 1));
23532 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC
| 1) );
23534 dres
.whatNext
= Dis_StopHere
;
23535 dres
.jk_StopHere
= Ijk_NoDecode
;
23536 dres
.continueAt
= 0;
23540 /* All decode successes end up here. */
23541 vassert(dres
.len
== 4 || dres
.len
== 2 || dres
.len
== 20);
23542 switch (dres
.whatNext
) {
23544 llPutIReg(15, mkU32(dres
.len
+ (guest_R15_curr_instr_notENC
| 1)));
23548 llPutIReg(15, mkU32(dres
.continueAt
));
23568 /* Helper table for figuring out how many insns an IT insn
23571 An ITxyz instruction of the format "1011 1111 firstcond mask"
23572 conditionalises some number of instructions, as indicated by the
23573 following table. A value of zero indicates the instruction is
23574 invalid in some way.
23576 mask = 0 means this isn't an IT instruction
23577 fc = 15 (NV) means unpredictable
23579 The line fc = 14 (AL) is different from the others; there are
23580 additional constraints in this case.
23583 +--------------------------------
23584 fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23585 .. | 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 0 2 0 0 0 1 0 0 0 0 0 0 0
23599 15) | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
23601 To be conservative with the analysis, let's rule out the mask = 0
23602 case, since that isn't an IT insn at all. But for all the other
23603 cases where the table contains zero, that means unpredictable, so
23604 let's say 4 to be conservative. Hence we have a safe value for any
23605 IT (mask,fc) pair that the CPU would actually identify as an IT
23606 instruction. The final table is
23609 +--------------------------------
23610 fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
23611 .. | 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 4 4 1 4 4 4 4 4 4 4
23625 15) | 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
23627 static const UChar it_length_table
[256]
23628 = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
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, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4,
23643 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
23647 /*------------------------------------------------------------*/
23648 /*--- Top-level fn ---*/
23649 /*------------------------------------------------------------*/
23651 /* Disassemble a single instruction into IR. The instruction
23652 is located in host memory at &guest_code[delta]. */
23654 DisResult
disInstr_ARM ( IRSB
* irsb_IN
,
23655 Bool (*resteerOkFn
) ( void*, Addr
),
23657 void* callback_opaque
,
23658 const UChar
* guest_code_IN
,
23659 Long delta_ENCODED
,
23660 Addr guest_IP_ENCODED
,
23661 VexArch guest_arch
,
23662 const VexArchInfo
* archinfo
,
23663 const VexAbiInfo
* abiinfo
,
23664 VexEndness host_endness_IN
,
23665 Bool sigill_diag_IN
)
23668 Bool isThumb
= (Bool
)(guest_IP_ENCODED
& 1);
23670 /* Set globals (see top of this file) */
23671 vassert(guest_arch
== VexArchARM
);
23674 host_endness
= host_endness_IN
;
23675 __curr_is_Thumb
= isThumb
;
23678 guest_R15_curr_instr_notENC
= (Addr32
)guest_IP_ENCODED
- 1;
23680 guest_R15_curr_instr_notENC
= (Addr32
)guest_IP_ENCODED
;
23684 dres
= disInstr_THUMB_WRK ( resteerOkFn
,
23685 resteerCisOk
, callback_opaque
,
23686 &guest_code_IN
[delta_ENCODED
- 1],
23687 archinfo
, abiinfo
, sigill_diag_IN
);
23689 dres
= disInstr_ARM_WRK ( resteerOkFn
,
23690 resteerCisOk
, callback_opaque
,
23691 &guest_code_IN
[delta_ENCODED
],
23692 archinfo
, abiinfo
, sigill_diag_IN
);
23698 /* Test program for the conversion of IRCmpF64Result values to VFP
23699 nzcv values. See handling of FCMPD et al above. */
23701 UInt foo ( UInt x )
23703 UInt ix = ((x >> 5) & 3) | (x & 1);
23704 UInt termL = (((((ix ^ 1) << 30) - 1) >> 29) + 1);
23705 UInt termR = (ix & (ix >> 1) & 1);
23706 return termL - termR;
23709 void try ( char* s, UInt ir, UInt req )
23711 UInt act = foo(ir);
23712 printf("%s 0x%02x -> req %d%d%d%d act %d%d%d%d (0x%x)\n",
23713 s, ir, (req >> 3) & 1, (req >> 2) & 1,
23714 (req >> 1) & 1, (req >> 0) & 1,
23715 (act >> 3) & 1, (act >> 2) & 1,
23716 (act >> 1) & 1, (act >> 0) & 1, act);
23723 try("UN", 0x45, 0b0011);
23724 try("LT", 0x01, 0b1000);
23725 try("GT", 0x00, 0b0010);
23726 try("EQ", 0x40, 0b0110);
23732 /* Spare code for doing reference implementations of various 64-bit
23733 SIMD interleaves/deinterleaves/concatenation ops. */
23735 // Split a 64 bit value into 4 16 bit ones, in 32-bit IRTemps with
23736 // the top halves guaranteed to be zero.
23737 static void break64to16s ( IRTemp* out3, IRTemp* out2, IRTemp* out1,
23738 IRTemp* out0, IRTemp v64 )
23740 if (out3) *out3 = newTemp(Ity_I32);
23741 if (out2) *out2 = newTemp(Ity_I32);
23742 if (out1) *out1 = newTemp(Ity_I32);
23743 if (out0) *out0 = newTemp(Ity_I32);
23744 IRTemp hi32 = newTemp(Ity_I32);
23745 IRTemp lo32 = newTemp(Ity_I32);
23746 assign(hi32, unop(Iop_64HIto32, mkexpr(v64)) );
23747 assign(lo32, unop(Iop_64to32, mkexpr(v64)) );
23748 if (out3) assign(*out3, binop(Iop_Shr32, mkexpr(hi32), mkU8(16)));
23749 if (out2) assign(*out2, binop(Iop_And32, mkexpr(hi32), mkU32(0xFFFF)));
23750 if (out1) assign(*out1, binop(Iop_Shr32, mkexpr(lo32), mkU8(16)));
23751 if (out0) assign(*out0, binop(Iop_And32, mkexpr(lo32), mkU32(0xFFFF)));
23754 // Make a 64 bit value from 4 16 bit ones, each of which is in a 32 bit
23756 static IRTemp mk64from16s ( IRTemp in3, IRTemp in2, IRTemp in1, IRTemp in0 )
23758 IRTemp hi32 = newTemp(Ity_I32);
23759 IRTemp lo32 = newTemp(Ity_I32);
23762 binop(Iop_Shl32, mkexpr(in3), mkU8(16)),
23763 binop(Iop_And32, mkexpr(in2), mkU32(0xFFFF))));
23766 binop(Iop_Shl32, mkexpr(in1), mkU8(16)),
23767 binop(Iop_And32, mkexpr(in0), mkU32(0xFFFF))));
23768 IRTemp res = newTemp(Ity_I64);
23769 assign(res, binop(Iop_32HLto64, mkexpr(hi32), mkexpr(lo32)));
23773 static IRExpr* mk_InterleaveLO16x4 ( IRTemp a3210, IRTemp b3210 )
23775 // returns a1 b1 a0 b0
23776 IRTemp a1, a0, b1, b0;
23777 break64to16s(NULL, NULL, &a1, &a0, a3210);
23778 break64to16s(NULL, NULL, &b1, &b0, b3210);
23779 return mkexpr(mk64from16s(a1, b1, a0, b0));
23782 static IRExpr* mk_InterleaveHI16x4 ( IRTemp a3210, IRTemp b3210 )
23784 // returns a3 b3 a2 b2
23785 IRTemp a3, a2, b3, b2;
23786 break64to16s(&a3, &a2, NULL, NULL, a3210);
23787 break64to16s(&b3, &b2, NULL, NULL, b3210);
23788 return mkexpr(mk64from16s(a3, b3, a2, b2));
23791 static IRExpr* mk_CatEvenLanes16x4 ( IRTemp a3210, IRTemp b3210 )
23793 // returns a2 a0 b2 b0
23794 IRTemp a2, a0, b2, b0;
23795 break64to16s(NULL, &a2, NULL, &a0, a3210);
23796 break64to16s(NULL, &b2, NULL, &b0, b3210);
23797 return mkexpr(mk64from16s(a2, a0, b2, b0));
23800 static IRExpr* mk_CatOddLanes16x4 ( IRTemp a3210, IRTemp b3210 )
23802 // returns a3 a1 b3 b1
23803 IRTemp a3, a1, b3, b1;
23804 break64to16s(&a3, NULL, &a1, NULL, a3210);
23805 break64to16s(&b3, NULL, &b1, NULL, b3210);
23806 return mkexpr(mk64from16s(a3, a1, b3, b1));
23809 static IRExpr* mk_InterleaveOddLanes16x4 ( IRTemp a3210, IRTemp b3210 )
23811 // returns a3 b3 a1 b1
23812 IRTemp a3, b3, a1, b1;
23813 break64to16s(&a3, NULL, &a1, NULL, a3210);
23814 break64to16s(&b3, NULL, &b1, NULL, b3210);
23815 return mkexpr(mk64from16s(a3, b3, a1, b1));
23818 static IRExpr* mk_InterleaveEvenLanes16x4 ( IRTemp a3210, IRTemp b3210 )
23820 // returns a2 b2 a0 b0
23821 IRTemp a2, b2, a0, b0;
23822 break64to16s(NULL, &a2, NULL, &a0, a3210);
23823 break64to16s(NULL, &b2, NULL, &b0, b3210);
23824 return mkexpr(mk64from16s(a2, b2, a0, b0));
23827 static void break64to8s ( IRTemp* out7, IRTemp* out6, IRTemp* out5,
23828 IRTemp* out4, IRTemp* out3, IRTemp* out2,
23829 IRTemp* out1,IRTemp* out0, IRTemp v64 )
23831 if (out7) *out7 = newTemp(Ity_I32);
23832 if (out6) *out6 = newTemp(Ity_I32);
23833 if (out5) *out5 = newTemp(Ity_I32);
23834 if (out4) *out4 = newTemp(Ity_I32);
23835 if (out3) *out3 = newTemp(Ity_I32);
23836 if (out2) *out2 = newTemp(Ity_I32);
23837 if (out1) *out1 = newTemp(Ity_I32);
23838 if (out0) *out0 = newTemp(Ity_I32);
23839 IRTemp hi32 = newTemp(Ity_I32);
23840 IRTemp lo32 = newTemp(Ity_I32);
23841 assign(hi32, unop(Iop_64HIto32, mkexpr(v64)) );
23842 assign(lo32, unop(Iop_64to32, mkexpr(v64)) );
23844 assign(*out7, binop(Iop_And32,
23845 binop(Iop_Shr32, mkexpr(hi32), mkU8(24)),
23848 assign(*out6, binop(Iop_And32,
23849 binop(Iop_Shr32, mkexpr(hi32), mkU8(16)),
23852 assign(*out5, binop(Iop_And32,
23853 binop(Iop_Shr32, mkexpr(hi32), mkU8(8)),
23856 assign(*out4, binop(Iop_And32, mkexpr(hi32), mkU32(0xFF)));
23858 assign(*out3, binop(Iop_And32,
23859 binop(Iop_Shr32, mkexpr(lo32), mkU8(24)),
23862 assign(*out2, binop(Iop_And32,
23863 binop(Iop_Shr32, mkexpr(lo32), mkU8(16)),
23866 assign(*out1, binop(Iop_And32,
23867 binop(Iop_Shr32, mkexpr(lo32), mkU8(8)),
23870 assign(*out0, binop(Iop_And32, mkexpr(lo32), mkU32(0xFF)));
23873 static IRTemp mk64from8s ( IRTemp in7, IRTemp in6, IRTemp in5, IRTemp in4,
23874 IRTemp in3, IRTemp in2, IRTemp in1, IRTemp in0 )
23876 IRTemp hi32 = newTemp(Ity_I32);
23877 IRTemp lo32 = newTemp(Ity_I32);
23882 binop(Iop_And32, mkexpr(in7), mkU32(0xFF)),
23885 binop(Iop_And32, mkexpr(in6), mkU32(0xFF)),
23889 binop(Iop_And32, mkexpr(in5), mkU32(0xFF)), mkU8(8)),
23891 mkexpr(in4), mkU32(0xFF)))));
23896 binop(Iop_And32, mkexpr(in3), mkU32(0xFF)),
23899 binop(Iop_And32, mkexpr(in2), mkU32(0xFF)),
23903 binop(Iop_And32, mkexpr(in1), mkU32(0xFF)), mkU8(8)),
23905 mkexpr(in0), mkU32(0xFF)))));
23906 IRTemp res = newTemp(Ity_I64);
23907 assign(res, binop(Iop_32HLto64, mkexpr(hi32), mkexpr(lo32)));
23911 static IRExpr* mk_InterleaveLO8x8 ( IRTemp a76543210, IRTemp b76543210 )
23913 // returns a3 b3 a2 b2 a1 b1 a0 b0
23914 IRTemp a3, b3, a2, b2, a1, a0, b1, b0;
23915 break64to8s(NULL, NULL, NULL, NULL, &a3, &a2, &a1, &a0, a76543210);
23916 break64to8s(NULL, NULL, NULL, NULL, &b3, &b2, &b1, &b0, b76543210);
23917 return mkexpr(mk64from8s(a3, b3, a2, b2, a1, b1, a0, b0));
23920 static IRExpr* mk_InterleaveHI8x8 ( IRTemp a76543210, IRTemp b76543210 )
23922 // returns a7 b7 a6 b6 a5 b5 a4 b4
23923 IRTemp a7, b7, a6, b6, a5, b5, a4, b4;
23924 break64to8s(&a7, &a6, &a5, &a4, NULL, NULL, NULL, NULL, a76543210);
23925 break64to8s(&b7, &b6, &b5, &b4, NULL, NULL, NULL, NULL, b76543210);
23926 return mkexpr(mk64from8s(a7, b7, a6, b6, a5, b5, a4, b4));
23929 static IRExpr* mk_CatEvenLanes8x8 ( IRTemp a76543210, IRTemp b76543210 )
23931 // returns a6 a4 a2 a0 b6 b4 b2 b0
23932 IRTemp a6, a4, a2, a0, b6, b4, b2, b0;
23933 break64to8s(NULL, &a6, NULL, &a4, NULL, &a2, NULL, &a0, a76543210);
23934 break64to8s(NULL, &b6, NULL, &b4, NULL, &b2, NULL, &b0, b76543210);
23935 return mkexpr(mk64from8s(a6, a4, a2, a0, b6, b4, b2, b0));
23938 static IRExpr* mk_CatOddLanes8x8 ( IRTemp a76543210, IRTemp b76543210 )
23940 // returns a7 a5 a3 a1 b7 b5 b3 b1
23941 IRTemp a7, a5, a3, a1, b7, b5, b3, b1;
23942 break64to8s(&a7, NULL, &a5, NULL, &a3, NULL, &a1, NULL, a76543210);
23943 break64to8s(&b7, NULL, &b5, NULL, &b3, NULL, &b1, NULL, b76543210);
23944 return mkexpr(mk64from8s(a7, a5, a3, a1, b7, b5, b3, b1));
23947 static IRExpr* mk_InterleaveEvenLanes8x8 ( IRTemp a76543210, IRTemp b76543210 )
23949 // returns a6 b6 a4 b4 a2 b2 a0 b0
23950 IRTemp a6, b6, a4, b4, a2, b2, a0, b0;
23951 break64to8s(NULL, &a6, NULL, &a4, NULL, &a2, NULL, &a0, a76543210);
23952 break64to8s(NULL, &b6, NULL, &b4, NULL, &b2, NULL, &b0, b76543210);
23953 return mkexpr(mk64from8s(a6, b6, a4, b4, a2, b2, a0, b0));
23956 static IRExpr* mk_InterleaveOddLanes8x8 ( IRTemp a76543210, IRTemp b76543210 )
23958 // returns a7 b7 a5 b5 a3 b3 a1 b1
23959 IRTemp a7, b7, a5, b5, a3, b3, a1, b1;
23960 break64to8s(&a7, NULL, &a5, NULL, &a3, NULL, &a1, NULL, a76543210);
23961 break64to8s(&b7, NULL, &b5, NULL, &b3, NULL, &b1, NULL, b76543210);
23962 return mkexpr(mk64from8s(a7, b7, a5, b5, a3, b3, a1, b1));
23965 static IRExpr* mk_InterleaveLO32x2 ( IRTemp a10, IRTemp b10 )
23968 return binop(Iop_32HLto64, unop(Iop_64to32, mkexpr(a10)),
23969 unop(Iop_64to32, mkexpr(b10)));
23972 static IRExpr* mk_InterleaveHI32x2 ( IRTemp a10, IRTemp b10 )
23975 return binop(Iop_32HLto64, unop(Iop_64HIto32, mkexpr(a10)),
23976 unop(Iop_64HIto32, mkexpr(b10)));
23980 /*--------------------------------------------------------------------*/
23981 /*--- end guest_arm_toIR.c ---*/
23982 /*--------------------------------------------------------------------*/