2 /*--------------------------------------------------------------------*/
3 /*--- begin guest_arm_toIR.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2004-2010 OpenWorks LLP
14 Copyright (C) 2010-2010 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, no doubt
72 - SWP: the restart jump back is Ijk_Boring; it should be
73 Ijk_NoRedir but that's expensive. See comments on casLE() in
77 /* "Special" instructions.
79 This instruction decoder can decode four special instructions
80 which mean nothing natively (are no-ops as far as regs/mem are
81 concerned) but have meaning for supporting Valgrind. A special
82 instruction is flagged by a 16-byte preamble:
84 E1A0C1EC E1A0C6EC E1A0CEEC E1A0C9EC
85 (mov r12, r12, ROR #3; mov r12, r12, ROR #13;
86 mov r12, r12, ROR #29; mov r12, r12, ROR #19)
88 Following that, one of the following 3 are allowed
89 (standard interpretation in parentheses):
91 E18AA00A (orr r10,r10,r10) R3 = client_request ( R4 )
92 E18BB00B (orr r11,r11,r11) R3 = guest_NRADDR
93 E18CC00C (orr r12,r12,r12) branch-and-link-to-noredir R4
95 Any other bytes following the 16-byte preamble are illegal and
96 constitute a failure in instruction decoding. This all assumes
97 that the preamble will never occur except in specific code
98 fragments designed for Valgrind to catch.
101 /* Translates ARM(v5) code to IR. */
103 #include "libvex_basictypes.h"
104 #include "libvex_ir.h"
106 #include "libvex_guest_arm.h"
108 #include "main_util.h"
109 #include "main_globals.h"
110 #include "guest_generic_bb_to_IR.h"
111 #include "guest_arm_defs.h"
114 /*------------------------------------------------------------*/
116 /*------------------------------------------------------------*/
118 /* These are set at the start of the translation of a instruction, so
119 that we don't have to pass them around endlessly. CONST means does
120 not change during translation of the instruction.
123 /* CONST: is the host bigendian? This has to do with float vs double
124 register accesses on VFP, but it's complex and not properly thought
126 static Bool host_is_bigendian;
128 /* CONST: The guest address for the instruction currently being
129 translated. This is the real, "decoded" address (not subject
130 to the CPSR.T kludge). */
131 static Addr32 guest_R15_curr_instr_notENC;
133 /* CONST, FOR ASSERTIONS ONLY. Indicates whether currently processed
134 insn is Thumb (True) or ARM (False). */
135 static Bool __curr_is_Thumb;
137 /* MOD: The IRSB* into which we're generating code. */
140 /* These are to do with handling writes to r15. They are initially
141 set at the start of disInstr_ARM_WRK to indicate no update,
142 possibly updated during the routine, and examined again at the end.
143 If they have been set to indicate a r15 update then a jump is
144 generated. Note, "explicit" jumps (b, bx, etc) are generated
145 directly, not using this mechanism -- this is intended to handle
146 the implicit-style jumps resulting from (eg) assigning to r15 as
147 the result of insns we wouldn't normally consider branchy. */
149 /* MOD. Initially False; set to True iff abovementioned handling is
151 static Bool r15written;
153 /* MOD. Initially IRTemp_INVALID. If the r15 branch to be generated
154 is conditional, this holds the gating IRTemp :: Ity_I32. If the
155 branch to be generated is unconditional, this remains
157 static IRTemp r15guard; /* :: Ity_I32, 0 or 1 */
159 /* MOD. Initially Ijk_Boring. If an r15 branch is to be generated,
160 this holds the jump kind. */
161 static IRTemp r15kind;
164 /*------------------------------------------------------------*/
165 /*--- Debugging output ---*/
166 /*------------------------------------------------------------*/
168 #define DIP(format, args...) \
169 if (vex_traceflags & VEX_TRACE_FE) \
170 vex_printf(format, ## args)
172 #define DIS(buf, format, args...) \
173 if (vex_traceflags & VEX_TRACE_FE) \
174 vex_sprintf(buf, format, ## args)
176 #define ASSERT_IS_THUMB \
177 do { vassert(__curr_is_Thumb); } while (0)
179 #define ASSERT_IS_ARM \
180 do { vassert(! __curr_is_Thumb); } while (0)
183 /*------------------------------------------------------------*/
184 /*--- Helper bits and pieces for deconstructing the ---*/
185 /*--- arm insn stream. ---*/
186 /*------------------------------------------------------------*/
188 /* Do a little-endian load of a 32-bit word, regardless of the
189 endianness of the underlying host. */
190 static inline UInt getUIntLittleEndianly ( UChar* p )
200 /* Do a little-endian load of a 16-bit word, regardless of the
201 endianness of the underlying host. */
202 static inline UShort getUShortLittleEndianly ( UChar* p )
210 static UInt ROR32 ( UInt x, UInt sh ) {
211 vassert(sh >= 0 && sh < 32);
215 return (x << (32-sh)) | (x >> sh);
218 static Int popcount32 ( UInt x )
221 for (i = 0; i < 32; i++) {
228 static UInt setbit32 ( UInt x, Int ix, UInt b )
232 x |= ((b << ix) & mask);
236 #define BITS2(_b1,_b0) \
237 (((_b1) << 1) | (_b0))
239 #define BITS3(_b2,_b1,_b0) \
240 (((_b2) << 2) | ((_b1) << 1) | (_b0))
242 #define BITS4(_b3,_b2,_b1,_b0) \
243 (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
245 #define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
246 ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
247 | BITS4((_b3),(_b2),(_b1),(_b0)))
249 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
250 (BITS8(0,0,0,(_b4),(_b3),(_b2),(_b1),(_b0)))
251 #define BITS6(_b5,_b4,_b3,_b2,_b1,_b0) \
252 (BITS8(0,0,(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
253 #define BITS7(_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
254 (BITS8(0,(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
256 #define BITS9(_b8,_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
258 | BITS8((_b7),(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
260 #define BITS10(_b9,_b8,_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
261 (((_b9) << 9) | ((_b8) << 8) \
262 | BITS8((_b7),(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
264 /* produces _uint[_bMax:_bMin] */
265 #define SLICE_UInt(_uint,_bMax,_bMin) \
266 (( ((UInt)(_uint)) >> (_bMin)) \
267 & (UInt)((1ULL << ((_bMax) - (_bMin) + 1)) - 1ULL))
270 /*------------------------------------------------------------*/
271 /*--- Helper bits and pieces for creating IR fragments. ---*/
272 /*------------------------------------------------------------*/
274 static IRExpr* mkU64 ( ULong i )
276 return IRExpr_Const(IRConst_U64(i));
279 static IRExpr* mkU32 ( UInt i )
281 return IRExpr_Const(IRConst_U32(i));
284 static IRExpr* mkU8 ( UInt i )
287 return IRExpr_Const(IRConst_U8( (UChar)i ));
290 static IRExpr* mkexpr ( IRTemp tmp )
292 return IRExpr_RdTmp(tmp);
295 static IRExpr* unop ( IROp op, IRExpr* a )
297 return IRExpr_Unop(op, a);
300 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
302 return IRExpr_Binop(op, a1, a2);
305 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
307 return IRExpr_Triop(op, a1, a2, a3);
310 static IRExpr* loadLE ( IRType ty, IRExpr* addr )
312 return IRExpr_Load(Iend_LE, ty, addr);
315 /* Add a statement to the list held by "irbb". */
316 static void stmt ( IRStmt* st )
318 addStmtToIRSB( irsb, st );
321 static void assign ( IRTemp dst, IRExpr* e )
323 stmt( IRStmt_WrTmp(dst, e) );
326 static void storeLE ( IRExpr* addr, IRExpr* data )
328 stmt( IRStmt_Store(Iend_LE, addr, data) );
331 /* Generate a new temporary of the given type. */
332 static IRTemp newTemp ( IRType ty )
334 vassert(isPlausibleIRType(ty));
335 return newIRTemp( irsb->tyenv, ty );
338 /* Produces a value in 0 .. 3, which is encoded as per the type
340 static IRExpr* /* :: Ity_I32 */ get_FAKE_roundingmode ( void )
342 return mkU32(Irrm_NEAREST);
345 /* Generate an expression for SRC rotated right by ROT. */
346 static IRExpr* genROR32( IRTemp src, Int rot )
348 vassert(rot >= 0 && rot < 32);
353 binop(Iop_Shl32, mkexpr(src), mkU8(32 - rot)),
354 binop(Iop_Shr32, mkexpr(src), mkU8(rot)));
357 static IRExpr* mkU128 ( ULong i )
359 return binop(Iop_64HLtoV128, mkU64(i), mkU64(i));
362 /* Generate a 4-aligned version of the given expression if
363 the given condition is true. Else return it unchanged. */
364 static IRExpr* align4if ( IRExpr* e, Bool b )
367 return binop(Iop_And32, e, mkU32(~3));
373 /*------------------------------------------------------------*/
374 /*--- Helpers for accessing guest registers. ---*/
375 /*------------------------------------------------------------*/
377 #define OFFB_R0 offsetof(VexGuestARMState,guest_R0)
378 #define OFFB_R1 offsetof(VexGuestARMState,guest_R1)
379 #define OFFB_R2 offsetof(VexGuestARMState,guest_R2)
380 #define OFFB_R3 offsetof(VexGuestARMState,guest_R3)
381 #define OFFB_R4 offsetof(VexGuestARMState,guest_R4)
382 #define OFFB_R5 offsetof(VexGuestARMState,guest_R5)
383 #define OFFB_R6 offsetof(VexGuestARMState,guest_R6)
384 #define OFFB_R7 offsetof(VexGuestARMState,guest_R7)
385 #define OFFB_R8 offsetof(VexGuestARMState,guest_R8)
386 #define OFFB_R9 offsetof(VexGuestARMState,guest_R9)
387 #define OFFB_R10 offsetof(VexGuestARMState,guest_R10)
388 #define OFFB_R11 offsetof(VexGuestARMState,guest_R11)
389 #define OFFB_R12 offsetof(VexGuestARMState,guest_R12)
390 #define OFFB_R13 offsetof(VexGuestARMState,guest_R13)
391 #define OFFB_R14 offsetof(VexGuestARMState,guest_R14)
392 #define OFFB_R15T offsetof(VexGuestARMState,guest_R15T)
394 #define OFFB_CC_OP offsetof(VexGuestARMState,guest_CC_OP)
395 #define OFFB_CC_DEP1 offsetof(VexGuestARMState,guest_CC_DEP1)
396 #define OFFB_CC_DEP2 offsetof(VexGuestARMState,guest_CC_DEP2)
397 #define OFFB_CC_NDEP offsetof(VexGuestARMState,guest_CC_NDEP)
398 #define OFFB_NRADDR offsetof(VexGuestARMState,guest_NRADDR)
400 #define OFFB_D0 offsetof(VexGuestARMState,guest_D0)
401 #define OFFB_D1 offsetof(VexGuestARMState,guest_D1)
402 #define OFFB_D2 offsetof(VexGuestARMState,guest_D2)
403 #define OFFB_D3 offsetof(VexGuestARMState,guest_D3)
404 #define OFFB_D4 offsetof(VexGuestARMState,guest_D4)
405 #define OFFB_D5 offsetof(VexGuestARMState,guest_D5)
406 #define OFFB_D6 offsetof(VexGuestARMState,guest_D6)
407 #define OFFB_D7 offsetof(VexGuestARMState,guest_D7)
408 #define OFFB_D8 offsetof(VexGuestARMState,guest_D8)
409 #define OFFB_D9 offsetof(VexGuestARMState,guest_D9)
410 #define OFFB_D10 offsetof(VexGuestARMState,guest_D10)
411 #define OFFB_D11 offsetof(VexGuestARMState,guest_D11)
412 #define OFFB_D12 offsetof(VexGuestARMState,guest_D12)
413 #define OFFB_D13 offsetof(VexGuestARMState,guest_D13)
414 #define OFFB_D14 offsetof(VexGuestARMState,guest_D14)
415 #define OFFB_D15 offsetof(VexGuestARMState,guest_D15)
416 #define OFFB_D16 offsetof(VexGuestARMState,guest_D16)
417 #define OFFB_D17 offsetof(VexGuestARMState,guest_D17)
418 #define OFFB_D18 offsetof(VexGuestARMState,guest_D18)
419 #define OFFB_D19 offsetof(VexGuestARMState,guest_D19)
420 #define OFFB_D20 offsetof(VexGuestARMState,guest_D20)
421 #define OFFB_D21 offsetof(VexGuestARMState,guest_D21)
422 #define OFFB_D22 offsetof(VexGuestARMState,guest_D22)
423 #define OFFB_D23 offsetof(VexGuestARMState,guest_D23)
424 #define OFFB_D24 offsetof(VexGuestARMState,guest_D24)
425 #define OFFB_D25 offsetof(VexGuestARMState,guest_D25)
426 #define OFFB_D26 offsetof(VexGuestARMState,guest_D26)
427 #define OFFB_D27 offsetof(VexGuestARMState,guest_D27)
428 #define OFFB_D28 offsetof(VexGuestARMState,guest_D28)
429 #define OFFB_D29 offsetof(VexGuestARMState,guest_D29)
430 #define OFFB_D30 offsetof(VexGuestARMState,guest_D30)
431 #define OFFB_D31 offsetof(VexGuestARMState,guest_D31)
433 #define OFFB_FPSCR offsetof(VexGuestARMState,guest_FPSCR)
434 #define OFFB_TPIDRURO offsetof(VexGuestARMState,guest_TPIDRURO)
435 #define OFFB_ITSTATE offsetof(VexGuestARMState,guest_ITSTATE)
436 #define OFFB_QFLAG32 offsetof(VexGuestARMState,guest_QFLAG32)
437 #define OFFB_GEFLAG0 offsetof(VexGuestARMState,guest_GEFLAG0)
438 #define OFFB_GEFLAG1 offsetof(VexGuestARMState,guest_GEFLAG1)
439 #define OFFB_GEFLAG2 offsetof(VexGuestARMState,guest_GEFLAG2)
440 #define OFFB_GEFLAG3 offsetof(VexGuestARMState,guest_GEFLAG3)
443 /* ---------------- Integer registers ---------------- */
445 static Int integerGuestRegOffset ( UInt iregNo )
447 /* Do we care about endianness here? We do if sub-parts of integer
448 registers are accessed, but I don't think that ever happens on
451 case 0: return OFFB_R0;
452 case 1: return OFFB_R1;
453 case 2: return OFFB_R2;
454 case 3: return OFFB_R3;
455 case 4: return OFFB_R4;
456 case 5: return OFFB_R5;
457 case 6: return OFFB_R6;
458 case 7: return OFFB_R7;
459 case 8: return OFFB_R8;
460 case 9: return OFFB_R9;
461 case 10: return OFFB_R10;
462 case 11: return OFFB_R11;
463 case 12: return OFFB_R12;
464 case 13: return OFFB_R13;
465 case 14: return OFFB_R14;
466 case 15: return OFFB_R15T;
471 /* Plain ("low level") read from a reg; no +8 offset magic for r15. */
472 static IRExpr* llGetIReg ( UInt iregNo )
474 vassert(iregNo < 16);
475 return IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 );
478 /* Architected read from a reg in ARM mode. This automagically adds 8
479 to all reads of r15. */
480 static IRExpr* getIRegA ( UInt iregNo )
484 vassert(iregNo < 16);
486 /* If asked for r15, don't read the guest state value, as that
487 may not be up to date in the case where loop unrolling has
488 happened, because the first insn's write to the block is
489 omitted; hence in the 2nd and subsequent unrollings we don't
490 have a correct value in guest r15. Instead produce the
491 constant that we know would be produced at this point. */
492 vassert(0 == (guest_R15_curr_instr_notENC & 3));
493 e = mkU32(guest_R15_curr_instr_notENC + 8);
495 e = IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 );
500 /* Architected read from a reg in Thumb mode. This automagically adds
501 4 to all reads of r15. */
502 static IRExpr* getIRegT ( UInt iregNo )
506 vassert(iregNo < 16);
508 /* Ditto comment in getIReg. */
509 vassert(0 == (guest_R15_curr_instr_notENC & 1));
510 e = mkU32(guest_R15_curr_instr_notENC + 4);
512 e = IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 );
517 /* Plain ("low level") write to a reg; no jump or alignment magic for
519 static void llPutIReg ( UInt iregNo, IRExpr* e )
521 vassert(iregNo < 16);
522 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
523 stmt( IRStmt_Put(integerGuestRegOffset(iregNo), e) );
526 /* Architected write to an integer register in ARM mode. If it is to
527 r15, record info so at the end of this insn's translation, a branch
528 to it can be made. Also handles conditional writes to the
529 register: if guardT == IRTemp_INVALID then the write is
530 unconditional. If writing r15, also 4-align it. */
531 static void putIRegA ( UInt iregNo,
533 IRTemp guardT /* :: Ity_I32, 0 or 1 */,
534 IRJumpKind jk /* if a jump is generated */ )
536 /* if writing r15, force e to be 4-aligned. */
537 // INTERWORKING FIXME. this needs to be relaxed so that
538 // puts caused by LDMxx which load r15 interwork right.
539 // but is no aligned too relaxed?
541 // e = binop(Iop_And32, e, mkU32(~3));
543 /* So, generate either an unconditional or a conditional write to
545 if (guardT == IRTemp_INVALID) {
546 /* unconditional write */
547 llPutIReg( iregNo, e );
550 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
555 // assert against competing r15 updates. Shouldn't
556 // happen; should be ruled out by the instr matching
558 vassert(r15written == False);
559 vassert(r15guard == IRTemp_INVALID);
560 vassert(r15kind == Ijk_Boring);
568 /* Architected write to an integer register in Thumb mode. Writes to
569 r15 are not allowed. Handles conditional writes to the register:
570 if guardT == IRTemp_INVALID then the write is unconditional. */
571 static void putIRegT ( UInt iregNo,
573 IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
575 /* So, generate either an unconditional or a conditional write to
578 vassert(iregNo >= 0 && iregNo <= 14);
579 if (guardT == IRTemp_INVALID) {
580 /* unconditional write */
581 llPutIReg( iregNo, e );
584 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
591 /* Thumb16 and Thumb32 only.
592 Returns true if reg is 13 or 15. Implements the BadReg
593 predicate in the ARM ARM. */
594 static Bool isBadRegT ( UInt r )
598 return r == 13 || r == 15;
602 /* ---------------- Double registers ---------------- */
604 static Int doubleGuestRegOffset ( UInt dregNo )
606 /* Do we care about endianness here? Probably do if we ever get
607 into the situation of dealing with the single-precision VFP
610 case 0: return OFFB_D0;
611 case 1: return OFFB_D1;
612 case 2: return OFFB_D2;
613 case 3: return OFFB_D3;
614 case 4: return OFFB_D4;
615 case 5: return OFFB_D5;
616 case 6: return OFFB_D6;
617 case 7: return OFFB_D7;
618 case 8: return OFFB_D8;
619 case 9: return OFFB_D9;
620 case 10: return OFFB_D10;
621 case 11: return OFFB_D11;
622 case 12: return OFFB_D12;
623 case 13: return OFFB_D13;
624 case 14: return OFFB_D14;
625 case 15: return OFFB_D15;
626 case 16: return OFFB_D16;
627 case 17: return OFFB_D17;
628 case 18: return OFFB_D18;
629 case 19: return OFFB_D19;
630 case 20: return OFFB_D20;
631 case 21: return OFFB_D21;
632 case 22: return OFFB_D22;
633 case 23: return OFFB_D23;
634 case 24: return OFFB_D24;
635 case 25: return OFFB_D25;
636 case 26: return OFFB_D26;
637 case 27: return OFFB_D27;
638 case 28: return OFFB_D28;
639 case 29: return OFFB_D29;
640 case 30: return OFFB_D30;
641 case 31: return OFFB_D31;
646 /* Plain ("low level") read from a VFP Dreg. */
647 static IRExpr* llGetDReg ( UInt dregNo )
649 vassert(dregNo < 32);
650 return IRExpr_Get( doubleGuestRegOffset(dregNo), Ity_F64 );
653 /* Architected read from a VFP Dreg. */
654 static IRExpr* getDReg ( UInt dregNo ) {
655 return llGetDReg( dregNo );
658 /* Plain ("low level") write to a VFP Dreg. */
659 static void llPutDReg ( UInt dregNo, IRExpr* e )
661 vassert(dregNo < 32);
662 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
663 stmt( IRStmt_Put(doubleGuestRegOffset(dregNo), e) );
666 /* Architected write to a VFP Dreg. Handles conditional writes to the
667 register: if guardT == IRTemp_INVALID then the write is
669 static void putDReg ( UInt dregNo,
671 IRTemp guardT /* :: Ity_I32, 0 or 1 */)
673 /* So, generate either an unconditional or a conditional write to
675 if (guardT == IRTemp_INVALID) {
676 /* unconditional write */
677 llPutDReg( dregNo, e );
680 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
686 /* And now exactly the same stuff all over again, but this time
687 taking/returning I64 rather than F64, to support 64-bit Neon
690 /* Plain ("low level") read from a Neon Integer Dreg. */
691 static IRExpr* llGetDRegI64 ( UInt dregNo )
693 vassert(dregNo < 32);
694 return IRExpr_Get( doubleGuestRegOffset(dregNo), Ity_I64 );
697 /* Architected read from a Neon Integer Dreg. */
698 static IRExpr* getDRegI64 ( UInt dregNo ) {
699 return llGetDRegI64( dregNo );
702 /* Plain ("low level") write to a Neon Integer Dreg. */
703 static void llPutDRegI64 ( UInt dregNo, IRExpr* e )
705 vassert(dregNo < 32);
706 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
707 stmt( IRStmt_Put(doubleGuestRegOffset(dregNo), e) );
710 /* Architected write to a Neon Integer Dreg. Handles conditional
711 writes to the register: if guardT == IRTemp_INVALID then the write
713 static void putDRegI64 ( UInt dregNo,
715 IRTemp guardT /* :: Ity_I32, 0 or 1 */)
717 /* So, generate either an unconditional or a conditional write to
719 if (guardT == IRTemp_INVALID) {
720 /* unconditional write */
721 llPutDRegI64( dregNo, e );
723 llPutDRegI64( dregNo,
724 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
725 llGetDRegI64(dregNo),
730 /* ---------------- Quad registers ---------------- */
732 static Int quadGuestRegOffset ( UInt qregNo )
734 /* Do we care about endianness here? Probably do if we ever get
735 into the situation of dealing with the 64 bit Neon registers. */
737 case 0: return OFFB_D0;
738 case 1: return OFFB_D2;
739 case 2: return OFFB_D4;
740 case 3: return OFFB_D6;
741 case 4: return OFFB_D8;
742 case 5: return OFFB_D10;
743 case 6: return OFFB_D12;
744 case 7: return OFFB_D14;
745 case 8: return OFFB_D16;
746 case 9: return OFFB_D18;
747 case 10: return OFFB_D20;
748 case 11: return OFFB_D22;
749 case 12: return OFFB_D24;
750 case 13: return OFFB_D26;
751 case 14: return OFFB_D28;
752 case 15: return OFFB_D30;
757 /* Plain ("low level") read from a Neon Qreg. */
758 static IRExpr* llGetQReg ( UInt qregNo )
760 vassert(qregNo < 16);
761 return IRExpr_Get( quadGuestRegOffset(qregNo), Ity_V128 );
764 /* Architected read from a Neon Qreg. */
765 static IRExpr* getQReg ( UInt qregNo ) {
766 return llGetQReg( qregNo );
769 /* Plain ("low level") write to a Neon Qreg. */
770 static void llPutQReg ( UInt qregNo, IRExpr* e )
772 vassert(qregNo < 16);
773 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
774 stmt( IRStmt_Put(quadGuestRegOffset(qregNo), e) );
777 /* Architected write to a Neon Qreg. Handles conditional writes to the
778 register: if guardT == IRTemp_INVALID then the write is
780 static void putQReg ( UInt qregNo,
782 IRTemp guardT /* :: Ity_I32, 0 or 1 */)
784 /* So, generate either an unconditional or a conditional write to
786 if (guardT == IRTemp_INVALID) {
787 /* unconditional write */
788 llPutQReg( qregNo, e );
791 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
798 /* ---------------- Float registers ---------------- */
800 static Int floatGuestRegOffset ( UInt fregNo )
802 /* Start with the offset of the containing double, and then correct
803 for endianness. Actually this is completely bogus and needs
806 vassert(fregNo < 32);
807 off = doubleGuestRegOffset(fregNo >> 1);
808 if (host_is_bigendian) {
817 /* Plain ("low level") read from a VFP Freg. */
818 static IRExpr* llGetFReg ( UInt fregNo )
820 vassert(fregNo < 32);
821 return IRExpr_Get( floatGuestRegOffset(fregNo), Ity_F32 );
824 /* Architected read from a VFP Freg. */
825 static IRExpr* getFReg ( UInt fregNo ) {
826 return llGetFReg( fregNo );
829 /* Plain ("low level") write to a VFP Freg. */
830 static void llPutFReg ( UInt fregNo, IRExpr* e )
832 vassert(fregNo < 32);
833 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F32);
834 stmt( IRStmt_Put(floatGuestRegOffset(fregNo), e) );
837 /* Architected write to a VFP Freg. Handles conditional writes to the
838 register: if guardT == IRTemp_INVALID then the write is
840 static void putFReg ( UInt fregNo,
842 IRTemp guardT /* :: Ity_I32, 0 or 1 */)
844 /* So, generate either an unconditional or a conditional write to
846 if (guardT == IRTemp_INVALID) {
847 /* unconditional write */
848 llPutFReg( fregNo, e );
851 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
858 /* ---------------- Misc registers ---------------- */
860 static void putMiscReg32 ( UInt gsoffset,
861 IRExpr* e, /* :: Ity_I32 */
862 IRTemp guardT /* :: Ity_I32, 0 or 1 */)
865 case OFFB_FPSCR: break;
866 case OFFB_QFLAG32: break;
867 case OFFB_GEFLAG0: break;
868 case OFFB_GEFLAG1: break;
869 case OFFB_GEFLAG2: break;
870 case OFFB_GEFLAG3: break;
871 default: vassert(0); /* awaiting more cases */
873 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
875 if (guardT == IRTemp_INVALID) {
876 /* unconditional write */
877 stmt(IRStmt_Put(gsoffset, e));
881 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
882 IRExpr_Get(gsoffset, Ity_I32),
889 static IRTemp get_ITSTATE ( void )
892 IRTemp t = newTemp(Ity_I32);
893 assign(t, IRExpr_Get( OFFB_ITSTATE, Ity_I32));
897 static void put_ITSTATE ( IRTemp t )
900 stmt( IRStmt_Put( OFFB_ITSTATE, mkexpr(t)) );
903 static IRTemp get_QFLAG32 ( void )
905 IRTemp t = newTemp(Ity_I32);
906 assign(t, IRExpr_Get( OFFB_QFLAG32, Ity_I32));
910 static void put_QFLAG32 ( IRTemp t, IRTemp condT )
912 putMiscReg32( OFFB_QFLAG32, mkexpr(t), condT );
915 /* Stickily set the 'Q' flag (APSR bit 27) of the APSR (Application Program
916 Status Register) to indicate that overflow or saturation occurred.
917 Nb: t must be zero to denote no saturation, and any nonzero
918 value to indicate saturation. */
919 static void or_into_QFLAG32 ( IRExpr* e, IRTemp condT )
921 IRTemp old = get_QFLAG32();
922 IRTemp nyu = newTemp(Ity_I32);
923 assign(nyu, binop(Iop_Or32, mkexpr(old), e) );
924 put_QFLAG32(nyu, condT);
927 /* Generate code to set APSR.GE[flagNo]. Each fn call sets 1 bit.
928 flagNo: which flag bit to set [3...0]
929 lowbits_to_ignore: 0 = look at all 32 bits
930 8 = look at top 24 bits only
931 16 = look at top 16 bits only
932 31 = look at the top bit only
933 e: input value to be evaluated.
934 The new value is taken from 'e' with the lowest 'lowbits_to_ignore'
935 masked out. If the resulting value is zero then the GE flag is
936 set to 0; any other value sets the flag to 1. */
937 static void put_GEFLAG32 ( Int flagNo, /* 0, 1, 2 or 3 */
938 Int lowbits_to_ignore, /* 0, 8, 16 or 31 */
939 IRExpr* e, /* Ity_I32 */
942 vassert( flagNo >= 0 && flagNo <= 3 );
943 vassert( lowbits_to_ignore == 0 ||
944 lowbits_to_ignore == 8 ||
945 lowbits_to_ignore == 16 ||
946 lowbits_to_ignore == 31 );
947 IRTemp masked = newTemp(Ity_I32);
948 assign(masked, binop(Iop_Shr32, e, mkU8(lowbits_to_ignore)));
951 case 0: putMiscReg32(OFFB_GEFLAG0, mkexpr(masked), condT); break;
952 case 1: putMiscReg32(OFFB_GEFLAG1, mkexpr(masked), condT); break;
953 case 2: putMiscReg32(OFFB_GEFLAG2, mkexpr(masked), condT); break;
954 case 3: putMiscReg32(OFFB_GEFLAG3, mkexpr(masked), condT); break;
959 /* Return the (32-bit, zero-or-nonzero representation scheme) of
960 the specified GE flag. */
961 static IRExpr* get_GEFLAG32( Int flagNo /* 0, 1, 2, 3 */ )
964 case 0: return IRExpr_Get( OFFB_GEFLAG0, Ity_I32 );
965 case 1: return IRExpr_Get( OFFB_GEFLAG1, Ity_I32 );
966 case 2: return IRExpr_Get( OFFB_GEFLAG2, Ity_I32 );
967 case 3: return IRExpr_Get( OFFB_GEFLAG3, Ity_I32 );
972 /* Set all 4 GE flags from the given 32-bit value as follows: GE 3 and
973 2 are set from bit 31 of the value, and GE 1 and 0 are set from bit
974 15 of the value. All other bits are ignored. */
975 static void set_GE_32_10_from_bits_31_15 ( IRTemp t32, IRTemp condT )
977 IRTemp ge10 = newTemp(Ity_I32);
978 IRTemp ge32 = newTemp(Ity_I32);
979 assign(ge10, binop(Iop_And32, mkexpr(t32), mkU32(0x00008000)));
980 assign(ge32, binop(Iop_And32, mkexpr(t32), mkU32(0x80000000)));
981 put_GEFLAG32( 0, 0, mkexpr(ge10), condT );
982 put_GEFLAG32( 1, 0, mkexpr(ge10), condT );
983 put_GEFLAG32( 2, 0, mkexpr(ge32), condT );
984 put_GEFLAG32( 3, 0, mkexpr(ge32), condT );
988 /* Set all 4 GE flags from the given 32-bit value as follows: GE 3
989 from bit 31, GE 2 from bit 23, GE 1 from bit 15, and GE0 from
990 bit 7. All other bits are ignored. */
991 static void set_GE_3_2_1_0_from_bits_31_23_15_7 ( IRTemp t32, IRTemp condT )
993 IRTemp ge0 = newTemp(Ity_I32);
994 IRTemp ge1 = newTemp(Ity_I32);
995 IRTemp ge2 = newTemp(Ity_I32);
996 IRTemp ge3 = newTemp(Ity_I32);
997 assign(ge0, binop(Iop_And32, mkexpr(t32), mkU32(0x00000080)));
998 assign(ge1, binop(Iop_And32, mkexpr(t32), mkU32(0x00008000)));
999 assign(ge2, binop(Iop_And32, mkexpr(t32), mkU32(0x00800000)));
1000 assign(ge3, binop(Iop_And32, mkexpr(t32), mkU32(0x80000000)));
1001 put_GEFLAG32( 0, 0, mkexpr(ge0), condT );
1002 put_GEFLAG32( 1, 0, mkexpr(ge1), condT );
1003 put_GEFLAG32( 2, 0, mkexpr(ge2), condT );
1004 put_GEFLAG32( 3, 0, mkexpr(ge3), condT );
1008 /* ---------------- FPSCR stuff ---------------- */
1010 /* Generate IR to get hold of the rounding mode bits in FPSCR, and
1011 convert them to IR format. Bind the final result to the
1013 static IRTemp /* :: Ity_I32 */ mk_get_IR_rounding_mode ( void )
1015 /* The ARMvfp encoding for rounding mode bits is:
1020 We need to convert that to the IR encoding:
1021 00 to nearest (the default)
1025 Which can be done by swapping bits 0 and 1.
1026 The rmode bits are at 23:22 in FPSCR.
1028 IRTemp armEncd = newTemp(Ity_I32);
1029 IRTemp swapped = newTemp(Ity_I32);
1030 /* Fish FPSCR[23:22] out, and slide to bottom. Doesn't matter that
1031 we don't zero out bits 24 and above, since the assignment to
1032 'swapped' will mask them out anyway. */
1034 binop(Iop_Shr32, IRExpr_Get(OFFB_FPSCR, Ity_I32), mkU8(22)));
1035 /* Now swap them. */
1039 binop(Iop_Shl32, mkexpr(armEncd), mkU8(1)),
1042 binop(Iop_Shr32, mkexpr(armEncd), mkU8(1)),
1049 /*------------------------------------------------------------*/
1050 /*--- Helpers for flag handling and conditional insns ---*/
1051 /*------------------------------------------------------------*/
1053 static HChar* name_ARMCondcode ( ARMCondcode cond )
1056 case ARMCondEQ: return "{eq}";
1057 case ARMCondNE: return "{ne}";
1058 case ARMCondHS: return "{hs}"; // or 'cs'
1059 case ARMCondLO: return "{lo}"; // or 'cc'
1060 case ARMCondMI: return "{mi}";
1061 case ARMCondPL: return "{pl}";
1062 case ARMCondVS: return "{vs}";
1063 case ARMCondVC: return "{vc}";
1064 case ARMCondHI: return "{hi}";
1065 case ARMCondLS: return "{ls}";
1066 case ARMCondGE: return "{ge}";
1067 case ARMCondLT: return "{lt}";
1068 case ARMCondGT: return "{gt}";
1069 case ARMCondLE: return "{le}";
1070 case ARMCondAL: return ""; // {al}: is the default
1071 case ARMCondNV: return "{nv}";
1072 default: vpanic("name_ARMCondcode");
1075 /* and a handy shorthand for it */
1076 static HChar* nCC ( ARMCondcode cond ) {
1077 return name_ARMCondcode(cond);
1081 /* Build IR to calculate some particular condition from stored
1082 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression of type
1083 Ity_I32, suitable for narrowing. Although the return type is
1084 Ity_I32, the returned value is either 0 or 1. 'cond' must be
1085 :: Ity_I32 and must denote the condition to compute in
1086 bits 7:4, and be zero everywhere else.
1088 static IRExpr* mk_armg_calculate_condition_dyn ( IRExpr* cond )
1090 vassert(typeOfIRExpr(irsb->tyenv, cond) == Ity_I32);
1091 /* And 'cond' had better produce a value in which only bits 7:4 are
1092 nonzero. However, obviously we can't assert for that. */
1094 /* So what we're constructing for the first argument is
1095 "(cond << 4) | stored-operation".
1096 However, as per comments above, 'cond' must be supplied
1097 pre-shifted to this function.
1099 This pairing scheme requires that the ARM_CC_OP_ values all fit
1100 in 4 bits. Hence we are passing a (COND, OP) pair in the lowest
1101 8 bits of the first argument. */
1104 binop(Iop_Or32, IRExpr_Get(OFFB_CC_OP, Ity_I32), cond),
1105 IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1106 IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1107 IRExpr_Get(OFFB_CC_NDEP, Ity_I32)
1113 "armg_calculate_condition", &armg_calculate_condition,
1117 /* Exclude the requested condition, OP and NDEP from definedness
1118 checking. We're only interested in DEP1 and DEP2. */
1119 call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1124 /* Build IR to calculate some particular condition from stored
1125 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression of type
1126 Ity_I32, suitable for narrowing. Although the return type is
1127 Ity_I32, the returned value is either 0 or 1.
1129 static IRExpr* mk_armg_calculate_condition ( ARMCondcode cond )
1131 /* First arg is "(cond << 4) | condition". This requires that the
1132 ARM_CC_OP_ values all fit in 4 bits. Hence we are passing a
1133 (COND, OP) pair in the lowest 8 bits of the first argument. */
1134 vassert(cond >= 0 && cond <= 15);
1135 return mk_armg_calculate_condition_dyn( mkU32(cond << 4) );
1139 /* Build IR to calculate just the carry flag from stored
1140 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression ::
1142 static IRExpr* mk_armg_calculate_flag_c ( void )
1145 = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP, Ity_I32),
1146 IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1147 IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1148 IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
1153 "armg_calculate_flag_c", &armg_calculate_flag_c,
1156 /* Exclude OP and NDEP from definedness checking. We're only
1157 interested in DEP1 and DEP2. */
1158 call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1163 /* Build IR to calculate just the overflow flag from stored
1164 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression ::
1166 static IRExpr* mk_armg_calculate_flag_v ( void )
1169 = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP, Ity_I32),
1170 IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1171 IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1172 IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
1177 "armg_calculate_flag_v", &armg_calculate_flag_v,
1180 /* Exclude OP and NDEP from definedness checking. We're only
1181 interested in DEP1 and DEP2. */
1182 call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1187 /* Build IR to calculate N Z C V in bits 31:28 of the
1189 static IRExpr* mk_armg_calculate_flags_nzcv ( void )
1192 = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP, Ity_I32),
1193 IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1194 IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1195 IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
1200 "armg_calculate_flags_nzcv", &armg_calculate_flags_nzcv,
1203 /* Exclude OP and NDEP from definedness checking. We're only
1204 interested in DEP1 and DEP2. */
1205 call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1209 static IRExpr* mk_armg_calculate_flag_qc ( IRExpr* resL, IRExpr* resR, Bool Q )
1213 IRExpr *call1, *call2, *res;
1216 args1 = mkIRExprVec_4 ( binop(Iop_GetElem32x4, resL, mkU8(0)),
1217 binop(Iop_GetElem32x4, resL, mkU8(1)),
1218 binop(Iop_GetElem32x4, resR, mkU8(0)),
1219 binop(Iop_GetElem32x4, resR, mkU8(1)) );
1220 args2 = mkIRExprVec_4 ( binop(Iop_GetElem32x4, resL, mkU8(2)),
1221 binop(Iop_GetElem32x4, resL, mkU8(3)),
1222 binop(Iop_GetElem32x4, resR, mkU8(2)),
1223 binop(Iop_GetElem32x4, resR, mkU8(3)) );
1225 args1 = mkIRExprVec_4 ( binop(Iop_GetElem32x2, resL, mkU8(0)),
1226 binop(Iop_GetElem32x2, resL, mkU8(1)),
1227 binop(Iop_GetElem32x2, resR, mkU8(0)),
1228 binop(Iop_GetElem32x2, resR, mkU8(1)) );
1232 call1 = mkIRExprCCall(
1235 "armg_calculate_flag_qc", &armg_calculate_flag_qc,
1239 call2 = mkIRExprCCall(
1242 "armg_calculate_flag_qc", &armg_calculate_flag_qc,
1247 res = binop(Iop_Or32, call1, call2);
1253 res = unop(Iop_1Uto32,
1272 res = unop(Iop_1Uto32,
1287 // FIXME: this is named wrongly .. looks like a sticky set of
1288 // QC, not a write to it.
1289 static void setFlag_QC ( IRExpr* resL, IRExpr* resR, Bool Q,
1292 putMiscReg32 (OFFB_FPSCR,
1294 IRExpr_Get(OFFB_FPSCR, Ity_I32),
1296 mk_armg_calculate_flag_qc(resL, resR, Q),
1301 /* Build IR to conditionally set the flags thunk. As with putIReg, if
1302 guard is IRTemp_INVALID then it's unconditional, else it holds a
1303 condition :: Ity_I32. */
1305 void setFlags_D1_D2_ND ( UInt cc_op, IRTemp t_dep1,
1306 IRTemp t_dep2, IRTemp t_ndep,
1307 IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1310 vassert(typeOfIRTemp(irsb->tyenv, t_dep1 == Ity_I32));
1311 vassert(typeOfIRTemp(irsb->tyenv, t_dep2 == Ity_I32));
1312 vassert(typeOfIRTemp(irsb->tyenv, t_ndep == Ity_I32));
1313 vassert(cc_op >= ARMG_CC_OP_COPY && cc_op < ARMG_CC_OP_NUMBER);
1314 if (guardT == IRTemp_INVALID) {
1316 stmt( IRStmt_Put( OFFB_CC_OP, mkU32(cc_op) ));
1317 stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(t_dep1) ));
1318 stmt( IRStmt_Put( OFFB_CC_DEP2, mkexpr(t_dep2) ));
1319 stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(t_ndep) ));
1322 c8 = newTemp(Ity_I8);
1323 assign( c8, unop(Iop_32to8, mkexpr(guardT)) );
1326 IRExpr_Mux0X( mkexpr(c8),
1327 IRExpr_Get(OFFB_CC_OP, Ity_I32),
1331 IRExpr_Mux0X( mkexpr(c8),
1332 IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1336 IRExpr_Mux0X( mkexpr(c8),
1337 IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1341 IRExpr_Mux0X( mkexpr(c8),
1342 IRExpr_Get(OFFB_CC_NDEP, Ity_I32),
1348 /* Minor variant of the above that sets NDEP to zero (if it
1350 static void setFlags_D1_D2 ( UInt cc_op, IRTemp t_dep1,
1352 IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1354 IRTemp z32 = newTemp(Ity_I32);
1355 assign( z32, mkU32(0) );
1356 setFlags_D1_D2_ND( cc_op, t_dep1, t_dep2, z32, guardT );
1360 /* Minor variant of the above that sets DEP2 to zero (if it
1362 static void setFlags_D1_ND ( UInt cc_op, IRTemp t_dep1,
1364 IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1366 IRTemp z32 = newTemp(Ity_I32);
1367 assign( z32, mkU32(0) );
1368 setFlags_D1_D2_ND( cc_op, t_dep1, z32, t_ndep, guardT );
1372 /* Minor variant of the above that sets DEP2 and NDEP to zero (if it
1373 sets them at all) */
1374 static void setFlags_D1 ( UInt cc_op, IRTemp t_dep1,
1375 IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1377 IRTemp z32 = newTemp(Ity_I32);
1378 assign( z32, mkU32(0) );
1379 setFlags_D1_D2_ND( cc_op, t_dep1, z32, z32, guardT );
1384 /* Generate a side-exit to the next instruction, if the given guard
1385 expression :: Ity_I32 is 0 (note! the side exit is taken if the
1386 condition is false!) This is used to skip over conditional
1387 instructions which we can't generate straight-line code for, either
1388 because they are too complex or (more likely) they potentially
1389 generate exceptions.
1391 static void mk_skip_over_A32_if_cond_is_false (
1392 IRTemp guardT /* :: Ity_I32, 0 or 1 */
1396 vassert(guardT != IRTemp_INVALID);
1397 vassert(0 == (guest_R15_curr_instr_notENC & 3));
1399 unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
1401 IRConst_U32(toUInt(guest_R15_curr_instr_notENC + 4))
1406 /* ditto, but jump over a 16-bit thumb insn */
1407 static void mk_skip_over_T16_if_cond_is_false (
1408 IRTemp guardT /* :: Ity_I32, 0 or 1 */
1412 vassert(guardT != IRTemp_INVALID);
1413 vassert(0 == (guest_R15_curr_instr_notENC & 1));
1415 unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
1417 IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 2) | 1))
1423 /* ditto, but jump over a 32-bit thumb insn */
1424 static void mk_skip_over_T32_if_cond_is_false (
1425 IRTemp guardT /* :: Ity_I32, 0 or 1 */
1429 vassert(guardT != IRTemp_INVALID);
1430 vassert(0 == (guest_R15_curr_instr_notENC & 1));
1432 unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
1434 IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 4) | 1))
1439 /* Thumb16 and Thumb32 only
1440 Generate a SIGILL followed by a restart of the current instruction
1441 if the given temp is nonzero. */
1442 static void gen_SIGILL_T_if_nonzero ( IRTemp t /* :: Ity_I32 */ )
1445 vassert(t != IRTemp_INVALID);
1446 vassert(0 == (guest_R15_curr_instr_notENC & 1));
1449 binop(Iop_CmpNE32, mkexpr(t), mkU32(0)),
1451 IRConst_U32(toUInt(guest_R15_curr_instr_notENC | 1))
1457 /* Inspect the old_itstate, and generate a SIGILL if it indicates that
1458 we are currently in an IT block and are not the last in the block.
1459 This also rolls back guest_ITSTATE to its old value before the exit
1460 and restores it to its new value afterwards. This is so that if
1461 the exit is taken, we have an up to date version of ITSTATE
1462 available. Without doing that, we have no hope of making precise
1464 static void gen_SIGILL_T_if_in_but_NLI_ITBlock (
1465 IRTemp old_itstate /* :: Ity_I32 */,
1466 IRTemp new_itstate /* :: Ity_I32 */
1470 put_ITSTATE(old_itstate); // backout
1471 IRTemp guards_for_next3 = newTemp(Ity_I32);
1472 assign(guards_for_next3,
1473 binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
1474 gen_SIGILL_T_if_nonzero(guards_for_next3);
1475 put_ITSTATE(new_itstate); //restore
1479 /* Simpler version of the above, which generates a SIGILL if
1480 we're anywhere within an IT block. */
1481 static void gen_SIGILL_T_if_in_ITBlock (
1482 IRTemp old_itstate /* :: Ity_I32 */,
1483 IRTemp new_itstate /* :: Ity_I32 */
1486 put_ITSTATE(old_itstate); // backout
1487 gen_SIGILL_T_if_nonzero(old_itstate);
1488 put_ITSTATE(new_itstate); //restore
1492 /* Generate an APSR value, from the NZCV thunk, and
1493 from QFLAG32 and GEFLAG0 .. GEFLAG3. */
1494 static IRTemp synthesise_APSR ( void )
1496 IRTemp res1 = newTemp(Ity_I32);
1498 assign( res1, mk_armg_calculate_flags_nzcv() );
1499 // OR in the Q value
1500 IRTemp res2 = newTemp(Ity_I32);
1508 mkexpr(get_QFLAG32()),
1510 mkU8(ARMG_CC_SHIFT_Q)))
1514 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(0), mkU32(0)));
1516 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(1), mkU32(0)));
1518 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(2), mkU32(0)));
1520 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(3), mkU32(0)));
1521 IRTemp res3 = newTemp(Ity_I32);
1527 binop(Iop_Shl32, ge0, mkU8(16)),
1528 binop(Iop_Shl32, ge1, mkU8(17))),
1530 binop(Iop_Shl32, ge2, mkU8(18)),
1531 binop(Iop_Shl32, ge3, mkU8(19))) )));
1536 /* and the inverse transformation: given an APSR value,
1537 set the NZCV thunk, the Q flag, and the GE flags. */
1538 static void desynthesise_APSR ( Bool write_nzcvq, Bool write_ge,
1539 IRTemp apsrT, IRTemp condT )
1541 vassert(write_nzcvq || write_ge);
1544 IRTemp immT = newTemp(Ity_I32);
1545 assign(immT, binop(Iop_And32, mkexpr(apsrT), mkU32(0xF0000000)) );
1546 setFlags_D1(ARMG_CC_OP_COPY, immT, condT);
1548 IRTemp qnewT = newTemp(Ity_I32);
1549 assign(qnewT, binop(Iop_And32, mkexpr(apsrT), mkU32(ARMG_CC_MASK_Q)));
1550 put_QFLAG32(qnewT, condT);
1554 put_GEFLAG32(0, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<16)),
1556 put_GEFLAG32(1, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<17)),
1558 put_GEFLAG32(2, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<18)),
1560 put_GEFLAG32(3, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<19)),
1566 /*------------------------------------------------------------*/
1567 /*--- Helpers for saturation ---*/
1568 /*------------------------------------------------------------*/
1570 /* FIXME: absolutely the only diff. between (a) armUnsignedSatQ and
1571 (b) armSignedSatQ is that in (a) the floor is set to 0, whereas in
1572 (b) the floor is computed from the value of imm5. these two fnsn
1573 should be commoned up. */
1575 /* UnsignedSatQ(): 'clamp' each value so it lies between 0 <= x <= (2^N)-1
1576 Optionally return flag resQ saying whether saturation occurred.
1577 See definition in manual, section A2.2.1, page 41
1578 (bits(N), boolean) UnsignedSatQ( integer i, integer N )
1580 if ( i > (2^N)-1 ) { result = (2^N)-1; saturated = TRUE; }
1581 elsif ( i < 0 ) { result = 0; saturated = TRUE; }
1582 else { result = i; saturated = FALSE; }
1583 return ( result<N-1:0>, saturated );
1586 static void armUnsignedSatQ( IRTemp* res, /* OUT - Ity_I32 */
1587 IRTemp* resQ, /* OUT - Ity_I32 */
1588 IRTemp regT, /* value to clamp - Ity_I32 */
1589 UInt imm5 ) /* saturation ceiling */
1591 UInt ceil = (1 << imm5) - 1; // (2^imm5)-1
1594 IRTemp node0 = newTemp(Ity_I32);
1595 IRTemp node1 = newTemp(Ity_I32);
1596 IRTemp node2 = newTemp(Ity_I1);
1597 IRTemp node3 = newTemp(Ity_I32);
1598 IRTemp node4 = newTemp(Ity_I32);
1599 IRTemp node5 = newTemp(Ity_I1);
1600 IRTemp node6 = newTemp(Ity_I32);
1602 assign( node0, mkexpr(regT) );
1603 assign( node1, mkU32(ceil) );
1604 assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
1605 assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
1608 assign( node4, mkU32(floor) );
1609 assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
1610 assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
1613 assign( *res, mkexpr(node6) );
1615 /* if saturation occurred, then resQ is set to some nonzero value
1616 if sat did not occur, resQ is guaranteed to be zero. */
1618 assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
1623 /* SignedSatQ(): 'clamp' each value so it lies between -2^N <= x <= (2^N) - 1
1624 Optionally return flag resQ saying whether saturation occurred.
1625 - see definition in manual, section A2.2.1, page 41
1626 (bits(N), boolean ) SignedSatQ( integer i, integer N )
1628 if ( i > 2^(N-1) - 1 ) { result = 2^(N-1) - 1; saturated = TRUE; }
1629 elsif ( i < -(2^(N-1)) ) { result = -(2^(N-1)); saturated = FALSE; }
1630 else { result = i; saturated = FALSE; }
1631 return ( result[N-1:0], saturated );
1634 static void armSignedSatQ( IRTemp regT, /* value to clamp - Ity_I32 */
1635 UInt imm5, /* saturation ceiling */
1636 IRTemp* res, /* OUT - Ity_I32 */
1637 IRTemp* resQ ) /* OUT - Ity_I32 */
1639 Int ceil = (1 << (imm5-1)) - 1; // (2^(imm5-1))-1
1640 Int floor = -(1 << (imm5-1)); // -(2^(imm5-1))
1642 IRTemp node0 = newTemp(Ity_I32);
1643 IRTemp node1 = newTemp(Ity_I32);
1644 IRTemp node2 = newTemp(Ity_I1);
1645 IRTemp node3 = newTemp(Ity_I32);
1646 IRTemp node4 = newTemp(Ity_I32);
1647 IRTemp node5 = newTemp(Ity_I1);
1648 IRTemp node6 = newTemp(Ity_I32);
1650 assign( node0, mkexpr(regT) );
1651 assign( node1, mkU32(ceil) );
1652 assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
1653 assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
1654 mkexpr(node0), mkexpr(node1) ) );
1655 assign( node4, mkU32(floor) );
1656 assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
1657 assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
1658 mkexpr(node3), mkexpr(node4) ) );
1659 assign( *res, mkexpr(node6) );
1661 /* if saturation occurred, then resQ is set to some nonzero value
1662 if sat did not occur, resQ is guaranteed to be zero. */
1664 assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
1669 /* Compute a value 0 :: I32 or 1 :: I32, indicating whether signed
1670 overflow occurred for 32-bit addition. Needs both args and the
1673 IRExpr* signed_overflow_after_Add32 ( IRExpr* resE,
1674 IRTemp argL, IRTemp argR )
1676 IRTemp res = newTemp(Ity_I32);
1681 binop( Iop_Xor32, mkexpr(res), mkexpr(argL) ),
1682 binop( Iop_Xor32, mkexpr(res), mkexpr(argR) )),
1687 /*------------------------------------------------------------*/
1688 /*--- Larger helpers ---*/
1689 /*------------------------------------------------------------*/
1691 /* Compute both the result and new C flag value for a LSL by an imm5
1692 or by a register operand. May generate reads of the old C value
1693 (hence only safe to use before any writes to guest state happen).
1694 Are factored out so can be used by both ARM and Thumb.
1696 Note that in compute_result_and_C_after_{LSL,LSR,ASR}_by{imm5,reg},
1697 "res" (the result) is a.k.a. "shop", shifter operand
1698 "newC" (the new C) is a.k.a. "shco", shifter carry out
1700 The calling convention for res and newC is a bit funny. They could
1701 be passed by value, but instead are passed by ref.
1703 The C (shco) value computed must be zero in bits 31:1, as the IR
1704 optimisations for flag handling (guest_arm_spechelper) rely on
1705 that, and the slow-path handlers (armg_calculate_flags_nzcv) assert
1706 for it. Same applies to all these functions that compute shco
1707 after a shift or rotate, not just this one.
1710 static void compute_result_and_C_after_LSL_by_imm5 (
1714 IRTemp rMt, UInt shift_amt, /* operands */
1715 UInt rM /* only for debug printing */
1718 if (shift_amt == 0) {
1720 assign( *newC, mk_armg_calculate_flag_c() );
1722 assign( *res, mkexpr(rMt) );
1723 DIS(buf, "r%u", rM);
1725 vassert(shift_amt >= 1 && shift_amt <= 31);
1729 binop(Iop_Shr32, mkexpr(rMt),
1730 mkU8(32 - shift_amt)),
1734 binop(Iop_Shl32, mkexpr(rMt), mkU8(shift_amt)) );
1735 DIS(buf, "r%u, LSL #%u", rM, shift_amt);
1740 static void compute_result_and_C_after_LSL_by_reg (
1744 IRTemp rMt, IRTemp rSt, /* operands */
1745 UInt rM, UInt rS /* only for debug printing */
1748 // shift left in range 0 .. 255
1750 // res = amt < 32 ? Rm << amt : 0
1751 // newC = amt == 0 ? oldC :
1752 // amt in 1..32 ? Rm[32-amt] : 0
1753 IRTemp amtT = newTemp(Ity_I32);
1754 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
1762 /* About the best you can do is pray that iropt is able
1763 to nuke most or all of the following junk. */
1764 IRTemp oldC = newTemp(Ity_I32);
1765 assign(oldC, mk_armg_calculate_flag_c() );
1770 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
1773 binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
1794 // (Rm << (Rs & 31)) & (((Rs & 255) - 32) >>s 31)
1795 // Lhs of the & limits the shift to 31 bits, so as to
1796 // give known IR semantics. Rhs of the & is all 1s for
1797 // Rs <= 31 and all 0s for Rs >= 32.
1805 binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
1811 DIS(buf, "r%u, LSL r%u", rM, rS);
1815 static void compute_result_and_C_after_LSR_by_imm5 (
1819 IRTemp rMt, UInt shift_amt, /* operands */
1820 UInt rM /* only for debug printing */
1823 if (shift_amt == 0) {
1824 // conceptually a 32-bit shift, however:
1830 binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
1833 assign( *res, mkU32(0) );
1834 DIS(buf, "r%u, LSR #0(a.k.a. 32)", rM);
1836 // shift in range 1..31
1837 // res = Rm >>u shift_amt
1838 // newC = Rm[shift_amt - 1]
1839 vassert(shift_amt >= 1 && shift_amt <= 31);
1843 binop(Iop_Shr32, mkexpr(rMt),
1844 mkU8(shift_amt - 1)),
1848 binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)) );
1849 DIS(buf, "r%u, LSR #%u", rM, shift_amt);
1854 static void compute_result_and_C_after_LSR_by_reg (
1858 IRTemp rMt, IRTemp rSt, /* operands */
1859 UInt rM, UInt rS /* only for debug printing */
1862 // shift right in range 0 .. 255
1864 // res = amt < 32 ? Rm >>u amt : 0
1865 // newC = amt == 0 ? oldC :
1866 // amt in 1..32 ? Rm[amt-1] : 0
1867 IRTemp amtT = newTemp(Ity_I32);
1868 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
1876 IRTemp oldC = newTemp(Ity_I32);
1877 assign(oldC, mk_armg_calculate_flag_c() );
1882 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
1885 binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
1906 // (Rm >>u (Rs & 31)) & (((Rs & 255) - 32) >>s 31)
1907 // Lhs of the & limits the shift to 31 bits, so as to
1908 // give known IR semantics. Rhs of the & is all 1s for
1909 // Rs <= 31 and all 0s for Rs >= 32.
1917 binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
1923 DIS(buf, "r%u, LSR r%u", rM, rS);
1927 static void compute_result_and_C_after_ASR_by_imm5 (
1931 IRTemp rMt, UInt shift_amt, /* operands */
1932 UInt rM /* only for debug printing */
1935 if (shift_amt == 0) {
1936 // conceptually a 32-bit shift, however:
1942 binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
1945 assign( *res, binop(Iop_Sar32, mkexpr(rMt), mkU8(31)) );
1946 DIS(buf, "r%u, ASR #0(a.k.a. 32)", rM);
1948 // shift in range 1..31
1949 // res = Rm >>s shift_amt
1950 // newC = Rm[shift_amt - 1]
1951 vassert(shift_amt >= 1 && shift_amt <= 31);
1955 binop(Iop_Shr32, mkexpr(rMt),
1956 mkU8(shift_amt - 1)),
1960 binop(Iop_Sar32, mkexpr(rMt), mkU8(shift_amt)) );
1961 DIS(buf, "r%u, ASR #%u", rM, shift_amt);
1966 static void compute_result_and_C_after_ASR_by_reg (
1970 IRTemp rMt, IRTemp rSt, /* operands */
1971 UInt rM, UInt rS /* only for debug printing */
1974 // arithmetic shift right in range 0 .. 255
1976 // res = amt < 32 ? Rm >>s amt : Rm >>s 31
1977 // newC = amt == 0 ? oldC :
1978 // amt in 1..32 ? Rm[amt-1] : Rm[31]
1979 IRTemp amtT = newTemp(Ity_I32);
1980 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
1988 IRTemp oldC = newTemp(Ity_I32);
1989 assign(oldC, mk_armg_calculate_flag_c() );
1994 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
1997 binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
2024 // (Rm >>s (amt <u 32 ? amt : 31))
2035 binop(Iop_CmpLT32U, mkexpr(amtT), mkU32(32))),
2038 DIS(buf, "r%u, ASR r%u", rM, rS);
2042 static void compute_result_and_C_after_ROR_by_reg (
2046 IRTemp rMt, IRTemp rSt, /* operands */
2047 UInt rM, UInt rS /* only for debug printing */
2050 // rotate right in range 0 .. 255
2052 // shop = Rm `ror` (amt & 31)
2053 // shco = amt == 0 ? oldC : Rm[(amt-1) & 31]
2054 IRTemp amtT = newTemp(Ity_I32);
2055 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
2056 IRTemp amt5T = newTemp(Ity_I32);
2057 assign( amt5T, binop(Iop_And32, mkexpr(rSt), mkU32(31)) );
2058 IRTemp oldC = newTemp(Ity_I32);
2059 assign(oldC, mk_armg_calculate_flag_c() );
2064 unop(Iop_32to8, mkexpr(amtT)),
2087 unop(Iop_32to8, mkexpr(amt5T)), mkexpr(rMt),
2091 unop(Iop_32to8, mkexpr(amt5T))
2096 binop(Iop_Sub32, mkU32(32), mkexpr(amt5T))
2102 DIS(buf, "r%u, ROR r#%u", rM, rS);
2106 /* Generate an expression corresponding to the immediate-shift case of
2107 a shifter operand. This is used both for ARM and Thumb2.
2109 Bind it to a temporary, and return that via *res. If newC is
2110 non-NULL, also compute a value for the shifter's carry out (in the
2111 LSB of a word), bind it to a temporary, and return that via *shco.
2113 Generates GETs from the guest state and is therefore not safe to
2114 use once we start doing PUTs to it, for any given instruction.
2116 'how' is encoded thusly:
2117 00b LSL, 01b LSR, 10b ASR, 11b ROR
2118 Most but not all ARM and Thumb integer insns use this encoding.
2119 Be careful to ensure the right value is passed here.
2121 static void compute_result_and_C_after_shift_by_imm5 (
2124 /*OUT*/IRTemp* newC,
2125 IRTemp rMt, /* reg to shift */
2126 UInt how, /* what kind of shift */
2127 UInt shift_amt, /* shift amount (0..31) */
2128 UInt rM /* only for debug printing */
2131 vassert(shift_amt < 32);
2137 compute_result_and_C_after_LSL_by_imm5(
2138 buf, res, newC, rMt, shift_amt, rM
2143 compute_result_and_C_after_LSR_by_imm5(
2144 buf, res, newC, rMt, shift_amt, rM
2149 compute_result_and_C_after_ASR_by_imm5(
2150 buf, res, newC, rMt, shift_amt, rM
2155 if (shift_amt == 0) {
2156 IRTemp oldcT = newTemp(Ity_I32);
2157 // rotate right 1 bit through carry (?)
2158 // RRX -- described at ARM ARM A5-17
2159 // res = (oldC << 31) | (Rm >>u 1)
2163 binop(Iop_And32, mkexpr(rMt), mkU32(1)));
2165 assign( oldcT, mk_armg_calculate_flag_c() );
2168 binop(Iop_Shl32, mkexpr(oldcT), mkU8(31)),
2169 binop(Iop_Shr32, mkexpr(rMt), mkU8(1))) );
2170 DIS(buf, "r%u, RRX", rM);
2172 // rotate right in range 1..31
2173 // res = Rm `ror` shift_amt
2174 // newC = Rm[shift_amt - 1]
2175 vassert(shift_amt >= 1 && shift_amt <= 31);
2179 binop(Iop_Shr32, mkexpr(rMt),
2180 mkU8(shift_amt - 1)),
2185 binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)),
2186 binop(Iop_Shl32, mkexpr(rMt),
2187 mkU8(32-shift_amt))));
2188 DIS(buf, "r%u, ROR #%u", rM, shift_amt);
2199 /* Generate an expression corresponding to the register-shift case of
2200 a shifter operand. This is used both for ARM and Thumb2.
2202 Bind it to a temporary, and return that via *res. If newC is
2203 non-NULL, also compute a value for the shifter's carry out (in the
2204 LSB of a word), bind it to a temporary, and return that via *shco.
2206 Generates GETs from the guest state and is therefore not safe to
2207 use once we start doing PUTs to it, for any given instruction.
2209 'how' is encoded thusly:
2210 00b LSL, 01b LSR, 10b ASR, 11b ROR
2211 Most but not all ARM and Thumb integer insns use this encoding.
2212 Be careful to ensure the right value is passed here.
2214 static void compute_result_and_C_after_shift_by_reg (
2217 /*OUT*/IRTemp* newC,
2218 IRTemp rMt, /* reg to shift */
2219 UInt how, /* what kind of shift */
2220 IRTemp rSt, /* shift amount */
2221 UInt rM, /* only for debug printing */
2222 UInt rS /* only for debug printing */
2228 compute_result_and_C_after_LSL_by_reg(
2229 buf, res, newC, rMt, rSt, rM, rS
2234 compute_result_and_C_after_LSR_by_reg(
2235 buf, res, newC, rMt, rSt, rM, rS
2240 compute_result_and_C_after_ASR_by_reg(
2241 buf, res, newC, rMt, rSt, rM, rS
2246 compute_result_and_C_after_ROR_by_reg(
2247 buf, res, newC, rMt, rSt, rM, rS
2258 /* Generate an expression corresponding to a shifter_operand, bind it
2259 to a temporary, and return that via *shop. If shco is non-NULL,
2260 also compute a value for the shifter's carry out (in the LSB of a
2261 word), bind it to a temporary, and return that via *shco.
2263 If for some reason we can't come up with a shifter operand (missing
2264 case? not really a shifter operand?) return False.
2266 Generates GETs from the guest state and is therefore not safe to
2267 use once we start doing PUTs to it, for any given instruction.
2269 For ARM insns only; not for Thumb.
2271 static Bool mk_shifter_operand ( UInt insn_25, UInt insn_11_0,
2272 /*OUT*/IRTemp* shop,
2273 /*OUT*/IRTemp* shco,
2276 UInt insn_4 = (insn_11_0 >> 4) & 1;
2277 UInt insn_7 = (insn_11_0 >> 7) & 1;
2278 vassert(insn_25 <= 0x1);
2279 vassert(insn_11_0 <= 0xFFF);
2281 vassert(shop && *shop == IRTemp_INVALID);
2282 *shop = newTemp(Ity_I32);
2285 vassert(*shco == IRTemp_INVALID);
2286 *shco = newTemp(Ity_I32);
2289 /* 32-bit immediate */
2292 /* immediate: (7:0) rotated right by 2 * (11:8) */
2293 UInt imm = (insn_11_0 >> 0) & 0xFF;
2294 UInt rot = 2 * ((insn_11_0 >> 8) & 0xF);
2296 imm = ROR32(imm, rot);
2299 assign( *shco, mk_armg_calculate_flag_c() );
2301 assign( *shco, mkU32( (imm >> 31) & 1 ) );
2304 DIS(buf, "#0x%x", imm);
2305 assign( *shop, mkU32(imm) );
2309 /* Shift/rotate by immediate */
2311 if (insn_25 == 0 && insn_4 == 0) {
2312 /* Rm (3:0) shifted (6:5) by immediate (11:7) */
2313 UInt shift_amt = (insn_11_0 >> 7) & 0x1F;
2314 UInt rM = (insn_11_0 >> 0) & 0xF;
2315 UInt how = (insn_11_0 >> 5) & 3;
2316 /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
2317 IRTemp rMt = newTemp(Ity_I32);
2318 assign(rMt, getIRegA(rM));
2320 vassert(shift_amt <= 31);
2322 compute_result_and_C_after_shift_by_imm5(
2323 buf, shop, shco, rMt, how, shift_amt, rM
2328 /* Shift/rotate by register */
2329 if (insn_25 == 0 && insn_4 == 1) {
2330 /* Rm (3:0) shifted (6:5) by Rs (11:8) */
2331 UInt rM = (insn_11_0 >> 0) & 0xF;
2332 UInt rS = (insn_11_0 >> 8) & 0xF;
2333 UInt how = (insn_11_0 >> 5) & 3;
2334 /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
2335 IRTemp rMt = newTemp(Ity_I32);
2336 IRTemp rSt = newTemp(Ity_I32);
2339 return False; /* not really a shifter operand */
2341 assign(rMt, getIRegA(rM));
2342 assign(rSt, getIRegA(rS));
2344 compute_result_and_C_after_shift_by_reg(
2345 buf, shop, shco, rMt, how, rSt, rM, rS
2350 vex_printf("mk_shifter_operand(0x%x,0x%x)\n", insn_25, insn_11_0 );
2357 IRExpr* mk_EA_reg_plusminus_imm12 ( UInt rN, UInt bU, UInt imm12,
2362 vassert(imm12 < 0x1000);
2363 UChar opChar = bU == 1 ? '+' : '-';
2364 DIS(buf, "[r%u, #%c%u]", rN, opChar, imm12);
2366 binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
2373 NB: This is "DecodeImmShift" in newer versions of the the ARM ARM.
2376 IRExpr* mk_EA_reg_plusminus_shifted_reg ( UInt rN, UInt bU, UInt rM,
2377 UInt sh2, UInt imm5,
2385 UChar opChar = bU == 1 ? '+' : '-';
2386 IRExpr* index = NULL;
2389 /* imm5 can be in the range 0 .. 31 inclusive. */
2390 index = binop(Iop_Shl32, getIRegA(rM), mkU8(imm5));
2391 DIS(buf, "[r%u, %c r%u LSL #%u]", rN, opChar, rM, imm5);
2398 index = binop(Iop_Shr32, getIRegA(rM), mkU8(imm5));
2400 DIS(buf, "[r%u, %cr%u, LSR #%u]",
2401 rN, opChar, rM, imm5 == 0 ? 32 : imm5);
2404 /* Doesn't this just mean that the behaviour with imm5 == 0
2405 is the same as if it had been 31 ? */
2407 index = binop(Iop_Sar32, getIRegA(rM), mkU8(31));
2410 index = binop(Iop_Sar32, getIRegA(rM), mkU8(imm5));
2412 DIS(buf, "[r%u, %cr%u, ASR #%u]",
2413 rN, opChar, rM, imm5 == 0 ? 32 : imm5);
2415 case 3: /* ROR or RRX */
2417 IRTemp rmT = newTemp(Ity_I32);
2418 IRTemp cflagT = newTemp(Ity_I32);
2419 assign(rmT, getIRegA(rM));
2420 assign(cflagT, mk_armg_calculate_flag_c());
2421 index = binop(Iop_Or32,
2422 binop(Iop_Shl32, mkexpr(cflagT), mkU8(31)),
2423 binop(Iop_Shr32, mkexpr(rmT), mkU8(1)));
2424 DIS(buf, "[r%u, %cr%u, RRX]", rN, opChar, rM);
2426 IRTemp rmT = newTemp(Ity_I32);
2427 assign(rmT, getIRegA(rM));
2428 vassert(imm5 >= 1 && imm5 <= 31);
2429 index = binop(Iop_Or32,
2430 binop(Iop_Shl32, mkexpr(rmT), mkU8(32-imm5)),
2431 binop(Iop_Shr32, mkexpr(rmT), mkU8(imm5)));
2432 DIS(buf, "[r%u, %cr%u, ROR #%u]", rN, opChar, rM, imm5);
2439 return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
2440 getIRegA(rN), index);
2446 IRExpr* mk_EA_reg_plusminus_imm8 ( UInt rN, UInt bU, UInt imm8,
2451 vassert(imm8 < 0x100);
2452 UChar opChar = bU == 1 ? '+' : '-';
2453 DIS(buf, "[r%u, #%c%u]", rN, opChar, imm8);
2455 binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
2463 IRExpr* mk_EA_reg_plusminus_reg ( UInt rN, UInt bU, UInt rM,
2469 UChar opChar = bU == 1 ? '+' : '-';
2470 IRExpr* index = getIRegA(rM);
2471 DIS(buf, "[r%u, %c r%u]", rN, opChar, rM);
2472 return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
2473 getIRegA(rN), index);
2477 /* irRes :: Ity_I32 holds a floating point comparison result encoded
2478 as an IRCmpF64Result. Generate code to convert it to an
2479 ARM-encoded (N,Z,C,V) group in the lowest 4 bits of an I32 value.
2480 Assign a new temp to hold that value, and return the temp. */
2482 IRTemp mk_convert_IRCmpF64Result_to_NZCV ( IRTemp irRes )
2484 IRTemp ix = newTemp(Ity_I32);
2485 IRTemp termL = newTemp(Ity_I32);
2486 IRTemp termR = newTemp(Ity_I32);
2487 IRTemp nzcv = newTemp(Ity_I32);
2489 /* This is where the fun starts. We have to convert 'irRes' from
2490 an IR-convention return result (IRCmpF64Result) to an
2491 ARM-encoded (N,Z,C,V) group. The final result is in the bottom
2492 4 bits of 'nzcv'. */
2493 /* Map compare result from IR to ARM(nzcv) */
2495 FP cmp result | IR | ARM(nzcv)
2496 --------------------------------
2502 /* Now since you're probably wondering WTF ..
2504 ix fishes the useful bits out of the IR value, bits 6 and 0, and
2505 places them side by side, giving a number which is 0, 1, 2 or 3.
2507 termL is a sequence cooked up by GNU superopt. It converts ix
2508 into an almost correct value NZCV value (incredibly), except
2509 for the case of UN, where it produces 0100 instead of the
2512 termR is therefore a correction term, also computed from ix. It
2513 is 1 in the UN case and 0 for LT, GT and UN. Hence, to get
2514 the final correct value, we subtract termR from termL.
2516 Don't take my word for it. There's a test program at the bottom
2517 of this file, to try this out with.
2523 binop(Iop_Shr32, mkexpr(irRes), mkU8(5)),
2525 binop(Iop_And32, mkexpr(irRes), mkU32(1))));
2533 binop(Iop_Xor32, mkexpr(ix), mkU32(1)),
2544 binop(Iop_Shr32, mkexpr(ix), mkU8(1))),
2547 assign(nzcv, binop(Iop_Sub32, mkexpr(termL), mkexpr(termR)));
2552 /* Thumb32 only. This is "ThumbExpandImm" in the ARM ARM. If
2553 updatesC is non-NULL, a boolean is written to it indicating whether
2554 or not the C flag is updated, as per ARM ARM "ThumbExpandImm_C".
2556 static UInt thumbExpandImm ( Bool* updatesC,
2557 UInt imm1, UInt imm3, UInt imm8 )
2559 vassert(imm1 < (1<<1));
2560 vassert(imm3 < (1<<3));
2561 vassert(imm8 < (1<<8));
2562 UInt i_imm3_a = (imm1 << 4) | (imm3 << 1) | ((imm8 >> 7) & 1);
2563 UInt abcdefgh = imm8;
2564 UInt lbcdefgh = imm8 | 0x80;
2566 *updatesC = i_imm3_a >= 8;
2572 return (abcdefgh << 16) | abcdefgh;
2574 return (abcdefgh << 24) | (abcdefgh << 8);
2576 return (abcdefgh << 24) | (abcdefgh << 16)
2577 | (abcdefgh << 8) | abcdefgh;
2579 return lbcdefgh << (32 - i_imm3_a);
2583 /*NOTREACHED*/vassert(0);
2587 /* Version of thumbExpandImm where we simply feed it the
2588 instruction halfwords (the lowest addressed one is I0). */
2589 static UInt thumbExpandImm_from_I0_I1 ( Bool* updatesC,
2590 UShort i0s, UShort i1s )
2592 UInt i0 = (UInt)i0s;
2593 UInt i1 = (UInt)i1s;
2594 UInt imm1 = SLICE_UInt(i0,10,10);
2595 UInt imm3 = SLICE_UInt(i1,14,12);
2596 UInt imm8 = SLICE_UInt(i1,7,0);
2597 return thumbExpandImm(updatesC, imm1, imm3, imm8);
2601 /* Thumb16 only. Given the firstcond and mask fields from an IT
2602 instruction, compute the 32-bit ITSTATE value implied, as described
2603 in libvex_guest_arm.h. This is not the ARM ARM representation.
2604 Also produce the t/e chars for the 2nd, 3rd, 4th insns, for
2605 disassembly printing. Returns False if firstcond or mask
2606 denote something invalid.
2608 The number and conditions for the instructions to be
2609 conditionalised depend on firstcond and mask:
2611 mask cond 1 cond 2 cond 3 cond 4
2614 x100 fc[3:0] fc[3:1]:x
2615 xy10 fc[3:0] fc[3:1]:x fc[3:1]:y
2616 xyz1 fc[3:0] fc[3:1]:x fc[3:1]:y fc[3:1]:z
2618 The condition fields are assembled in *itstate backwards (cond 4 at
2619 the top, cond 1 at the bottom). Conditions are << 4'd and then
2620 ^0xE'd, and those fields that correspond to instructions in the IT
2621 block are tagged with a 1 bit.
2623 static Bool compute_ITSTATE ( /*OUT*/UInt* itstate,
2627 UInt firstcond, UInt mask )
2629 vassert(firstcond <= 0xF);
2630 vassert(mask <= 0xF);
2632 *ch1 = *ch2 = *ch3 = '.';
2634 return False; /* the logic below actually ensures this anyway,
2635 but clearer to make it explicit. */
2636 if (firstcond == 0xF)
2637 return False; /* NV is not allowed */
2638 if (firstcond == 0xE && popcount32(mask) != 1)
2639 return False; /* if firstcond is AL then all the rest must be too */
2641 UInt m3 = (mask >> 3) & 1;
2642 UInt m2 = (mask >> 2) & 1;
2643 UInt m1 = (mask >> 1) & 1;
2644 UInt m0 = (mask >> 0) & 1;
2646 UInt fc = (firstcond << 4) | 1/*in-IT-block*/;
2647 UInt ni = (0xE/*AL*/ << 4) | 0/*not-in-IT-block*/;
2649 if (m3 == 1 && (m2|m1|m0) == 0) {
2650 *itstate = (ni << 24) | (ni << 16) | (ni << 8) | fc;
2651 *itstate ^= 0xE0E0E0E0;
2655 if (m2 == 1 && (m1|m0) == 0) {
2656 *itstate = (ni << 24) | (ni << 16) | (setbit32(fc, 4, m3) << 8) | fc;
2657 *itstate ^= 0xE0E0E0E0;
2658 *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2662 if (m1 == 1 && m0 == 0) {
2663 *itstate = (ni << 24)
2664 | (setbit32(fc, 4, m2) << 16)
2665 | (setbit32(fc, 4, m3) << 8) | fc;
2666 *itstate ^= 0xE0E0E0E0;
2667 *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2668 *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
2673 *itstate = (setbit32(fc, 4, m1) << 24)
2674 | (setbit32(fc, 4, m2) << 16)
2675 | (setbit32(fc, 4, m3) << 8) | fc;
2676 *itstate ^= 0xE0E0E0E0;
2677 *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2678 *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
2679 *ch3 = m1 == (firstcond & 1) ? 't' : 'e';
2687 /* Generate IR to do 32-bit bit reversal, a la Hacker's Delight
2688 Chapter 7 Section 1. */
2689 static IRTemp gen_BITREV ( IRTemp x0 )
2691 IRTemp x1 = newTemp(Ity_I32);
2692 IRTemp x2 = newTemp(Ity_I32);
2693 IRTemp x3 = newTemp(Ity_I32);
2694 IRTemp x4 = newTemp(Ity_I32);
2695 IRTemp x5 = newTemp(Ity_I32);
2696 UInt c1 = 0x55555555;
2697 UInt c2 = 0x33333333;
2698 UInt c3 = 0x0F0F0F0F;
2699 UInt c4 = 0x00FF00FF;
2700 UInt c5 = 0x0000FFFF;
2704 binop(Iop_And32, mkexpr(x0), mkU32(c1)),
2707 binop(Iop_And32, mkexpr(x0), mkU32(~c1)),
2713 binop(Iop_And32, mkexpr(x1), mkU32(c2)),
2716 binop(Iop_And32, mkexpr(x1), mkU32(~c2)),
2722 binop(Iop_And32, mkexpr(x2), mkU32(c3)),
2725 binop(Iop_And32, mkexpr(x2), mkU32(~c3)),
2731 binop(Iop_And32, mkexpr(x3), mkU32(c4)),
2734 binop(Iop_And32, mkexpr(x3), mkU32(~c4)),
2740 binop(Iop_And32, mkexpr(x4), mkU32(c5)),
2743 binop(Iop_And32, mkexpr(x4), mkU32(~c5)),
2750 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
2751 0:1:2:3 (aka byte-swap). */
2752 static IRTemp gen_REV ( IRTemp arg )
2754 IRTemp res = newTemp(Ity_I32);
2757 binop(Iop_Shl32, mkexpr(arg), mkU8(24)),
2759 binop(Iop_And32, binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
2762 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
2764 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(24)),
2771 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
2772 2:3:0:1 (swap within lo and hi halves). */
2773 static IRTemp gen_REV16 ( IRTemp arg )
2775 IRTemp res = newTemp(Ity_I32);
2779 binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
2782 binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
2783 mkU32(0x00FF00FF))));
2788 /*------------------------------------------------------------*/
2789 /*--- Advanced SIMD (NEON) instructions ---*/
2790 /*------------------------------------------------------------*/
2792 /*------------------------------------------------------------*/
2793 /*--- NEON data processing ---*/
2794 /*------------------------------------------------------------*/
2796 /* For all NEON DP ops, we use the normal scheme to handle conditional
2797 writes to registers -- pass in condT and hand that on to the
2798 put*Reg functions. In ARM mode condT is always IRTemp_INVALID
2799 since NEON is unconditional for ARM. In Thumb mode condT is
2800 derived from the ITSTATE shift register in the normal way. */
2803 UInt get_neon_d_regno(UInt theInstr)
2805 UInt x = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
2806 if (theInstr & 0x40) {
2817 UInt get_neon_n_regno(UInt theInstr)
2819 UInt x = ((theInstr >> 3) & 0x10) | ((theInstr >> 16) & 0xF);
2820 if (theInstr & 0x40) {
2831 UInt get_neon_m_regno(UInt theInstr)
2833 UInt x = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
2834 if (theInstr & 0x40) {
2845 Bool dis_neon_vext ( UInt theInstr, IRTemp condT )
2847 UInt dreg = get_neon_d_regno(theInstr);
2848 UInt mreg = get_neon_m_regno(theInstr);
2849 UInt nreg = get_neon_n_regno(theInstr);
2850 UInt imm4 = (theInstr >> 8) & 0xf;
2851 UInt Q = (theInstr >> 6) & 1;
2852 HChar reg_t = Q ? 'q' : 'd';
2855 putQReg(dreg, triop(Iop_ExtractV128, getQReg(nreg),
2856 getQReg(mreg), mkU8(imm4)), condT);
2858 putDRegI64(dreg, triop(Iop_Extract64, getDRegI64(nreg),
2859 getDRegI64(mreg), mkU8(imm4)), condT);
2861 DIP("vext.8 %c%d, %c%d, %c%d, #%d\n", reg_t, dreg, reg_t, nreg,
2868 Bool dis_neon_vtb ( UInt theInstr, IRTemp condT )
2870 UInt op = (theInstr >> 6) & 1;
2871 UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
2872 UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
2873 UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
2874 UInt len = (theInstr >> 8) & 3;
2879 IRTemp old_mask, new_mask, cur_mask;
2880 IRTemp old_res, new_res;
2881 IRTemp old_arg, new_arg;
2883 if (dreg >= 0x100 || mreg >= 0x100 || nreg >= 0x100)
2885 if (nreg + len > 31)
2888 cmp = Iop_CmpGT8Ux8;
2890 old_mask = newTemp(Ity_I64);
2891 old_res = newTemp(Ity_I64);
2892 old_arg = newTemp(Ity_I64);
2893 assign(old_mask, mkU64(0));
2894 assign(old_res, mkU64(0));
2895 assign(old_arg, getDRegI64(mreg));
2897 imm = (imm << 8) | imm;
2898 imm = (imm << 16) | imm;
2899 imm = (imm << 32) | imm;
2901 for (i = 0; i <= len; i++) {
2902 arg_l = newTemp(Ity_I64);
2903 new_mask = newTemp(Ity_I64);
2904 cur_mask = newTemp(Ity_I64);
2905 new_res = newTemp(Ity_I64);
2906 new_arg = newTemp(Ity_I64);
2907 assign(arg_l, getDRegI64(nreg+i));
2908 assign(new_arg, binop(Iop_Sub8x8, mkexpr(old_arg), mkU64(imm)));
2909 assign(cur_mask, binop(cmp, mkU64(imm), mkexpr(old_arg)));
2910 assign(new_mask, binop(Iop_Or64, mkexpr(old_mask), mkexpr(cur_mask)));
2911 assign(new_res, binop(Iop_Or64,
2919 mkexpr(cur_mask))));
2922 old_mask = new_mask;
2926 new_res = newTemp(Ity_I64);
2927 assign(new_res, binop(Iop_Or64,
2930 unop(Iop_Not64, mkexpr(old_mask))),
2935 putDRegI64(dreg, mkexpr(old_res), condT);
2936 DIP("vtb%c.8 d%u, {", op ? 'x' : 'l', dreg);
2938 DIP("d%u-d%u", nreg, nreg + len);
2942 DIP("}, d%u\n", mreg);
2948 Bool dis_neon_vdup ( UInt theInstr, IRTemp condT )
2950 UInt Q = (theInstr >> 6) & 1;
2951 UInt dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
2952 UInt mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
2953 UInt imm4 = (theInstr >> 16) & 0xF;
2960 if ((imm4 == 0) || (imm4 == 8))
2962 if ((Q == 1) && ((dreg & 1) == 1))
2966 arg_m = newTemp(Ity_I64);
2967 assign(arg_m, getDRegI64(mreg));
2969 res = newTemp(Ity_V128);
2971 res = newTemp(Ity_I64);
2972 if ((imm4 & 1) == 1) {
2973 op = Q ? Iop_Dup8x16 : Iop_Dup8x8;
2974 op2 = Iop_GetElem8x8;
2977 } else if ((imm4 & 3) == 2) {
2978 op = Q ? Iop_Dup16x8 : Iop_Dup16x4;
2979 op2 = Iop_GetElem16x4;
2982 } else if ((imm4 & 7) == 4) {
2983 op = Q ? Iop_Dup32x4 : Iop_Dup32x2;
2984 op2 = Iop_GetElem32x2;
2988 return False; // can this ever happen?
2990 assign(res, unop(op, binop(op2, mkexpr(arg_m), mkU8(index))));
2992 putQReg(dreg, mkexpr(res), condT);
2994 putDRegI64(dreg, mkexpr(res), condT);
2996 DIP("vdup.%d %c%d, d%d[%d]\n", size, Q ? 'q' : 'd', dreg, mreg, index);
3000 /* A7.4.1 Three registers of the same length */
3002 Bool dis_neon_data_3same ( UInt theInstr, IRTemp condT )
3004 UInt Q = (theInstr >> 6) & 1;
3005 UInt dreg = get_neon_d_regno(theInstr);
3006 UInt nreg = get_neon_n_regno(theInstr);
3007 UInt mreg = get_neon_m_regno(theInstr);
3008 UInt A = (theInstr >> 8) & 0xF;
3009 UInt B = (theInstr >> 4) & 1;
3010 UInt C = (theInstr >> 20) & 0x3;
3011 UInt U = (theInstr >> 24) & 1;
3019 arg_n = newTemp(Ity_V128);
3020 arg_m = newTemp(Ity_V128);
3021 res = newTemp(Ity_V128);
3022 assign(arg_n, getQReg(nreg));
3023 assign(arg_m, getQReg(mreg));
3025 arg_n = newTemp(Ity_I64);
3026 arg_m = newTemp(Ity_I64);
3027 res = newTemp(Ity_I64);
3028 assign(arg_n, getDRegI64(nreg));
3029 assign(arg_m, getDRegI64(mreg));
3041 char regType = Q ? 'q' : 'd';
3046 case 0: imm = 0x101010101010101LL; break;
3047 case 1: imm = 0x1000100010001LL; break;
3048 case 2: imm = 0x100000001LL; break;
3049 default: vassert(0);
3052 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
3053 andOp = Iop_AndV128;
3055 imm_val = mkU64(imm);
3061 addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
3062 shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3065 addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
3066 shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3069 addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
3070 shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3078 addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
3079 shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
3082 addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
3083 shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
3086 addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
3087 shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
3096 binop(shOp, mkexpr(arg_m), mkU8(1)),
3097 binop(shOp, mkexpr(arg_n), mkU8(1))),
3100 binop(andOp, mkexpr(arg_m), imm_val),
3101 binop(andOp, mkexpr(arg_n), imm_val)),
3103 DIP("vhadd.%c%d %c%d, %c%d, %c%d\n",
3104 U ? 'u' : 's', 8 << size, regType,
3105 dreg, regType, nreg, regType, mreg);
3110 char reg_t = Q ? 'q' : 'd';
3114 op = U ? Iop_QAdd8Ux16 : Iop_QAdd8Sx16;
3118 op = U ? Iop_QAdd16Ux8 : Iop_QAdd16Sx8;
3122 op = U ? Iop_QAdd32Ux4 : Iop_QAdd32Sx4;
3126 op = U ? Iop_QAdd64Ux2 : Iop_QAdd64Sx2;
3135 op = U ? Iop_QAdd8Ux8 : Iop_QAdd8Sx8;
3139 op = U ? Iop_QAdd16Ux4 : Iop_QAdd16Sx4;
3143 op = U ? Iop_QAdd32Ux2 : Iop_QAdd32Sx2;
3147 op = U ? Iop_QAdd64Ux1 : Iop_QAdd64Sx1;
3155 tmp = newTemp(Ity_V128);
3157 tmp = newTemp(Ity_I64);
3159 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3160 #ifndef DISABLE_QC_FLAG
3161 assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
3162 setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
3164 DIP("vqadd.%c%d %c%d, %c%d, %c%d\n",
3166 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
3172 /* VRHADD C, A, B ::=
3173 C = (A >> 1) + (B >> 1) + (((A & 1) + (B & 1) + 1) >> 1) */
3174 IROp shift_op, add_op;
3177 HChar reg_t = Q ? 'q' : 'd';
3179 case 0: one = (one << 8) | one; /* fall through */
3180 case 1: one = (one << 16) | one; /* fall through */
3181 case 2: one = (one << 32) | one; break;
3182 case 3: return False;
3183 default: vassert(0);
3188 shift_op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
3189 add_op = Iop_Add8x16;
3192 shift_op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
3193 add_op = Iop_Add16x8;
3196 shift_op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
3197 add_op = Iop_Add32x4;
3207 shift_op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
3208 add_op = Iop_Add8x8;
3211 shift_op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
3212 add_op = Iop_Add16x4;
3215 shift_op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
3216 add_op = Iop_Add32x2;
3225 cc = newTemp(Ity_V128);
3226 assign(cc, binop(shift_op,
3231 binop(Iop_64HLtoV128,
3236 binop(Iop_64HLtoV128,
3239 binop(Iop_64HLtoV128,
3243 assign(res, binop(add_op,
3253 cc = newTemp(Ity_I64);
3254 assign(cc, binop(shift_op,
3265 assign(res, binop(add_op,
3275 DIP("vrhadd.%c%d %c%d, %c%d, %c%d\n",
3277 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
3283 HChar reg_t = Q ? 'q' : 'd';
3285 assign(res, binop(Iop_AndV128, mkexpr(arg_n),
3288 assign(res, binop(Iop_And64, mkexpr(arg_n),
3291 DIP("vand %c%d, %c%d, %c%d\n",
3292 reg_t, dreg, reg_t, nreg, reg_t, mreg);
3297 HChar reg_t = Q ? 'q' : 'd';
3299 assign(res, binop(Iop_AndV128,mkexpr(arg_n),
3300 unop(Iop_NotV128, mkexpr(arg_m))));
3302 assign(res, binop(Iop_And64, mkexpr(arg_n),
3303 unop(Iop_Not64, mkexpr(arg_m))));
3305 DIP("vbic %c%d, %c%d, %c%d\n",
3306 reg_t, dreg, reg_t, nreg, reg_t, mreg);
3310 if ( nreg != mreg) {
3312 HChar reg_t = Q ? 'q' : 'd';
3314 assign(res, binop(Iop_OrV128, mkexpr(arg_n),
3317 assign(res, binop(Iop_Or64, mkexpr(arg_n),
3320 DIP("vorr %c%d, %c%d, %c%d\n",
3321 reg_t, dreg, reg_t, nreg, reg_t, mreg);
3324 HChar reg_t = Q ? 'q' : 'd';
3325 assign(res, mkexpr(arg_m));
3326 DIP("vmov %c%d, %c%d\n", reg_t, dreg, reg_t, mreg);
3331 HChar reg_t = Q ? 'q' : 'd';
3333 assign(res, binop(Iop_OrV128,mkexpr(arg_n),
3334 unop(Iop_NotV128, mkexpr(arg_m))));
3336 assign(res, binop(Iop_Or64, mkexpr(arg_n),
3337 unop(Iop_Not64, mkexpr(arg_m))));
3339 DIP("vorn %c%d, %c%d, %c%d\n",
3340 reg_t, dreg, reg_t, nreg, reg_t, mreg);
3349 assign(res, binop(Iop_XorV128, mkexpr(arg_n),
3352 assign(res, binop(Iop_Xor64, mkexpr(arg_n),
3355 DIP("veor %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
3356 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3361 IRTemp reg_d = newTemp(Ity_V128);
3362 assign(reg_d, getQReg(dreg));
3365 binop(Iop_AndV128, mkexpr(arg_n),
3370 mkexpr(reg_d)) ) ) );
3372 IRTemp reg_d = newTemp(Ity_I64);
3373 assign(reg_d, getDRegI64(dreg));
3376 binop(Iop_And64, mkexpr(arg_n),
3380 unop(Iop_Not64, mkexpr(reg_d)))));
3382 DIP("vbsl %c%u, %c%u, %c%u\n",
3383 Q ? 'q' : 'd', dreg,
3384 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3389 IRTemp reg_d = newTemp(Ity_V128);
3390 assign(reg_d, getQReg(dreg));
3393 binop(Iop_AndV128, mkexpr(arg_n),
3397 unop(Iop_NotV128, mkexpr(arg_m)))));
3399 IRTemp reg_d = newTemp(Ity_I64);
3400 assign(reg_d, getDRegI64(dreg));
3403 binop(Iop_And64, mkexpr(arg_n),
3407 unop(Iop_Not64, mkexpr(arg_m)))));
3409 DIP("vbit %c%u, %c%u, %c%u\n",
3410 Q ? 'q' : 'd', dreg,
3411 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3416 IRTemp reg_d = newTemp(Ity_V128);
3417 assign(reg_d, getQReg(dreg));
3420 binop(Iop_AndV128, mkexpr(reg_d),
3424 unop(Iop_NotV128, mkexpr(arg_m)))));
3426 IRTemp reg_d = newTemp(Ity_I64);
3427 assign(reg_d, getDRegI64(dreg));
3430 binop(Iop_And64, mkexpr(reg_d),
3434 unop(Iop_Not64, mkexpr(arg_m)))));
3436 DIP("vbif %c%u, %c%u, %c%u\n",
3437 Q ? 'q' : 'd', dreg,
3438 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3447 /* (A >> 1) - (B >> 1) - (NOT (A) & B & 1) */
3457 case 0: imm = 0x101010101010101LL; break;
3458 case 1: imm = 0x1000100010001LL; break;
3459 case 2: imm = 0x100000001LL; break;
3460 default: vassert(0);
3463 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
3464 andOp = Iop_AndV128;
3465 notOp = Iop_NotV128;
3467 imm_val = mkU64(imm);
3474 subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3475 shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3478 subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3479 shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3482 subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3483 shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3491 subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3492 shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
3495 subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3496 shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
3499 subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3500 shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
3509 binop(shOp, mkexpr(arg_n), mkU8(1)),
3510 binop(shOp, mkexpr(arg_m), mkU8(1))),
3513 unop(notOp, mkexpr(arg_n)),
3516 DIP("vhsub.%c%u %c%u, %c%u, %c%u\n",
3517 U ? 'u' : 's', 8 << size,
3518 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3527 op = U ? Iop_QSub8Ux16 : Iop_QSub8Sx16;
3531 op = U ? Iop_QSub16Ux8 : Iop_QSub16Sx8;
3535 op = U ? Iop_QSub32Ux4 : Iop_QSub32Sx4;
3539 op = U ? Iop_QSub64Ux2 : Iop_QSub64Sx2;
3548 op = U ? Iop_QSub8Ux8 : Iop_QSub8Sx8;
3552 op = U ? Iop_QSub16Ux4 : Iop_QSub16Sx4;
3556 op = U ? Iop_QSub32Ux2 : Iop_QSub32Sx2;
3560 op = U ? Iop_QSub64Ux1 : Iop_QSub64Sx1;
3568 tmp = newTemp(Ity_V128);
3570 tmp = newTemp(Ity_I64);
3571 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3572 #ifndef DISABLE_QC_FLAG
3573 assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
3574 setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
3576 DIP("vqsub.%c%u %c%u, %c%u, %c%u\n",
3577 U ? 'u' : 's', 8 << size,
3578 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3586 case 0: op = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; break;
3587 case 1: op = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; break;
3588 case 2: op = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; break;
3589 case 3: return False;
3590 default: vassert(0);
3594 case 0: op = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; break;
3595 case 1: op = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; break;
3596 case 2: op = U ? Iop_CmpGT32Ux2: Iop_CmpGT32Sx2; break;
3597 case 3: return False;
3598 default: vassert(0);
3603 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3604 DIP("vcgt.%c%u %c%u, %c%u, %c%u\n",
3605 U ? 'u' : 's', 8 << size,
3606 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3610 /* VCGE res, argn, argm
3612 VCGT tmp, argm, argn
3615 unop(Q ? Iop_NotV128 : Iop_Not64,
3616 binop(op, mkexpr(arg_m), mkexpr(arg_n))));
3617 DIP("vcge.%c%u %c%u, %c%u, %c%u\n",
3618 U ? 'u' : 's', 8 << size,
3619 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3631 case 0: op = Q ? Iop_Shl8x16 : Iop_Shl8x8; break;
3632 case 1: op = Q ? Iop_Shl16x8 : Iop_Shl16x4; break;
3633 case 2: op = Q ? Iop_Shl32x4 : Iop_Shl32x2; break;
3634 case 3: op = Q ? Iop_Shl64x2 : Iop_Shl64; break;
3635 default: vassert(0);
3638 tmp = newTemp(Q ? Ity_V128 : Ity_I64);
3641 op = Q ? Iop_Sar8x16 : Iop_Sar8x8;
3642 sub_op = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3645 op = Q ? Iop_Sar16x8 : Iop_Sar16x4;
3646 sub_op = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3649 op = Q ? Iop_Sar32x4 : Iop_Sar32x2;
3650 sub_op = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3653 op = Q ? Iop_Sar64x2 : Iop_Sar64;
3654 sub_op = Q ? Iop_Sub64x2 : Iop_Sub64;
3661 if (!Q && (size == 3))
3662 assign(res, binop(op, mkexpr(arg_m),
3663 unop(Iop_64to8, mkexpr(arg_n))));
3665 assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
3668 assign(tmp, binop(sub_op,
3669 binop(Iop_64HLtoV128, mkU64(0), mkU64(0)),
3672 assign(tmp, binop(sub_op, mkU64(0), mkexpr(arg_n)));
3673 if (!Q && (size == 3))
3674 assign(res, binop(op, mkexpr(arg_m),
3675 unop(Iop_64to8, mkexpr(tmp))));
3677 assign(res, binop(op, mkexpr(arg_m), mkexpr(tmp)));
3679 DIP("vshl.%c%u %c%u, %c%u, %c%u\n",
3680 U ? 'u' : 's', 8 << size,
3681 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3685 IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt;
3686 IRTemp tmp, shval, mask, old_shval;
3689 cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
3690 cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3694 op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
3695 op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
3696 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3697 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3700 op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
3701 op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
3702 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3703 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3706 op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
3707 op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
3708 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3709 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3712 op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
3713 op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
3714 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3715 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3723 op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
3724 op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
3725 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3726 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3729 op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
3730 op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
3731 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3732 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3735 op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
3736 op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
3737 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3738 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3741 op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
3742 op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
3743 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3744 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3751 tmp = newTemp(Ity_V128);
3752 shval = newTemp(Ity_V128);
3753 mask = newTemp(Ity_V128);
3755 tmp = newTemp(Ity_I64);
3756 shval = newTemp(Ity_I64);
3757 mask = newTemp(Ity_I64);
3759 assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
3760 #ifndef DISABLE_QC_FLAG
3761 /* Only least significant byte from second argument is used.
3762 Copy this byte to the whole vector element. */
3763 assign(shval, binop(op_shrn,
3766 mkU8((8 << size) - 8)),
3767 mkU8((8 << size) - 8)));
3768 for(i = 0; i < size; i++) {
3770 shval = newTemp(Q ? Ity_V128 : Ity_I64);
3771 assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
3777 /* If shift is greater or equal to the element size and
3778 element is non-zero, then QC flag should be set. */
3779 esize = (8 << size) - 1;
3780 esize = (esize << 8) | esize;
3781 esize = (esize << 16) | esize;
3782 esize = (esize << 32) | esize;
3783 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
3784 binop(cmp_gt, mkexpr(shval),
3785 Q ? mkU128(esize) : mkU64(esize)),
3786 unop(cmp_neq, mkexpr(arg_m))),
3787 Q ? mkU128(0) : mkU64(0),
3789 /* Othervise QC flag should be set if shift value is positive and
3790 result beign rightshifted the same value is not equal to left
3792 assign(mask, binop(cmp_gt, mkexpr(shval),
3793 Q ? mkU128(0) : mkU64(0)));
3794 if (!Q && size == 3)
3795 assign(tmp, binop(op_rev, mkexpr(res),
3796 unop(Iop_64to8, mkexpr(arg_n))));
3798 assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
3799 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
3800 mkexpr(tmp), mkexpr(mask)),
3801 binop(Q ? Iop_AndV128 : Iop_And64,
3802 mkexpr(arg_m), mkexpr(mask)),
3805 DIP("vqshl.%c%u %c%u, %c%u, %c%u\n",
3806 U ? 'u' : 's', 8 << size,
3807 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3814 IROp op, op_shrn, op_shln, cmp_gt, op_add;
3815 IRTemp shval, old_shval, imm_val, round;
3818 cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3821 case 0: imm = (imm << 8) | imm; /* fall through */
3822 case 1: imm = (imm << 16) | imm; /* fall through */
3823 case 2: imm = (imm << 32) | imm; /* fall through */
3825 default: vassert(0);
3827 imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
3828 round = newTemp(Q ? Ity_V128 : Ity_I64);
3829 assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
3833 op = Q ? Iop_Shl8x16 : Iop_Shl8x8;
3834 op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3835 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3836 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3839 op = Q ? Iop_Shl16x8 : Iop_Shl16x4;
3840 op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3841 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3842 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3845 op = Q ? Iop_Shl32x4 : Iop_Shl32x2;
3846 op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
3847 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3848 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3851 op = Q ? Iop_Shl64x2 : Iop_Shl64;
3852 op_add = Q ? Iop_Add64x2 : Iop_Add64;
3853 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3854 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3862 op = Q ? Iop_Sal8x16 : Iop_Sal8x8;
3863 op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3864 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3865 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3868 op = Q ? Iop_Sal16x8 : Iop_Sal16x4;
3869 op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3870 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3871 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3874 op = Q ? Iop_Sal32x4 : Iop_Sal32x2;
3875 op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
3876 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3877 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3880 op = Q ? Iop_Sal64x2 : Iop_Sal64x1;
3881 op_add = Q ? Iop_Add64x2 : Iop_Add64;
3882 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3883 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3890 shval = newTemp(Ity_V128);
3892 shval = newTemp(Ity_I64);
3894 /* Only least significant byte from second argument is used.
3895 Copy this byte to the whole vector element. */
3896 assign(shval, binop(op_shrn,
3899 mkU8((8 << size) - 8)),
3900 mkU8((8 << size) - 8)));
3901 for (i = 0; i < size; i++) {
3903 shval = newTemp(Q ? Ity_V128 : Ity_I64);
3904 assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
3910 /* Compute the result */
3911 if (!Q && size == 3 && U) {
3912 assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
3919 binop(Q ? Iop_AndV128 : Iop_And64,
3922 Q ? mkU128(0) : mkU64(0),
3924 assign(res, binop(op_add,
3927 unop(Iop_64to8, mkexpr(arg_n))),
3930 assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
3936 binop(Q ? Iop_AndV128 : Iop_And64,
3939 Q ? mkU128(0) : mkU64(0),
3941 assign(res, binop(op_add,
3942 binop(op, mkexpr(arg_m), mkexpr(arg_n)),
3945 DIP("vrshl.%c%u %c%u, %c%u, %c%u\n",
3946 U ? 'u' : 's', 8 << size,
3947 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3951 IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt, op_add;
3952 IRTemp tmp, shval, mask, old_shval, imm_val, round;
3955 cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
3956 cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3959 case 0: imm = (imm << 8) | imm; /* fall through */
3960 case 1: imm = (imm << 16) | imm; /* fall through */
3961 case 2: imm = (imm << 32) | imm; /* fall through */
3963 default: vassert(0);
3965 imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
3966 round = newTemp(Q ? Ity_V128 : Ity_I64);
3967 assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
3971 op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
3972 op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3973 op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
3974 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3975 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3978 op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
3979 op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3980 op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
3981 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3982 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3985 op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
3986 op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
3987 op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
3988 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3989 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3992 op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
3993 op_add = Q ? Iop_Add64x2 : Iop_Add64;
3994 op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
3995 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3996 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
4004 op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
4005 op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
4006 op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
4007 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
4008 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
4011 op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
4012 op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
4013 op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
4014 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
4015 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
4018 op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
4019 op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
4020 op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
4021 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
4022 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
4025 op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
4026 op_add = Q ? Iop_Add64x2 : Iop_Add64;
4027 op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
4028 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
4029 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
4036 tmp = newTemp(Ity_V128);
4037 shval = newTemp(Ity_V128);
4038 mask = newTemp(Ity_V128);
4040 tmp = newTemp(Ity_I64);
4041 shval = newTemp(Ity_I64);
4042 mask = newTemp(Ity_I64);
4044 /* Only least significant byte from second argument is used.
4045 Copy this byte to the whole vector element. */
4046 assign(shval, binop(op_shrn,
4049 mkU8((8 << size) - 8)),
4050 mkU8((8 << size) - 8)));
4051 for (i = 0; i < size; i++) {
4053 shval = newTemp(Q ? Ity_V128 : Ity_I64);
4054 assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
4060 /* Compute the result */
4061 assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
4067 binop(Q ? Iop_AndV128 : Iop_And64,
4070 Q ? mkU128(0) : mkU64(0),
4072 assign(res, binop(op_add,
4073 binop(op, mkexpr(arg_m), mkexpr(arg_n)),
4075 #ifndef DISABLE_QC_FLAG
4076 /* If shift is greater or equal to the element size and element is
4077 non-zero, then QC flag should be set. */
4078 esize = (8 << size) - 1;
4079 esize = (esize << 8) | esize;
4080 esize = (esize << 16) | esize;
4081 esize = (esize << 32) | esize;
4082 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4083 binop(cmp_gt, mkexpr(shval),
4084 Q ? mkU128(esize) : mkU64(esize)),
4085 unop(cmp_neq, mkexpr(arg_m))),
4086 Q ? mkU128(0) : mkU64(0),
4088 /* Othervise QC flag should be set if shift value is positive and
4089 result beign rightshifted the same value is not equal to left
4091 assign(mask, binop(cmp_gt, mkexpr(shval),
4092 Q ? mkU128(0) : mkU64(0)));
4093 if (!Q && size == 3)
4094 assign(tmp, binop(op_rev, mkexpr(res),
4095 unop(Iop_64to8, mkexpr(arg_n))));
4097 assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
4098 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4099 mkexpr(tmp), mkexpr(mask)),
4100 binop(Q ? Iop_AndV128 : Iop_And64,
4101 mkexpr(arg_m), mkexpr(mask)),
4104 DIP("vqrshl.%c%u %c%u, %c%u, %c%u\n",
4105 U ? 'u' : 's', 8 << size,
4106 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
4117 case 0: op = Q ? Iop_Max8Sx16 : Iop_Max8Sx8; break;
4118 case 1: op = Q ? Iop_Max16Sx8 : Iop_Max16Sx4; break;
4119 case 2: op = Q ? Iop_Max32Sx4 : Iop_Max32Sx2; break;
4120 case 3: return False;
4121 default: vassert(0);
4125 case 0: op = Q ? Iop_Max8Ux16 : Iop_Max8Ux8; break;
4126 case 1: op = Q ? Iop_Max16Ux8 : Iop_Max16Ux4; break;
4127 case 2: op = Q ? Iop_Max32Ux4 : Iop_Max32Ux2; break;
4128 case 3: return False;
4129 default: vassert(0);
4132 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4133 DIP("vmax.%c%u %c%u, %c%u, %c%u\n",
4134 U ? 'u' : 's', 8 << size,
4135 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4142 case 0: op = Q ? Iop_Min8Sx16 : Iop_Min8Sx8; break;
4143 case 1: op = Q ? Iop_Min16Sx8 : Iop_Min16Sx4; break;
4144 case 2: op = Q ? Iop_Min32Sx4 : Iop_Min32Sx2; break;
4145 case 3: return False;
4146 default: vassert(0);
4150 case 0: op = Q ? Iop_Min8Ux16 : Iop_Min8Ux8; break;
4151 case 1: op = Q ? Iop_Min16Ux8 : Iop_Min16Ux4; break;
4152 case 2: op = Q ? Iop_Min32Ux4 : Iop_Min32Ux2; break;
4153 case 3: return False;
4154 default: vassert(0);
4157 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4158 DIP("vmin.%c%u %c%u, %c%u, %c%u\n",
4159 U ? 'u' : 's', 8 << size,
4160 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4167 IROp op_cmp, op_sub;
4169 if ((theInstr >> 23) & 1) {
4170 vpanic("VABDL should not be in dis_neon_data_3same\n");
4175 op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
4176 op_sub = Iop_Sub8x16;
4179 op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
4180 op_sub = Iop_Sub16x8;
4183 op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
4184 op_sub = Iop_Sub32x4;
4194 op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4195 op_sub = Iop_Sub8x8;
4198 op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4199 op_sub = Iop_Sub16x4;
4202 op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4203 op_sub = Iop_Sub32x2;
4212 cond = newTemp(Ity_V128);
4214 cond = newTemp(Ity_I64);
4216 assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
4217 assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
4218 binop(Q ? Iop_AndV128 : Iop_And64,
4219 binop(op_sub, mkexpr(arg_n),
4222 binop(Q ? Iop_AndV128 : Iop_And64,
4223 binop(op_sub, mkexpr(arg_m),
4225 unop(Q ? Iop_NotV128 : Iop_Not64,
4227 DIP("vabd.%c%u %c%u, %c%u, %c%u\n",
4228 U ? 'u' : 's', 8 << size,
4229 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4233 IROp op_cmp, op_sub, op_add;
4234 IRTemp cond, acc, tmp;
4235 if ((theInstr >> 23) & 1) {
4236 vpanic("VABAL should not be in dis_neon_data_3same");
4241 op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
4242 op_sub = Iop_Sub8x16;
4243 op_add = Iop_Add8x16;
4246 op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
4247 op_sub = Iop_Sub16x8;
4248 op_add = Iop_Add16x8;
4251 op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
4252 op_sub = Iop_Sub32x4;
4253 op_add = Iop_Add32x4;
4263 op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4264 op_sub = Iop_Sub8x8;
4265 op_add = Iop_Add8x8;
4268 op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4269 op_sub = Iop_Sub16x4;
4270 op_add = Iop_Add16x4;
4273 op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4274 op_sub = Iop_Sub32x2;
4275 op_add = Iop_Add32x2;
4284 cond = newTemp(Ity_V128);
4285 acc = newTemp(Ity_V128);
4286 tmp = newTemp(Ity_V128);
4287 assign(acc, getQReg(dreg));
4289 cond = newTemp(Ity_I64);
4290 acc = newTemp(Ity_I64);
4291 tmp = newTemp(Ity_I64);
4292 assign(acc, getDRegI64(dreg));
4294 assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
4295 assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
4296 binop(Q ? Iop_AndV128 : Iop_And64,
4297 binop(op_sub, mkexpr(arg_n),
4300 binop(Q ? Iop_AndV128 : Iop_And64,
4301 binop(op_sub, mkexpr(arg_m),
4303 unop(Q ? Iop_NotV128 : Iop_Not64,
4305 assign(res, binop(op_add, mkexpr(acc), mkexpr(tmp)));
4306 DIP("vaba.%c%u %c%u, %c%u, %c%u\n",
4307 U ? 'u' : 's', 8 << size,
4308 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4318 case 0: op = Q ? Iop_Add8x16 : Iop_Add8x8; break;
4319 case 1: op = Q ? Iop_Add16x8 : Iop_Add16x4; break;
4320 case 2: op = Q ? Iop_Add32x4 : Iop_Add32x2; break;
4321 case 3: op = Q ? Iop_Add64x2 : Iop_Add64; break;
4322 default: vassert(0);
4324 DIP("vadd.i%u %c%u, %c%u, %c%u\n",
4325 8 << size, Q ? 'q' : 'd',
4326 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4330 case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
4331 case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
4332 case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
4333 case 3: op = Q ? Iop_Sub64x2 : Iop_Sub64; break;
4334 default: vassert(0);
4336 DIP("vsub.i%u %c%u, %c%u, %c%u\n",
4337 8 << size, Q ? 'q' : 'd',
4338 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4340 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4344 case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
4345 case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
4346 case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
4347 case 3: op = Q ? Iop_CmpNEZ64x2 : Iop_CmpwNEZ64; break;
4348 default: vassert(0);
4352 assign(res, unop(op, binop(Q ? Iop_AndV128 : Iop_And64,
4355 DIP("vtst.%u %c%u, %c%u, %c%u\n",
4356 8 << size, Q ? 'q' : 'd',
4357 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4360 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
4362 binop(Q ? Iop_XorV128 : Iop_Xor64,
4365 DIP("vceq.i%u %c%u, %c%u, %c%u\n",
4366 8 << size, Q ? 'q' : 'd',
4367 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4373 /* VMLA, VMLS (integer) */
4375 UInt P = (theInstr >> 24) & 1;
4379 op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
4380 op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
4383 op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
4384 op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
4387 op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
4388 op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
4398 op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
4399 op2 = Q ? Iop_Add8x16 : Iop_Add8x8;
4402 op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
4403 op2 = Q ? Iop_Add16x8 : Iop_Add16x4;
4406 op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
4407 op2 = Q ? Iop_Add32x4 : Iop_Add32x2;
4415 assign(res, binop(op2,
4416 Q ? getQReg(dreg) : getDRegI64(dreg),
4417 binop(op, mkexpr(arg_n), mkexpr(arg_m))));
4418 DIP("vml%c.i%u %c%u, %c%u, %c%u\n",
4419 P ? 's' : 'a', 8 << size,
4420 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4425 UInt P = (theInstr >> 24) & 1;
4429 op = Q ? Iop_PolynomialMul8x16 : Iop_PolynomialMul8x8;
4431 case 1: case 2: case 3: return False;
4432 default: vassert(0);
4436 case 0: op = Q ? Iop_Mul8x16 : Iop_Mul8x8; break;
4437 case 1: op = Q ? Iop_Mul16x8 : Iop_Mul16x4; break;
4438 case 2: op = Q ? Iop_Mul32x4 : Iop_Mul32x2; break;
4439 case 3: return False;
4440 default: vassert(0);
4443 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4444 DIP("vmul.%c%u %c%u, %c%u, %c%u\n",
4445 P ? 'p' : 'i', 8 << size,
4446 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4452 UInt P = (theInstr >> 4) & 1;
4458 case 0: op = U ? Iop_PwMin8Ux8 : Iop_PwMin8Sx8; break;
4459 case 1: op = U ? Iop_PwMin16Ux4 : Iop_PwMin16Sx4; break;
4460 case 2: op = U ? Iop_PwMin32Ux2 : Iop_PwMin32Sx2; break;
4461 case 3: return False;
4462 default: vassert(0);
4466 case 0: op = U ? Iop_PwMax8Ux8 : Iop_PwMax8Sx8; break;
4467 case 1: op = U ? Iop_PwMax16Ux4 : Iop_PwMax16Sx4; break;
4468 case 2: op = U ? Iop_PwMax32Ux2 : Iop_PwMax32Sx2; break;
4469 case 3: return False;
4470 default: vassert(0);
4473 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4474 DIP("vp%s.%c%u %c%u, %c%u, %c%u\n",
4475 P ? "min" : "max", U ? 'u' : 's',
4476 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
4477 Q ? 'q' : 'd', mreg);
4490 op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
4491 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
4493 imm = (imm << 16) | imm;
4494 imm = (imm << 32) | imm;
4497 op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
4498 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
4500 imm = (imm << 32) | imm;
4505 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4506 #ifndef DISABLE_QC_FLAG
4507 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4508 binop(op2, mkexpr(arg_n),
4509 Q ? mkU128(imm) : mkU64(imm)),
4510 binop(op2, mkexpr(arg_m),
4511 Q ? mkU128(imm) : mkU64(imm))),
4512 Q ? mkU128(0) : mkU64(0),
4515 DIP("vqdmulh.s%u %c%u, %c%u, %c%u\n",
4516 8 << size, Q ? 'q' : 'd',
4517 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4527 imm = (imm << 16) | imm;
4528 imm = (imm << 32) | imm;
4529 op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
4530 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
4534 imm = (imm << 32) | imm;
4535 op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
4536 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
4541 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4542 #ifndef DISABLE_QC_FLAG
4543 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4544 binop(op2, mkexpr(arg_n),
4545 Q ? mkU128(imm) : mkU64(imm)),
4546 binop(op2, mkexpr(arg_m),
4547 Q ? mkU128(imm) : mkU64(imm))),
4548 Q ? mkU128(0) : mkU64(0),
4551 DIP("vqrdmulh.s%u %c%u, %c%u, %c%u\n",
4552 8 << size, Q ? 'q' : 'd',
4553 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4562 case 0: op = Q ? Iop_PwAdd8x16 : Iop_PwAdd8x8; break;
4563 case 1: op = Q ? Iop_PwAdd16x8 : Iop_PwAdd16x4; break;
4564 case 2: op = Q ? Iop_PwAdd32x4 : Iop_PwAdd32x2; break;
4565 case 3: return False;
4566 default: vassert(0);
4568 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4569 DIP("vpadd.i%d %c%u, %c%u, %c%u\n",
4570 8 << size, Q ? 'q' : 'd',
4571 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4575 /* Starting from here these are FP SIMD cases */
4580 if ((C >> 1) == 0) {
4582 op = Q ? Iop_Add32Fx4 : Iop_Add32Fx2 ;
4583 DIP("vadd.f32 %c%u, %c%u, %c%u\n",
4584 Q ? 'q' : 'd', dreg,
4585 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4588 op = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2 ;
4589 DIP("vsub.f32 %c%u, %c%u, %c%u\n",
4590 Q ? 'q' : 'd', dreg,
4591 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4594 if ((C >> 1) == 0) {
4598 op = Iop_PwAdd32Fx2;
4599 DIP("vpadd.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4603 assign(res, unop(Iop_Abs32Fx4,
4608 assign(res, unop(Iop_Abs32Fx2,
4613 DIP("vabd.f32 %c%u, %c%u, %c%u\n",
4614 Q ? 'q' : 'd', dreg,
4615 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4619 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4624 UInt P = (theInstr >> 21) & 1;
4628 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
4629 op2 = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
4631 case 1: return False;
4632 default: vassert(0);
4637 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
4638 op2 = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
4640 case 1: return False;
4641 default: vassert(0);
4644 assign(res, binop(op2,
4645 Q ? getQReg(dreg) : getDRegI64(dreg),
4646 binop(op, mkexpr(arg_n), mkexpr(arg_m))));
4648 DIP("vml%c.f32 %c%u, %c%u, %c%u\n",
4649 P ? 's' : 'a', Q ? 'q' : 'd',
4650 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4656 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2 ;
4657 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4658 DIP("vmul.f32 %c%u, %c%u, %c%u\n",
4659 Q ? 'q' : 'd', dreg,
4660 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4667 if ((C >> 1) == 0) {
4670 if ((theInstr >> 20) & 1)
4672 op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2;
4673 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4674 DIP("vceq.f32 %c%u, %c%u, %c%u\n",
4675 Q ? 'q' : 'd', dreg,
4676 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4681 if ((C >> 1) == 0) {
4684 if ((theInstr >> 20) & 1)
4686 op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
4687 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4688 DIP("vcge.f32 %c%u, %c%u, %c%u\n",
4689 Q ? 'q' : 'd', dreg,
4690 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4694 if ((theInstr >> 20) & 1)
4696 op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
4697 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4698 DIP("vcgt.f32 %c%u, %c%u, %c%u\n",
4699 Q ? 'q' : 'd', dreg,
4700 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4706 UInt op_bit = (theInstr >> 21) & 1;
4708 op2 = Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2;
4710 op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
4711 assign(res, binop(op,
4712 unop(op2, mkexpr(arg_n)),
4713 unop(op2, mkexpr(arg_m))));
4715 op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
4716 assign(res, binop(op,
4717 unop(op2, mkexpr(arg_n)),
4718 unop(op2, mkexpr(arg_m))));
4720 DIP("vacg%c.f32 %c%u, %c%u, %c%u\n", op_bit ? 't' : 'e',
4721 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
4722 Q ? 'q' : 'd', mreg);
4731 if ((theInstr >> 20) & 1)
4733 if ((theInstr >> 21) & 1) {
4734 op = Q ? Iop_Min32Fx4 : Iop_Min32Fx2;
4735 DIP("vmin.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4736 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4738 op = Q ? Iop_Max32Fx4 : Iop_Max32Fx2;
4739 DIP("vmax.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4740 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4742 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4748 if ((theInstr >> 20) & 1)
4750 if ((theInstr >> 21) & 1) {
4751 op = Iop_PwMin32Fx2;
4752 DIP("vpmin.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4754 op = Iop_PwMax32Fx2;
4755 DIP("vpmax.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4757 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4761 if ((C >> 1) == 0) {
4763 if ((theInstr >> 20) & 1)
4765 assign(res, binop(Q ? Iop_Recps32Fx4 : Iop_Recps32Fx2,
4768 DIP("vrecps.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4769 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4772 if ((theInstr >> 20) & 1)
4774 assign(res, binop(Q ? Iop_Rsqrts32Fx4 : Iop_Rsqrts32Fx2,
4777 DIP("vrsqrts.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4778 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4786 putQReg(dreg, mkexpr(res), condT);
4788 putDRegI64(dreg, mkexpr(res), condT);
4794 /* A7.4.2 Three registers of different length */
4796 Bool dis_neon_data_3diff ( UInt theInstr, IRTemp condT )
4798 UInt A = (theInstr >> 8) & 0xf;
4799 UInt B = (theInstr >> 20) & 3;
4800 UInt U = (theInstr >> 24) & 1;
4801 UInt P = (theInstr >> 9) & 1;
4802 UInt mreg = get_neon_m_regno(theInstr);
4803 UInt nreg = get_neon_n_regno(theInstr);
4804 UInt dreg = get_neon_d_regno(theInstr);
4807 IRTemp res, arg_m, arg_n, cond, tmp;
4808 IROp cvt, cvt2, cmp, op, op2, sh, add;
4810 case 0: case 1: case 2: case 3:
4811 /* VADDL, VADDW, VSUBL, VSUBW */
4818 cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
4819 op = (A & 2) ? Iop_Sub16x8 : Iop_Add16x8;
4822 cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
4823 op = (A & 2) ? Iop_Sub32x4 : Iop_Add32x4;
4826 cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
4827 op = (A & 2) ? Iop_Sub64x2 : Iop_Add64x2;
4834 arg_n = newTemp(Ity_V128);
4835 arg_m = newTemp(Ity_V128);
4840 assign(arg_n, getQReg(nreg));
4842 assign(arg_n, unop(cvt, getDRegI64(nreg)));
4844 assign(arg_m, unop(cvt, getDRegI64(mreg)));
4845 putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
4847 DIP("v%s%c.%c%u q%u, %c%u, d%u\n", (A & 2) ? "sub" : "add",
4848 (A & 1) ? 'w' : 'l', U ? 'u' : 's', 8 << size, dreg,
4849 (A & 1) ? 'q' : 'd', nreg, mreg);
4852 /* VADDHN, VRADDHN */
4863 cvt = Iop_Shorten16x8;
4866 imm = (imm << 16) | imm;
4867 imm = (imm << 32) | imm;
4871 cvt = Iop_Shorten32x4;
4874 imm = (imm << 32) | imm;
4878 cvt = Iop_Shorten64x2;
4887 tmp = newTemp(Ity_V128);
4888 res = newTemp(Ity_V128);
4889 assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
4892 assign(res, binop(op, mkexpr(tmp),
4893 binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
4895 assign(res, mkexpr(tmp));
4897 putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
4899 DIP("v%saddhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
4904 if (!((theInstr >> 23) & 1)) {
4905 vpanic("VABA should not be in dis_neon_data_3diff\n");
4912 cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4913 cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
4914 cvt2 = Iop_Longen8Sx8;
4919 cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4920 cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
4921 cvt2 = Iop_Longen16Sx4;
4926 cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4927 cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
4928 cvt2 = Iop_Longen32Sx2;
4937 arg_n = newTemp(Ity_V128);
4938 arg_m = newTemp(Ity_V128);
4939 cond = newTemp(Ity_V128);
4940 res = newTemp(Ity_V128);
4941 assign(arg_n, unop(cvt, getDRegI64(nreg)));
4942 assign(arg_m, unop(cvt, getDRegI64(mreg)));
4943 assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
4944 getDRegI64(mreg))));
4945 assign(res, binop(op2,
4948 binop(op, mkexpr(arg_n), mkexpr(arg_m)),
4951 binop(op, mkexpr(arg_m), mkexpr(arg_n)),
4952 unop(Iop_NotV128, mkexpr(cond)))),
4954 putQReg(dreg, mkexpr(res), condT);
4955 DIP("vabal.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
4959 /* VSUBHN, VRSUBHN */
4971 cvt = Iop_Shorten16x8;
4974 imm = (imm << 16) | imm;
4975 imm = (imm << 32) | imm;
4980 cvt = Iop_Shorten32x4;
4983 imm = (imm << 32) | imm;
4988 cvt = Iop_Shorten64x2;
4997 tmp = newTemp(Ity_V128);
4998 res = newTemp(Ity_V128);
4999 assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
5002 assign(res, binop(op2, mkexpr(tmp),
5003 binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
5005 assign(res, mkexpr(tmp));
5007 putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
5009 DIP("v%ssubhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
5014 if (!((theInstr >> 23) & 1)) {
5015 vpanic("VABL should not be in dis_neon_data_3diff\n");
5022 cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
5023 cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
5024 cvt2 = Iop_Longen8Sx8;
5028 cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
5029 cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
5030 cvt2 = Iop_Longen16Sx4;
5034 cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
5035 cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
5036 cvt2 = Iop_Longen32Sx2;
5044 arg_n = newTemp(Ity_V128);
5045 arg_m = newTemp(Ity_V128);
5046 cond = newTemp(Ity_V128);
5047 res = newTemp(Ity_V128);
5048 assign(arg_n, unop(cvt, getDRegI64(nreg)));
5049 assign(arg_m, unop(cvt, getDRegI64(mreg)));
5050 assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
5051 getDRegI64(mreg))));
5052 assign(res, binop(Iop_OrV128,
5054 binop(op, mkexpr(arg_n), mkexpr(arg_m)),
5057 binop(op, mkexpr(arg_m), mkexpr(arg_n)),
5058 unop(Iop_NotV128, mkexpr(cond)))));
5059 putQReg(dreg, mkexpr(res), condT);
5060 DIP("vabdl.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
5065 /* VMLAL, VMLSL (integer) */
5072 op = U ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
5073 op2 = P ? Iop_Sub16x8 : Iop_Add16x8;
5076 op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5077 op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5080 op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5081 op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5088 res = newTemp(Ity_V128);
5089 assign(res, binop(op, getDRegI64(nreg),getDRegI64(mreg)));
5090 putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
5091 DIP("vml%cl.%c%u q%u, d%u, d%u\n", P ? 's' : 'a', U ? 'u' : 's',
5092 8 << size, dreg, nreg, mreg);
5096 /* VQDMLAL, VQDMLSL */
5107 op = Iop_QDMulLong16Sx4;
5108 cmp = Iop_CmpEQ16x4;
5109 add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
5110 op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5112 imm = (imm << 16) | imm;
5113 imm = (imm << 32) | imm;
5116 op = Iop_QDMulLong32Sx2;
5117 cmp = Iop_CmpEQ32x2;
5118 add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
5119 op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5121 imm = (imm << 32) | imm;
5126 res = newTemp(Ity_V128);
5127 tmp = newTemp(Ity_V128);
5128 assign(res, binop(op, getDRegI64(nreg), getDRegI64(mreg)));
5129 #ifndef DISABLE_QC_FLAG
5130 assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
5131 setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
5133 setFlag_QC(binop(Iop_And64,
5134 binop(cmp, getDRegI64(nreg), mkU64(imm)),
5135 binop(cmp, getDRegI64(mreg), mkU64(imm))),
5139 putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
5140 DIP("vqdml%cl.s%u q%u, d%u, d%u\n", P ? 's' : 'a', 8 << size, dreg,
5145 /* VMULL (integer or polynomial) */
5152 op = (U) ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
5154 op = Iop_PolynomialMull8x8;
5157 op = (U) ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5160 op = (U) ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5165 putQReg(dreg, binop(op, getDRegI64(nreg),
5166 getDRegI64(mreg)), condT);
5167 DIP("vmull.%c%u q%u, d%u, d%u\n", P ? 'p' : (U ? 'u' : 's'),
5168 8 << size, dreg, nreg, mreg);
5183 op = Iop_QDMulLong16Sx4;
5184 op2 = Iop_CmpEQ16x4;
5186 imm = (imm << 16) | imm;
5187 imm = (imm << 32) | imm;
5190 op = Iop_QDMulLong32Sx2;
5191 op2 = Iop_CmpEQ32x2;
5193 imm = (imm << 32) | imm;
5198 putQReg(dreg, binop(op, getDRegI64(nreg), getDRegI64(mreg)),
5200 #ifndef DISABLE_QC_FLAG
5201 setFlag_QC(binop(Iop_And64,
5202 binop(op2, getDRegI64(nreg), mkU64(imm)),
5203 binop(op2, getDRegI64(mreg), mkU64(imm))),
5207 DIP("vqdmull.s%u q%u, d%u, d%u\n", 8 << size, dreg, nreg, mreg);
5215 /* A7.4.3 Two registers and a scalar */
5217 Bool dis_neon_data_2reg_and_scalar ( UInt theInstr, IRTemp condT )
5219 # define INSN(_bMax,_bMin) SLICE_UInt(theInstr, (_bMax), (_bMin))
5220 UInt U = INSN(24,24);
5221 UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
5222 UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
5223 UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
5224 UInt size = INSN(21,20);
5226 UInt Q = INSN(24,24);
5228 if (INSN(27,25) != 1 || INSN(23,23) != 1
5229 || INSN(6,6) != 1 || INSN(4,4) != 0)
5232 /* VMLA, VMLS (scalar) */
5233 if ((INSN(11,8) & BITS4(1,0,1,0)) == BITS4(0,0,0,0)) {
5234 IRTemp res, arg_m, arg_n;
5235 IROp dup, get, op, op2, add, sub;
5237 if ((dreg & 1) || (nreg & 1))
5241 res = newTemp(Ity_V128);
5242 arg_m = newTemp(Ity_V128);
5243 arg_n = newTemp(Ity_V128);
5244 assign(arg_n, getQReg(nreg));
5248 get = Iop_GetElem16x4;
5254 get = Iop_GetElem32x2;
5264 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5266 res = newTemp(Ity_I64);
5267 arg_m = newTemp(Ity_I64);
5268 arg_n = newTemp(Ity_I64);
5269 assign(arg_n, getDRegI64(nreg));
5273 get = Iop_GetElem16x4;
5279 get = Iop_GetElem32x2;
5289 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5294 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
5295 add = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
5296 sub = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
5308 op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
5309 add = Q ? Iop_Add16x8 : Iop_Add16x4;
5310 sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
5313 op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
5314 add = Q ? Iop_Add32x4 : Iop_Add32x2;
5315 sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
5324 op2 = INSN(10,10) ? sub : add;
5325 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5327 putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)),
5330 putDRegI64(dreg, binop(op2, getDRegI64(dreg), mkexpr(res)),
5332 DIP("vml%c.%c%u %c%u, %c%u, d%u[%u]\n", INSN(10,10) ? 's' : 'a',
5333 INSN(8,8) ? 'f' : 'i', 8 << size,
5334 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, mreg, index);
5338 /* VMLAL, VMLSL (scalar) */
5339 if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,0)) {
5340 IRTemp res, arg_m, arg_n;
5341 IROp dup, get, op, op2, add, sub;
5345 res = newTemp(Ity_V128);
5346 arg_m = newTemp(Ity_I64);
5347 arg_n = newTemp(Ity_I64);
5348 assign(arg_n, getDRegI64(nreg));
5352 get = Iop_GetElem16x4;
5358 get = Iop_GetElem32x2;
5368 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5371 op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5376 op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5386 op2 = INSN(10,10) ? sub : add;
5387 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5388 putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
5389 DIP("vml%cl.%c%u q%u, d%u, d%u[%u]\n",
5390 INSN(10,10) ? 's' : 'a', U ? 'u' : 's',
5391 8 << size, dreg, nreg, mreg, index);
5395 /* VQDMLAL, VQDMLSL (scalar) */
5396 if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,1) && !U) {
5397 IRTemp res, arg_m, arg_n, tmp;
5398 IROp dup, get, op, op2, add, cmp;
5399 UInt P = INSN(10,10);
5404 res = newTemp(Ity_V128);
5405 arg_m = newTemp(Ity_I64);
5406 arg_n = newTemp(Ity_I64);
5407 assign(arg_n, getDRegI64(nreg));
5411 get = Iop_GetElem16x4;
5417 get = Iop_GetElem32x2;
5427 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5433 op = Iop_QDMulLong16Sx4;
5434 cmp = Iop_CmpEQ16x4;
5435 add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
5436 op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5438 imm = (imm << 16) | imm;
5439 imm = (imm << 32) | imm;
5442 op = Iop_QDMulLong32Sx2;
5443 cmp = Iop_CmpEQ32x2;
5444 add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
5445 op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5447 imm = (imm << 32) | imm;
5452 res = newTemp(Ity_V128);
5453 tmp = newTemp(Ity_V128);
5454 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5455 #ifndef DISABLE_QC_FLAG
5456 assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
5457 setFlag_QC(binop(Iop_And64,
5458 binop(cmp, mkexpr(arg_n), mkU64(imm)),
5459 binop(cmp, mkexpr(arg_m), mkU64(imm))),
5462 setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
5465 putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
5466 DIP("vqdml%cl.s%u q%u, d%u, d%u[%u]\n", P ? 's' : 'a', 8 << size,
5467 dreg, nreg, mreg, index);
5471 /* VMUL (by scalar) */
5472 if ((INSN(11,8) & BITS4(1,1,1,0)) == BITS4(1,0,0,0)) {
5473 IRTemp res, arg_m, arg_n;
5476 if ((dreg & 1) || (nreg & 1))
5480 res = newTemp(Ity_V128);
5481 arg_m = newTemp(Ity_V128);
5482 arg_n = newTemp(Ity_V128);
5483 assign(arg_n, getQReg(nreg));
5487 get = Iop_GetElem16x4;
5493 get = Iop_GetElem32x2;
5503 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5505 res = newTemp(Ity_I64);
5506 arg_m = newTemp(Ity_I64);
5507 arg_n = newTemp(Ity_I64);
5508 assign(arg_n, getDRegI64(nreg));
5512 get = Iop_GetElem16x4;
5518 get = Iop_GetElem32x2;
5528 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5532 op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
5535 op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
5543 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5545 putQReg(dreg, mkexpr(res), condT);
5547 putDRegI64(dreg, mkexpr(res), condT);
5548 DIP("vmul.i%u %c%u, %c%u, d%u[%u]\n", 8 << size, Q ? 'q' : 'd', dreg,
5549 Q ? 'q' : 'd', nreg, mreg, index);
5553 /* VMULL (scalar) */
5554 if (INSN(11,8) == BITS4(1,0,1,0)) {
5555 IRTemp res, arg_m, arg_n;
5560 res = newTemp(Ity_V128);
5561 arg_m = newTemp(Ity_I64);
5562 arg_n = newTemp(Ity_I64);
5563 assign(arg_n, getDRegI64(nreg));
5567 get = Iop_GetElem16x4;
5573 get = Iop_GetElem32x2;
5583 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5585 case 1: op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; break;
5586 case 2: op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; break;
5587 case 0: case 3: return False;
5588 default: vassert(0);
5590 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5591 putQReg(dreg, mkexpr(res), condT);
5592 DIP("vmull.%c%u q%u, d%u, d%u[%u]\n", U ? 'u' : 's', 8 << size, dreg,
5598 if (INSN(11,8) == BITS4(1,0,1,1) && !U) {
5599 IROp op ,op2, dup, get;
5601 IRTemp arg_m, arg_n;
5605 arg_m = newTemp(Ity_I64);
5606 arg_n = newTemp(Ity_I64);
5607 assign(arg_n, getDRegI64(nreg));
5611 get = Iop_GetElem16x4;
5617 get = Iop_GetElem32x2;
5627 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5633 op = Iop_QDMulLong16Sx4;
5634 op2 = Iop_CmpEQ16x4;
5636 imm = (imm << 16) | imm;
5637 imm = (imm << 32) | imm;
5640 op = Iop_QDMulLong32Sx2;
5641 op2 = Iop_CmpEQ32x2;
5643 imm = (imm << 32) | imm;
5648 putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
5650 #ifndef DISABLE_QC_FLAG
5651 setFlag_QC(binop(Iop_And64,
5652 binop(op2, mkexpr(arg_n), mkU64(imm)),
5653 binop(op2, mkexpr(arg_m), mkU64(imm))),
5657 DIP("vqdmull.s%u q%u, d%u, d%u[%u]\n", 8 << size, dreg, nreg, mreg,
5663 if (INSN(11,8) == BITS4(1,1,0,0)) {
5664 IROp op ,op2, dup, get;
5666 IRTemp res, arg_m, arg_n;
5668 if ((dreg & 1) || (nreg & 1))
5672 res = newTemp(Ity_V128);
5673 arg_m = newTemp(Ity_V128);
5674 arg_n = newTemp(Ity_V128);
5675 assign(arg_n, getQReg(nreg));
5679 get = Iop_GetElem16x4;
5685 get = Iop_GetElem32x2;
5695 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5697 res = newTemp(Ity_I64);
5698 arg_m = newTemp(Ity_I64);
5699 arg_n = newTemp(Ity_I64);
5700 assign(arg_n, getDRegI64(nreg));
5704 get = Iop_GetElem16x4;
5710 get = Iop_GetElem32x2;
5720 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5727 op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
5728 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
5730 imm = (imm << 16) | imm;
5731 imm = (imm << 32) | imm;
5734 op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
5735 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
5737 imm = (imm << 32) | imm;
5742 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5743 #ifndef DISABLE_QC_FLAG
5744 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
5745 binop(op2, mkexpr(arg_n),
5746 Q ? mkU128(imm) : mkU64(imm)),
5747 binop(op2, mkexpr(arg_m),
5748 Q ? mkU128(imm) : mkU64(imm))),
5749 Q ? mkU128(0) : mkU64(0),
5753 putQReg(dreg, mkexpr(res), condT);
5755 putDRegI64(dreg, mkexpr(res), condT);
5756 DIP("vqdmulh.s%u %c%u, %c%u, d%u[%u]\n",
5757 8 << size, Q ? 'q' : 'd', dreg,
5758 Q ? 'q' : 'd', nreg, mreg, index);
5762 /* VQRDMULH (scalar) */
5763 if (INSN(11,8) == BITS4(1,1,0,1)) {
5764 IROp op ,op2, dup, get;
5766 IRTemp res, arg_m, arg_n;
5768 if ((dreg & 1) || (nreg & 1))
5772 res = newTemp(Ity_V128);
5773 arg_m = newTemp(Ity_V128);
5774 arg_n = newTemp(Ity_V128);
5775 assign(arg_n, getQReg(nreg));
5779 get = Iop_GetElem16x4;
5785 get = Iop_GetElem32x2;
5795 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5797 res = newTemp(Ity_I64);
5798 arg_m = newTemp(Ity_I64);
5799 arg_n = newTemp(Ity_I64);
5800 assign(arg_n, getDRegI64(nreg));
5804 get = Iop_GetElem16x4;
5810 get = Iop_GetElem32x2;
5820 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5827 op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
5828 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
5830 imm = (imm << 16) | imm;
5831 imm = (imm << 32) | imm;
5834 op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
5835 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
5837 imm = (imm << 32) | imm;
5842 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5843 #ifndef DISABLE_QC_FLAG
5844 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
5845 binop(op2, mkexpr(arg_n),
5846 Q ? mkU128(imm) : mkU64(imm)),
5847 binop(op2, mkexpr(arg_m),
5848 Q ? mkU128(imm) : mkU64(imm))),
5849 Q ? mkU128(0) : mkU64(0),
5853 putQReg(dreg, mkexpr(res), condT);
5855 putDRegI64(dreg, mkexpr(res), condT);
5856 DIP("vqrdmulh.s%u %c%u, %c%u, d%u[%u]\n",
5857 8 << size, Q ? 'q' : 'd', dreg,
5858 Q ? 'q' : 'd', nreg, mreg, index);
5866 /* A7.4.4 Two registers and a shift amount */
5868 Bool dis_neon_data_2reg_and_shift ( UInt theInstr, IRTemp condT )
5870 UInt A = (theInstr >> 8) & 0xf;
5871 UInt B = (theInstr >> 6) & 1;
5872 UInt L = (theInstr >> 7) & 1;
5873 UInt U = (theInstr >> 24) & 1;
5875 UInt imm6 = (theInstr >> 16) & 0x3f;
5879 UInt mreg = get_neon_m_regno(theInstr);
5880 UInt dreg = get_neon_d_regno(theInstr);
5882 IROp op, cvt, add = Iop_INVALID, cvt2, op_rev;
5883 IRTemp reg_m, res, mask;
5885 if (L == 0 && ((theInstr >> 19) & 7) == 0)
5886 /* It is one reg and immediate */
5889 tmp = (L << 6) | imm6;
5892 shift_imm = 64 - imm6;
5893 } else if (tmp & 0x20) {
5895 shift_imm = 64 - imm6;
5896 } else if (tmp & 0x10) {
5898 shift_imm = 32 - imm6;
5899 } else if (tmp & 0x8) {
5901 shift_imm = 16 - imm6;
5910 if (shift_imm > 0) {
5915 imm = (imm << 8) | imm;
5918 imm = (imm << 16) | imm;
5921 imm = (imm << 32) | imm;
5929 reg_m = newTemp(Ity_V128);
5930 res = newTemp(Ity_V128);
5931 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
5932 assign(reg_m, getQReg(mreg));
5936 op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
5940 op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
5944 op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
5948 op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
5954 reg_m = newTemp(Ity_I64);
5955 res = newTemp(Ity_I64);
5956 imm_val = mkU64(imm);
5957 assign(reg_m, getDRegI64(mreg));
5961 op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
5965 op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
5969 op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
5973 op = U ? Iop_Shr64 : Iop_Sar64;
5984 binop(Q ? Iop_AndV128 : Iop_And64,
5987 mkU8(shift_imm - 1)),
5991 res = newTemp(Ity_V128);
5992 assign(res, getQReg(mreg));
5994 res = newTemp(Ity_I64);
5995 assign(res, getDRegI64(mreg));
6000 putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
6003 putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
6006 DIP("vrsra.%c%u %c%u, %c%u, #%u\n",
6007 U ? 'u' : 's', 8 << size,
6008 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6011 putQReg(dreg, mkexpr(res), condT);
6013 putDRegI64(dreg, mkexpr(res), condT);
6015 DIP("vrshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6016 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6023 reg_m = newTemp(Ity_V128);
6024 assign(reg_m, getQReg(mreg));
6025 res = newTemp(Ity_V128);
6027 reg_m = newTemp(Ity_I64);
6028 assign(reg_m, getDRegI64(mreg));
6029 res = newTemp(Ity_I64);
6034 op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
6038 op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
6042 op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
6046 op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
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;
6074 assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6077 putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
6080 putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
6083 DIP("vsra.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6084 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6087 putQReg(dreg, mkexpr(res), condT);
6089 putDRegI64(dreg, mkexpr(res), condT);
6091 DIP("vshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6092 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6100 res = newTemp(Ity_V128);
6101 mask = newTemp(Ity_V128);
6103 res = newTemp(Ity_I64);
6104 mask = newTemp(Ity_I64);
6107 case 0: op = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; break;
6108 case 1: op = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; break;
6109 case 2: op = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; break;
6110 case 3: op = Q ? Iop_ShrN64x2 : Iop_Shr64; break;
6111 default: vassert(0);
6114 assign(mask, binop(op, binop(Iop_64HLtoV128,
6115 mkU64(0xFFFFFFFFFFFFFFFFLL),
6116 mkU64(0xFFFFFFFFFFFFFFFFLL)),
6118 assign(res, binop(Iop_OrV128,
6126 putQReg(dreg, mkexpr(res), condT);
6128 assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
6130 assign(res, binop(Iop_Or64,
6138 putDRegI64(dreg, mkexpr(res), condT);
6140 DIP("vsri.%u %c%u, %c%u, #%u\n",
6141 8 << size, Q ? 'q' : 'd', dreg,
6142 Q ? 'q' : 'd', mreg, shift_imm);
6147 shift_imm = 8 * (1 << size) - shift_imm;
6149 res = newTemp(Ity_V128);
6150 mask = newTemp(Ity_V128);
6152 res = newTemp(Ity_I64);
6153 mask = newTemp(Ity_I64);
6156 case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
6157 case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
6158 case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
6159 case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
6160 default: vassert(0);
6163 assign(mask, binop(op, binop(Iop_64HLtoV128,
6164 mkU64(0xFFFFFFFFFFFFFFFFLL),
6165 mkU64(0xFFFFFFFFFFFFFFFFLL)),
6167 assign(res, binop(Iop_OrV128,
6175 putQReg(dreg, mkexpr(res), condT);
6177 assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
6179 assign(res, binop(Iop_Or64,
6187 putDRegI64(dreg, mkexpr(res), condT);
6189 DIP("vsli.%u %c%u, %c%u, #%u\n",
6190 8 << size, Q ? 'q' : 'd', dreg,
6191 Q ? 'q' : 'd', mreg, shift_imm);
6195 shift_imm = 8 * (1 << size) - shift_imm;
6197 res = newTemp(Ity_V128);
6199 res = newTemp(Ity_I64);
6202 case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
6203 case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
6204 case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
6205 case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
6206 default: vassert(0);
6208 assign(res, binop(op, Q ? getQReg(mreg) : getDRegI64(mreg),
6211 putQReg(dreg, mkexpr(res), condT);
6213 putDRegI64(dreg, mkexpr(res), condT);
6215 DIP("vshl.i%u %c%u, %c%u, #%u\n",
6216 8 << size, Q ? 'q' : 'd', dreg,
6217 Q ? 'q' : 'd', mreg, shift_imm);
6224 shift_imm = 8 * (1 << size) - shift_imm;
6229 op = Q ? Iop_QShlN8x16 : Iop_QShlN8x8;
6230 op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
6233 op = Q ? Iop_QShlN16x8 : Iop_QShlN16x4;
6234 op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
6237 op = Q ? Iop_QShlN32x4 : Iop_QShlN32x2;
6238 op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
6241 op = Q ? Iop_QShlN64x2 : Iop_QShlN64x1;
6242 op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
6247 DIP("vqshl.u%u %c%u, %c%u, #%u\n",
6249 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6253 op = Q ? Iop_QShlN8Sx16 : Iop_QShlN8Sx8;
6254 op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
6257 op = Q ? Iop_QShlN16Sx8 : Iop_QShlN16Sx4;
6258 op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
6261 op = Q ? Iop_QShlN32Sx4 : Iop_QShlN32Sx2;
6262 op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
6265 op = Q ? Iop_QShlN64Sx2 : Iop_QShlN64Sx1;
6266 op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
6271 DIP("vqshlu.s%u %c%u, %c%u, #%u\n",
6273 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6280 op = Q ? Iop_QSalN8x16 : Iop_QSalN8x8;
6281 op_rev = Q ? Iop_SarN8x16 : Iop_SarN8x8;
6284 op = Q ? Iop_QSalN16x8 : Iop_QSalN16x4;
6285 op_rev = Q ? Iop_SarN16x8 : Iop_SarN16x4;
6288 op = Q ? Iop_QSalN32x4 : Iop_QSalN32x2;
6289 op_rev = Q ? Iop_SarN32x4 : Iop_SarN32x2;
6292 op = Q ? Iop_QSalN64x2 : Iop_QSalN64x1;
6293 op_rev = Q ? Iop_SarN64x2 : Iop_Sar64;
6298 DIP("vqshl.s%u %c%u, %c%u, #%u\n",
6300 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6303 tmp = newTemp(Ity_V128);
6304 res = newTemp(Ity_V128);
6305 reg_m = newTemp(Ity_V128);
6306 assign(reg_m, getQReg(mreg));
6308 tmp = newTemp(Ity_I64);
6309 res = newTemp(Ity_I64);
6310 reg_m = newTemp(Ity_I64);
6311 assign(reg_m, getDRegI64(mreg));
6313 assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6314 #ifndef DISABLE_QC_FLAG
6315 assign(tmp, binop(op_rev, mkexpr(res), mkU8(shift_imm)));
6316 setFlag_QC(mkexpr(tmp), mkexpr(reg_m), Q, condT);
6319 putQReg(dreg, mkexpr(res), condT);
6321 putDRegI64(dreg, mkexpr(res), condT);
6328 dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
6329 mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
6336 reg_m = newTemp(Ity_V128);
6337 assign(reg_m, getQReg(mreg));
6338 res = newTemp(Ity_I64);
6342 narOp = Iop_Shorten16x8;
6346 narOp = Iop_Shorten32x4;
6350 narOp = Iop_Shorten64x2;
6355 assign(res, unop(narOp,
6359 putDRegI64(dreg, mkexpr(res), condT);
6360 DIP("vshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6365 IROp addOp, shOp, narOp;
6367 reg_m = newTemp(Ity_V128);
6368 assign(reg_m, getQReg(mreg));
6369 res = newTemp(Ity_I64);
6372 case 0: imm = (imm << 8) | imm; /* fall through */
6373 case 1: imm = (imm << 16) | imm; /* fall through */
6374 case 2: imm = (imm << 32) | imm; /* fall through */
6376 default: vassert(0);
6378 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
6381 addOp = Iop_Add16x8;
6382 shOp = Iop_ShrN16x8;
6383 narOp = Iop_Shorten16x8;
6386 addOp = Iop_Add32x4;
6387 shOp = Iop_ShrN32x4;
6388 narOp = Iop_Shorten32x4;
6391 addOp = Iop_Add64x2;
6392 shOp = Iop_ShrN64x2;
6393 narOp = Iop_Shorten64x2;
6398 assign(res, unop(narOp,
6406 mkU8(shift_imm - 1)),
6408 putDRegI64(dreg, mkexpr(res), condT);
6409 if (shift_imm == 0) {
6410 DIP("vmov%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6413 DIP("vrshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6422 dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
6423 mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
6428 if ((theInstr >> 8) & 1) {
6431 op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
6432 cvt = U ? Iop_QShortenU16Ux8 : Iop_QShortenS16Sx8;
6433 cvt2 = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
6436 op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
6437 cvt = U ? Iop_QShortenU32Ux4 : Iop_QShortenS32Sx4;
6438 cvt2 = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
6441 op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
6442 cvt = U ? Iop_QShortenU64Ux2 : Iop_QShortenS64Sx2;
6443 cvt2 = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
6448 DIP("vq%sshrn.%c%u d%u, q%u, #%u\n", B ? "r" : "",
6449 U ? 'u' : 's', 8 << size, dreg, mreg, shift_imm);
6455 cvt = Iop_QShortenU16Sx8;
6456 cvt2 = Iop_Longen8Ux8;
6460 cvt = Iop_QShortenU32Sx4;
6461 cvt2 = Iop_Longen16Ux4;
6465 cvt = Iop_QShortenU64Sx2;
6466 cvt2 = Iop_Longen32Ux2;
6471 DIP("vq%sshrun.s%u d%u, q%u, #%u\n", B ? "r" : "",
6472 8 << size, dreg, mreg, shift_imm);
6475 if (shift_imm > 0) {
6478 case 1: imm = (imm << 16) | imm; /* fall through */
6479 case 2: imm = (imm << 32) | imm; /* fall through */
6481 case 0: default: vassert(0);
6484 case 1: add = Iop_Add16x8; break;
6485 case 2: add = Iop_Add32x4; break;
6486 case 3: add = Iop_Add64x2; break;
6487 case 0: default: vassert(0);
6491 reg_m = newTemp(Ity_V128);
6492 res = newTemp(Ity_V128);
6493 assign(reg_m, getQReg(mreg));
6495 /* VQRSHRN, VQRSHRUN */
6496 assign(res, binop(add,
6497 binop(op, mkexpr(reg_m), mkU8(shift_imm)),
6501 mkU8(shift_imm - 1)),
6504 /* VQSHRN, VQSHRUN */
6505 assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6507 #ifndef DISABLE_QC_FLAG
6508 setFlag_QC(unop(cvt2, unop(cvt, mkexpr(res))), mkexpr(res),
6511 putDRegI64(dreg, unop(cvt, mkexpr(res)), condT);
6515 VMOVL ::= VSHLL #0 */
6521 shift_imm = (8 << size) - shift_imm;
6522 res = newTemp(Ity_V128);
6526 cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
6530 cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
6534 cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
6541 assign(res, binop(op, unop(cvt, getDRegI64(mreg)), mkU8(shift_imm)));
6542 putQReg(dreg, mkexpr(res), condT);
6543 if (shift_imm == 0) {
6544 DIP("vmovl.%c%u q%u, d%u\n", U ? 'u' : 's', 8 << size,
6547 DIP("vshll.%c%u q%u, d%u, #%u\n", U ? 'u' : 's', 8 << size,
6548 dreg, mreg, shift_imm);
6553 /* VCVT floating-point <-> fixed-point */
6554 if ((theInstr >> 8) & 1) {
6556 op = Q ? Iop_F32ToFixed32Ux4_RZ : Iop_F32ToFixed32Ux2_RZ;
6558 op = Q ? Iop_F32ToFixed32Sx4_RZ : Iop_F32ToFixed32Sx2_RZ;
6560 DIP("vcvt.%c32.f32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
6561 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
6562 64 - ((theInstr >> 16) & 0x3f));
6565 op = Q ? Iop_Fixed32UToF32x4_RN : Iop_Fixed32UToF32x2_RN;
6567 op = Q ? Iop_Fixed32SToF32x4_RN : Iop_Fixed32SToF32x2_RN;
6569 DIP("vcvt.f32.%c32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
6570 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
6571 64 - ((theInstr >> 16) & 0x3f));
6573 if (((theInstr >> 21) & 1) == 0)
6576 putQReg(dreg, binop(op, getQReg(mreg),
6577 mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
6579 putDRegI64(dreg, binop(op, getDRegI64(mreg),
6580 mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
6590 /* A7.4.5 Two registers, miscellaneous */
6592 Bool dis_neon_data_2reg_misc ( UInt theInstr, IRTemp condT )
6594 UInt A = (theInstr >> 16) & 3;
6595 UInt B = (theInstr >> 6) & 0x1f;
6596 UInt Q = (theInstr >> 6) & 1;
6597 UInt U = (theInstr >> 24) & 1;
6598 UInt size = (theInstr >> 18) & 3;
6599 UInt dreg = get_neon_d_regno(theInstr);
6600 UInt mreg = get_neon_m_regno(theInstr);
6601 UInt F = (theInstr >> 10) & 1;
6608 arg_m = newTemp(Ity_V128);
6609 res = newTemp(Ity_V128);
6610 assign(arg_m, getQReg(mreg));
6612 arg_m = newTemp(Ity_I64);
6613 res = newTemp(Ity_I64);
6614 assign(arg_m, getDRegI64(mreg));
6622 op = Q ? Iop_Reverse64_8x16 : Iop_Reverse64_8x8;
6625 op = Q ? Iop_Reverse64_16x8 : Iop_Reverse64_16x4;
6628 op = Q ? Iop_Reverse64_32x4 : Iop_Reverse64_32x2;
6635 assign(res, unop(op, mkexpr(arg_m)));
6636 DIP("vrev64.%u %c%u, %c%u\n", 8 << size,
6637 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6645 op = Q ? Iop_Reverse32_8x16 : Iop_Reverse32_8x8;
6648 op = Q ? Iop_Reverse32_16x8 : Iop_Reverse32_16x4;
6656 assign(res, unop(op, mkexpr(arg_m)));
6657 DIP("vrev32.%u %c%u, %c%u\n", 8 << size,
6658 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6666 op = Q ? Iop_Reverse16_8x16 : Iop_Reverse16_8x8;
6675 assign(res, unop(op, mkexpr(arg_m)));
6676 DIP("vrev16.%u %c%u, %c%u\n", 8 << size,
6677 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6686 U = (theInstr >> 7) & 1;
6689 case 0: op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16; break;
6690 case 1: op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8; break;
6691 case 2: op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4; break;
6692 case 3: return False;
6693 default: vassert(0);
6697 case 0: op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8; break;
6698 case 1: op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4; break;
6699 case 2: op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2; break;
6700 case 3: return False;
6701 default: vassert(0);
6704 assign(res, unop(op, mkexpr(arg_m)));
6705 DIP("vpaddl.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
6706 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6716 case 0: op = Q ? Iop_Cls8Sx16 : Iop_Cls8Sx8; break;
6717 case 1: op = Q ? Iop_Cls16Sx8 : Iop_Cls16Sx4; break;
6718 case 2: op = Q ? Iop_Cls32Sx4 : Iop_Cls32Sx2; break;
6719 case 3: return False;
6720 default: vassert(0);
6722 assign(res, unop(op, mkexpr(arg_m)));
6723 DIP("vcls.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6724 Q ? 'q' : 'd', mreg);
6731 case 0: op = Q ? Iop_Clz8Sx16 : Iop_Clz8Sx8; break;
6732 case 1: op = Q ? Iop_Clz16Sx8 : Iop_Clz16Sx4; break;
6733 case 2: op = Q ? Iop_Clz32Sx4 : Iop_Clz32Sx2; break;
6734 case 3: return False;
6735 default: vassert(0);
6737 assign(res, unop(op, mkexpr(arg_m)));
6738 DIP("vclz.i%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6739 Q ? 'q' : 'd', mreg);
6744 assign(res, unop(Q ? Iop_Cnt8x16 : Iop_Cnt8x8, mkexpr(arg_m)));
6745 DIP("vcnt.8 %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
6751 assign(res, unop(Iop_NotV128, mkexpr(arg_m)));
6753 assign(res, unop(Iop_Not64, mkexpr(arg_m)));
6754 DIP("vmvn %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
6761 U = (theInstr >> 7) & 1;
6765 op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16;
6766 add_op = Iop_Add16x8;
6769 op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8;
6770 add_op = Iop_Add32x4;
6773 op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4;
6774 add_op = Iop_Add64x2;
6784 op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8;
6785 add_op = Iop_Add16x4;
6788 op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4;
6789 add_op = Iop_Add32x2;
6792 op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2;
6802 arg_d = newTemp(Ity_V128);
6803 assign(arg_d, getQReg(dreg));
6805 arg_d = newTemp(Ity_I64);
6806 assign(arg_d, getDRegI64(dreg));
6808 assign(res, binop(add_op, unop(op, mkexpr(arg_m)),
6810 DIP("vpadal.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
6811 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6816 IROp op_sub, op_qsub, op_cmp;
6818 IRExpr *zero1, *zero2;
6821 zero1 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6822 zero2 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6823 mask = newTemp(Ity_V128);
6824 tmp = newTemp(Ity_V128);
6828 mask = newTemp(Ity_I64);
6829 tmp = newTemp(Ity_I64);
6833 op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8;
6834 op_qsub = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
6835 op_cmp = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
6838 op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
6839 op_qsub = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
6840 op_cmp = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4;
6843 op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
6844 op_qsub = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
6845 op_cmp = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2;
6852 assign(mask, binop(op_cmp, mkexpr(arg_m), zero1));
6853 neg = binop(op_qsub, zero2, mkexpr(arg_m));
6854 neg2 = binop(op_sub, zero2, mkexpr(arg_m));
6855 assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
6856 binop(Q ? Iop_AndV128 : Iop_And64,
6859 binop(Q ? Iop_AndV128 : Iop_And64,
6860 unop(Q ? Iop_NotV128 : Iop_Not64,
6863 #ifndef DISABLE_QC_FLAG
6864 assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
6865 binop(Q ? Iop_AndV128 : Iop_And64,
6868 binop(Q ? Iop_AndV128 : Iop_And64,
6869 unop(Q ? Iop_NotV128 : Iop_Not64,
6872 setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
6874 DIP("vqabs.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6875 Q ? 'q' : 'd', mreg);
6883 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6889 op = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
6890 op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
6893 op = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
6894 op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
6897 op = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
6898 op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
6905 assign(res, binop(op, zero, mkexpr(arg_m)));
6906 #ifndef DISABLE_QC_FLAG
6907 setFlag_QC(mkexpr(res), binop(op2, zero, mkexpr(arg_m)),
6910 DIP("vqneg.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6911 Q ? 'q' : 'd', mreg);
6918 putQReg(dreg, mkexpr(res), condT);
6920 putDRegI64(dreg, mkexpr(res), condT);
6925 arg_m = newTemp(Ity_V128);
6926 res = newTemp(Ity_V128);
6927 assign(arg_m, getQReg(mreg));
6929 arg_m = newTemp(Ity_I64);
6930 res = newTemp(Ity_I64);
6931 assign(arg_m, getDRegI64(mreg));
6933 switch ((B >> 1) & 0x7) {
6939 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6945 case 0: case 1: case 3: return False;
6946 case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
6947 default: vassert(0);
6951 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
6952 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
6953 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
6954 case 3: return False;
6955 default: vassert(0);
6958 assign(res, binop(op, mkexpr(arg_m), zero));
6959 DIP("vcgt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
6960 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6968 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6974 case 0: case 1: case 3: return False;
6975 case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
6976 default: vassert(0);
6978 assign(res, binop(op, mkexpr(arg_m), zero));
6981 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
6982 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
6983 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
6984 case 3: return False;
6985 default: vassert(0);
6987 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
6988 binop(op, zero, mkexpr(arg_m))));
6990 DIP("vcge.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
6991 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7000 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7005 case 0: case 1: case 3: return False;
7006 case 2: op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2; break;
7007 default: vassert(0);
7009 assign(res, binop(op, zero, mkexpr(arg_m)));
7012 case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
7013 case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
7014 case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
7015 case 3: return False;
7016 default: vassert(0);
7018 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
7019 unop(op, mkexpr(arg_m))));
7021 DIP("vceq.%c%u %c%u, %c%u, #0\n", F ? 'f' : 'i', 8 << size,
7022 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7030 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7036 case 0: case 1: case 3: return False;
7037 case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
7038 default: vassert(0);
7040 assign(res, binop(op, zero, mkexpr(arg_m)));
7043 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
7044 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
7045 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
7046 case 3: return False;
7047 default: vassert(0);
7049 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
7050 binop(op, mkexpr(arg_m), zero)));
7052 DIP("vcle.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
7053 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7061 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7067 case 0: case 1: case 3: return False;
7068 case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
7069 default: vassert(0);
7071 assign(res, binop(op, zero, mkexpr(arg_m)));
7074 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
7075 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
7076 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
7077 case 3: return False;
7078 default: vassert(0);
7080 assign(res, binop(op, zero, mkexpr(arg_m)));
7082 DIP("vclt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
7083 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7093 case 0: op = Q ? Iop_Abs8x16 : Iop_Abs8x8; break;
7094 case 1: op = Q ? Iop_Abs16x8 : Iop_Abs16x4; break;
7095 case 2: op = Q ? Iop_Abs32x4 : Iop_Abs32x2; break;
7096 case 3: return False;
7097 default: vassert(0);
7099 assign(res, unop(op, mkexpr(arg_m)));
7101 assign(res, unop(Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2,
7104 DIP("vabs.%c%u %c%u, %c%u\n",
7105 F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
7106 Q ? 'q' : 'd', mreg);
7115 case 0: case 1: case 3: return False;
7116 case 2: op = Q ? Iop_Neg32Fx4 : Iop_Neg32Fx2; break;
7117 default: vassert(0);
7119 assign(res, unop(op, mkexpr(arg_m)));
7122 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7127 case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
7128 case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
7129 case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
7130 case 3: return False;
7131 default: vassert(0);
7133 assign(res, binop(op, zero, mkexpr(arg_m)));
7135 DIP("vneg.%c%u %c%u, %c%u\n",
7136 F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
7137 Q ? 'q' : 'd', mreg);
7144 putQReg(dreg, mkexpr(res), condT);
7146 putDRegI64(dreg, mkexpr(res), condT);
7150 if ((B >> 1) == 0) {
7153 arg_m = newTemp(Ity_V128);
7154 assign(arg_m, getQReg(mreg));
7155 putQReg(mreg, getQReg(dreg), condT);
7156 putQReg(dreg, mkexpr(arg_m), condT);
7158 arg_m = newTemp(Ity_I64);
7159 assign(arg_m, getDRegI64(mreg));
7160 putDRegI64(mreg, getDRegI64(dreg), condT);
7161 putDRegI64(dreg, mkexpr(arg_m), condT);
7163 DIP("vswp %c%u, %c%u\n",
7164 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7166 } else if ((B >> 1) == 1) {
7171 arg_m = newTemp(Ity_V128);
7172 arg_d = newTemp(Ity_V128);
7173 res1 = newTemp(Ity_V128);
7174 res2 = newTemp(Ity_V128);
7175 assign(arg_m, getQReg(mreg));
7176 assign(arg_d, getQReg(dreg));
7178 res1 = newTemp(Ity_I64);
7179 res2 = newTemp(Ity_I64);
7180 arg_m = newTemp(Ity_I64);
7181 arg_d = newTemp(Ity_I64);
7182 assign(arg_m, getDRegI64(mreg));
7183 assign(arg_d, getDRegI64(dreg));
7188 op_lo = Iop_InterleaveOddLanes8x16;
7189 op_hi = Iop_InterleaveEvenLanes8x16;
7192 op_lo = Iop_InterleaveOddLanes16x8;
7193 op_hi = Iop_InterleaveEvenLanes16x8;
7196 op_lo = Iop_InterleaveOddLanes32x4;
7197 op_hi = Iop_InterleaveEvenLanes32x4;
7207 op_lo = Iop_InterleaveOddLanes8x8;
7208 op_hi = Iop_InterleaveEvenLanes8x8;
7211 op_lo = Iop_InterleaveOddLanes16x4;
7212 op_hi = Iop_InterleaveEvenLanes16x4;
7215 op_lo = Iop_InterleaveLO32x2;
7216 op_hi = Iop_InterleaveHI32x2;
7224 assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7225 assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7227 putQReg(dreg, mkexpr(res1), condT);
7228 putQReg(mreg, mkexpr(res2), condT);
7230 putDRegI64(dreg, mkexpr(res1), condT);
7231 putDRegI64(mreg, mkexpr(res2), condT);
7233 DIP("vtrn.%u %c%u, %c%u\n",
7234 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7236 } else if ((B >> 1) == 2) {
7240 if (!Q && size == 2)
7243 arg_m = newTemp(Ity_V128);
7244 arg_d = newTemp(Ity_V128);
7245 res1 = newTemp(Ity_V128);
7246 res2 = newTemp(Ity_V128);
7247 assign(arg_m, getQReg(mreg));
7248 assign(arg_d, getQReg(dreg));
7250 res1 = newTemp(Ity_I64);
7251 res2 = newTemp(Ity_I64);
7252 arg_m = newTemp(Ity_I64);
7253 arg_d = newTemp(Ity_I64);
7254 assign(arg_m, getDRegI64(mreg));
7255 assign(arg_d, getDRegI64(dreg));
7259 op_lo = Q ? Iop_CatOddLanes8x16 : Iop_CatOddLanes8x8;
7260 op_hi = Q ? Iop_CatEvenLanes8x16 : Iop_CatEvenLanes8x8;
7263 op_lo = Q ? Iop_CatOddLanes16x8 : Iop_CatOddLanes16x4;
7264 op_hi = Q ? Iop_CatEvenLanes16x8 : Iop_CatEvenLanes16x4;
7267 op_lo = Iop_CatOddLanes32x4;
7268 op_hi = Iop_CatEvenLanes32x4;
7275 assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7276 assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7278 putQReg(dreg, mkexpr(res1), condT);
7279 putQReg(mreg, mkexpr(res2), condT);
7281 putDRegI64(dreg, mkexpr(res1), condT);
7282 putDRegI64(mreg, mkexpr(res2), condT);
7284 DIP("vuzp.%u %c%u, %c%u\n",
7285 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7287 } else if ((B >> 1) == 3) {
7291 if (!Q && size == 2)
7294 arg_m = newTemp(Ity_V128);
7295 arg_d = newTemp(Ity_V128);
7296 res1 = newTemp(Ity_V128);
7297 res2 = newTemp(Ity_V128);
7298 assign(arg_m, getQReg(mreg));
7299 assign(arg_d, getQReg(dreg));
7301 res1 = newTemp(Ity_I64);
7302 res2 = newTemp(Ity_I64);
7303 arg_m = newTemp(Ity_I64);
7304 arg_d = newTemp(Ity_I64);
7305 assign(arg_m, getDRegI64(mreg));
7306 assign(arg_d, getDRegI64(dreg));
7310 op_lo = Q ? Iop_InterleaveHI8x16 : Iop_InterleaveHI8x8;
7311 op_hi = Q ? Iop_InterleaveLO8x16 : Iop_InterleaveLO8x8;
7314 op_lo = Q ? Iop_InterleaveHI16x8 : Iop_InterleaveHI16x4;
7315 op_hi = Q ? Iop_InterleaveLO16x8 : Iop_InterleaveLO16x4;
7318 op_lo = Iop_InterleaveHI32x4;
7319 op_hi = Iop_InterleaveLO32x4;
7326 assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7327 assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7329 putQReg(dreg, mkexpr(res1), condT);
7330 putQReg(mreg, mkexpr(res2), condT);
7332 putDRegI64(dreg, mkexpr(res1), condT);
7333 putDRegI64(mreg, mkexpr(res2), condT);
7335 DIP("vzip.%u %c%u, %c%u\n",
7336 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7338 } else if (B == 8) {
7343 case 0: op = Iop_Shorten16x8; break;
7344 case 1: op = Iop_Shorten32x4; break;
7345 case 2: op = Iop_Shorten64x2; break;
7346 case 3: return False;
7347 default: vassert(0);
7349 putDRegI64(dreg, unop(op, getQReg(mreg)), condT);
7350 DIP("vmovn.i%u d%u, q%u\n", 16 << size, dreg, mreg);
7352 } else if (B == 9 || (B >> 1) == 5) {
7353 /* VQMOVN, VQMOVUN */
7356 dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
7357 mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
7362 case 0: op2 = Iop_Shorten16x8; break;
7363 case 1: op2 = Iop_Shorten32x4; break;
7364 case 2: op2 = Iop_Shorten64x2; break;
7365 case 3: return False;
7366 default: vassert(0);
7373 case 0: op = Iop_QShortenU16Sx8; break;
7374 case 1: op = Iop_QShortenU32Sx4; break;
7375 case 2: op = Iop_QShortenU64Sx2; break;
7376 case 3: return False;
7377 default: vassert(0);
7379 DIP("vqmovun.s%u d%u, q%u\n", 16 << size, dreg, mreg);
7383 case 0: op = Iop_QShortenS16Sx8; break;
7384 case 1: op = Iop_QShortenS32Sx4; break;
7385 case 2: op = Iop_QShortenS64Sx2; break;
7386 case 3: return False;
7387 default: vassert(0);
7389 DIP("vqmovn.s%u d%u, q%u\n", 16 << size, dreg, mreg);
7393 case 0: op = Iop_QShortenU16Ux8; break;
7394 case 1: op = Iop_QShortenU32Ux4; break;
7395 case 2: op = Iop_QShortenU64Ux2; break;
7396 case 3: return False;
7397 default: vassert(0);
7399 DIP("vqmovn.u%u d%u, q%u\n", 16 << size, dreg, mreg);
7404 res = newTemp(Ity_I64);
7405 tmp = newTemp(Ity_I64);
7406 assign(res, unop(op, getQReg(mreg)));
7407 #ifndef DISABLE_QC_FLAG
7408 assign(tmp, unop(op2, getQReg(mreg)));
7409 setFlag_QC(mkexpr(res), mkexpr(tmp), False, condT);
7411 putDRegI64(dreg, mkexpr(res), condT);
7413 } else if (B == 12) {
7414 /* VSHLL (maximum shift) */
7422 shift_imm = 8 << size;
7423 res = newTemp(Ity_V128);
7425 case 0: op = Iop_ShlN16x8; cvt = Iop_Longen8Ux8; break;
7426 case 1: op = Iop_ShlN32x4; cvt = Iop_Longen16Ux4; break;
7427 case 2: op = Iop_ShlN64x2; cvt = Iop_Longen32Ux2; break;
7428 case 3: return False;
7429 default: vassert(0);
7431 assign(res, binop(op, unop(cvt, getDRegI64(mreg)),
7433 putQReg(dreg, mkexpr(res), condT);
7434 DIP("vshll.i%u q%u, d%u, #%u\n", 8 << size, dreg, mreg, 8 << size);
7436 } else if ((B >> 3) == 3 && (B & 3) == 0) {
7437 /* VCVT (half<->single) */
7438 /* Half-precision extensions are needed to run this */
7440 if (((theInstr >> 18) & 3) != 1)
7442 if ((theInstr >> 8) & 1) {
7446 putQReg(dreg, unop(Iop_F16toF32x4, getDRegI64(mreg)),
7448 DIP("vcvt.f32.f16 q%u, d%u\n", dreg, mreg);
7453 putDRegI64(dreg, unop(Iop_F32toF16x4, getQReg(mreg)),
7455 DIP("vcvt.f16.f32 d%u, q%u\n", dreg, mreg);
7464 if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,0)) {
7467 F = (theInstr >> 8) & 1;
7471 op = F ? Iop_Recip32Fx4 : Iop_Recip32x4;
7472 putQReg(dreg, unop(op, getQReg(mreg)), condT);
7473 DIP("vrecpe.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
7475 op = F ? Iop_Recip32Fx2 : Iop_Recip32x2;
7476 putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7477 DIP("vrecpe.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
7480 } else if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,1)) {
7488 op = Q ? Iop_Rsqrte32Fx4 : Iop_Rsqrte32Fx2;
7491 op = Q ? Iop_Rsqrte32x4 : Iop_Rsqrte32x2;
7494 putQReg(dreg, unop(op, getQReg(mreg)), condT);
7495 DIP("vrsqrte.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
7497 putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7498 DIP("vrsqrte.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
7501 } else if ((B >> 3) == 3) {
7502 /* VCVT (fp<->integer) */
7506 switch ((B >> 1) & 3) {
7508 op = Q ? Iop_I32StoFx4 : Iop_I32StoFx2;
7509 DIP("vcvt.f32.s32 %c%u, %c%u\n",
7510 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7513 op = Q ? Iop_I32UtoFx4 : Iop_I32UtoFx2;
7514 DIP("vcvt.f32.u32 %c%u, %c%u\n",
7515 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7518 op = Q ? Iop_FtoI32Sx4_RZ : Iop_FtoI32Sx2_RZ;
7519 DIP("vcvt.s32.f32 %c%u, %c%u\n",
7520 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7523 op = Q ? Iop_FtoI32Ux4_RZ : Iop_FtoI32Ux2_RZ;
7524 DIP("vcvt.u32.f32 %c%u, %c%u\n",
7525 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7531 putQReg(dreg, unop(op, getQReg(mreg)), condT);
7533 putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7547 /* A7.4.6 One register and a modified immediate value */
7549 void ppNeonImm(UInt imm, UInt cmode, UInt op)
7553 case 0: case 1: case 8: case 9:
7554 vex_printf("0x%x", imm);
7556 case 2: case 3: case 10: case 11:
7557 vex_printf("0x%x00", imm);
7560 vex_printf("0x%x0000", imm);
7563 vex_printf("0x%x000000", imm);
7566 vex_printf("0x%xff", imm);
7569 vex_printf("0x%xffff", imm);
7574 for (i = 7; i >= 0; i--)
7575 vex_printf("%s", (imm & (1 << i)) ? "ff" : "00");
7577 vex_printf("0x%x", imm);
7581 vex_printf("0x%x", imm);
7587 const char *ppNeonImmType(UInt cmode, UInt op)
7611 void DIPimm(UInt imm, UInt cmode, UInt op,
7612 const char *instr, UInt Q, UInt dreg)
7614 if (vex_traceflags & VEX_TRACE_FE) {
7615 vex_printf("%s.%s %c%u, #", instr,
7616 ppNeonImmType(cmode, op), Q ? 'q' : 'd', dreg);
7617 ppNeonImm(imm, cmode, op);
7623 Bool dis_neon_data_1reg_and_imm ( UInt theInstr, IRTemp condT )
7625 UInt dreg = get_neon_d_regno(theInstr);
7626 ULong imm_raw = ((theInstr >> 17) & 0x80) | ((theInstr >> 12) & 0x70) |
7628 ULong imm_raw_pp = imm_raw;
7629 UInt cmode = (theInstr >> 8) & 0xf;
7630 UInt op_bit = (theInstr >> 5) & 1;
7632 UInt Q = (theInstr >> 6) & 1;
7640 imm_raw = imm_raw << 8;
7643 imm_raw = imm_raw << 8;
7646 imm_raw = imm_raw << 8;
7649 imm = (imm_raw << 32) | imm_raw;
7652 imm_raw = imm_raw << 8;
7655 imm_raw = (imm_raw << 16) | imm_raw;
7656 imm = (imm_raw << 32) | imm_raw;
7659 imm_raw = (imm_raw << 8) | 0xff;
7662 imm_raw = (imm_raw << 8) | 0xff;
7663 imm = (imm_raw << 32) | imm_raw;
7667 for(i = 0; i < 8; i++) {
7668 imm = (imm << 8) | imm_raw;
7671 for(i = 7; i >= 0; i--) {
7673 for(j = 0; j < 8; j++) {
7674 tmp = (tmp << 1) | ((imm_raw >> i) & 1);
7676 imm = (imm << 8) | tmp;
7681 imm = (imm_raw & 0x80) << 5;
7682 imm |= ~((imm_raw & 0x40) << 5);
7683 for(i = 1; i <= 4; i++)
7684 imm |= (imm_raw & 0x40) << i;
7685 imm |= (imm_raw & 0x7f);
7687 imm = (imm << 32) | imm;
7693 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
7695 imm_val = mkU64(imm);
7697 if (((op_bit == 0) &&
7698 (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 12) == 12))) ||
7699 ((op_bit == 1) && (cmode == 14))) {
7700 /* VMOV (immediate) */
7702 putQReg(dreg, imm_val, condT);
7704 putDRegI64(dreg, imm_val, condT);
7706 DIPimm(imm_raw_pp, cmode, op_bit, "vmov", Q, dreg);
7709 if ((op_bit == 1) &&
7710 (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 14) == 12))) {
7711 /* VMVN (immediate) */
7713 putQReg(dreg, unop(Iop_NotV128, imm_val), condT);
7715 putDRegI64(dreg, unop(Iop_Not64, imm_val), condT);
7717 DIPimm(imm_raw_pp, cmode, op_bit, "vmvn", Q, dreg);
7721 tmp_var = newTemp(Ity_V128);
7722 assign(tmp_var, getQReg(dreg));
7724 tmp_var = newTemp(Ity_I64);
7725 assign(tmp_var, getDRegI64(dreg));
7727 if ((op_bit == 0) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
7728 /* VORR (immediate) */
7730 expr = binop(Iop_OrV128, mkexpr(tmp_var), imm_val);
7732 expr = binop(Iop_Or64, mkexpr(tmp_var), imm_val);
7733 DIPimm(imm_raw_pp, cmode, op_bit, "vorr", Q, dreg);
7734 } else if ((op_bit == 1) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
7735 /* VBIC (immediate) */
7737 expr = binop(Iop_AndV128, mkexpr(tmp_var),
7738 unop(Iop_NotV128, imm_val));
7740 expr = binop(Iop_And64, mkexpr(tmp_var), unop(Iop_Not64, imm_val));
7741 DIPimm(imm_raw_pp, cmode, op_bit, "vbic", Q, dreg);
7746 putQReg(dreg, expr, condT);
7748 putDRegI64(dreg, expr, condT);
7752 /* A7.4 Advanced SIMD data-processing instructions */
7754 Bool dis_neon_data_processing ( UInt theInstr, IRTemp condT )
7756 UInt A = (theInstr >> 19) & 0x1F;
7757 UInt B = (theInstr >> 8) & 0xF;
7758 UInt C = (theInstr >> 4) & 0xF;
7759 UInt U = (theInstr >> 24) & 0x1;
7762 return dis_neon_data_3same(theInstr, condT);
7764 if (((A & 0x17) == 0x10) && ((C & 0x9) == 0x1)) {
7765 return dis_neon_data_1reg_and_imm(theInstr, condT);
7768 return dis_neon_data_2reg_and_shift(theInstr, condT);
7770 if (((C & 5) == 0) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
7771 return dis_neon_data_3diff(theInstr, condT);
7773 if (((C & 5) == 4) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
7774 return dis_neon_data_2reg_and_scalar(theInstr, condT);
7776 if ((A & 0x16) == 0x16) {
7777 if ((U == 0) && ((C & 1) == 0)) {
7778 return dis_neon_vext(theInstr, condT);
7780 if ((U != 1) || ((C & 1) == 1))
7783 return dis_neon_data_2reg_misc(theInstr, condT);
7785 if ((B & 12) == 8) {
7786 return dis_neon_vtb(theInstr, condT);
7788 if ((B == 12) && ((C & 9) == 0)) {
7789 return dis_neon_vdup(theInstr, condT);
7796 /*------------------------------------------------------------*/
7797 /*--- NEON loads and stores ---*/
7798 /*------------------------------------------------------------*/
7800 /* For NEON memory operations, we use the standard scheme to handle
7801 conditionalisation: generate a jump around the instruction if the
7802 condition is false. That's only necessary in Thumb mode, however,
7803 since in ARM mode NEON instructions are unconditional. */
7805 /* A helper function for what follows. It assumes we already went
7806 uncond as per comments at the top of this section. */
7808 void mk_neon_elem_load_to_one_lane( UInt rD, UInt inc, UInt index,
7809 UInt N, UInt size, IRTemp addr )
7814 putDRegI64(rD, triop(Iop_SetElem8x8, getDRegI64(rD), mkU8(index),
7815 loadLE(Ity_I8, mkexpr(addr))), IRTemp_INVALID);
7818 putDRegI64(rD, triop(Iop_SetElem16x4, getDRegI64(rD), mkU8(index),
7819 loadLE(Ity_I16, mkexpr(addr))), IRTemp_INVALID);
7822 putDRegI64(rD, triop(Iop_SetElem32x2, getDRegI64(rD), mkU8(index),
7823 loadLE(Ity_I32, mkexpr(addr))), IRTemp_INVALID);
7828 for (i = 1; i <= N; i++) {
7831 putDRegI64(rD + i * inc,
7832 triop(Iop_SetElem8x8,
7833 getDRegI64(rD + i * inc),
7835 loadLE(Ity_I8, binop(Iop_Add32,
7841 putDRegI64(rD + i * inc,
7842 triop(Iop_SetElem16x4,
7843 getDRegI64(rD + i * inc),
7845 loadLE(Ity_I16, binop(Iop_Add32,
7851 putDRegI64(rD + i * inc,
7852 triop(Iop_SetElem32x2,
7853 getDRegI64(rD + i * inc),
7855 loadLE(Ity_I32, binop(Iop_Add32,
7866 /* A(nother) helper function for what follows. It assumes we already
7867 went uncond as per comments at the top of this section. */
7869 void mk_neon_elem_store_from_one_lane( UInt rD, UInt inc, UInt index,
7870 UInt N, UInt size, IRTemp addr )
7875 storeLE(mkexpr(addr),
7876 binop(Iop_GetElem8x8, getDRegI64(rD), mkU8(index)));
7879 storeLE(mkexpr(addr),
7880 binop(Iop_GetElem16x4, getDRegI64(rD), mkU8(index)));
7883 storeLE(mkexpr(addr),
7884 binop(Iop_GetElem32x2, getDRegI64(rD), mkU8(index)));
7889 for (i = 1; i <= N; i++) {
7892 storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 1)),
7893 binop(Iop_GetElem8x8, getDRegI64(rD + i * inc),
7897 storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 2)),
7898 binop(Iop_GetElem16x4, getDRegI64(rD + i * inc),
7902 storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 4)),
7903 binop(Iop_GetElem32x2, getDRegI64(rD + i * inc),
7912 /* A7.7 Advanced SIMD element or structure load/store instructions */
7914 Bool dis_neon_elem_or_struct_load ( UInt theInstr,
7915 Bool isT, IRTemp condT )
7917 # define INSN(_bMax,_bMin) SLICE_UInt(theInstr, (_bMax), (_bMin))
7918 UInt A = INSN(23,23);
7919 UInt B = INSN(11,8);
7920 UInt L = INSN(21,21);
7921 UInt rD = (INSN(22,22) << 4) | INSN(15,12);
7922 UInt rN = INSN(19,16);
7923 UInt rM = INSN(3,0);
7929 vassert(condT != IRTemp_INVALID);
7931 vassert(condT == IRTemp_INVALID);
7933 /* So now, if condT is not IRTemp_INVALID, we know we're
7934 dealing with Thumb code. */
7936 if (INSN(20,20) != 0)
7939 IRTemp initialRn = newTemp(Ity_I32);
7940 assign(initialRn, isT ? getIRegT(rN) : getIRegA(rN));
7942 IRTemp initialRm = newTemp(Ity_I32);
7943 assign(initialRm, isT ? getIRegT(rM) : getIRegA(rM));
7948 /* VSTn / VLDn (n-element structure from/to one lane) */
7953 case 0: i = INSN(7,5); inc = 1; break;
7954 case 1: i = INSN(7,6); inc = INSN(5,5) ? 2 : 1; break;
7955 case 2: i = INSN(7,7); inc = INSN(6,6) ? 2 : 1; break;
7956 case 3: return False;
7957 default: vassert(0);
7960 IRTemp addr = newTemp(Ity_I32);
7961 assign(addr, mkexpr(initialRn));
7964 if (condT != IRTemp_INVALID)
7965 mk_skip_over_T32_if_cond_is_false(condT);
7969 mk_neon_elem_load_to_one_lane(rD, inc, i, N, size, addr);
7971 mk_neon_elem_store_from_one_lane(rD, inc, i, N, size, addr);
7972 DIP("v%s%u.%u {", L ? "ld" : "st", N + 1, 8 << size);
7973 for (j = 0; j <= N; j++) {
7976 DIP("d%u[%u]", rD + j * inc, i);
7978 DIP("}, [r%u]", rN);
7979 if (rM != 13 && rM != 15) {
7982 DIP("%s\n", (rM != 15) ? "!" : "");
7985 /* VLDn (single element to all lanes) */
7990 inc = INSN(5,5) + 1;
7993 /* size == 3 and size == 2 cases differ in alignment constraints */
7994 if (size == 3 && N == 3 && INSN(4,4) == 1)
7997 if (size == 0 && N == 0 && INSN(4,4) == 1)
7999 if (N == 2 && INSN(4,4) == 1)
8005 if (condT != IRTemp_INVALID)
8006 mk_skip_over_T32_if_cond_is_false(condT);
8009 IRTemp addr = newTemp(Ity_I32);
8010 assign(addr, mkexpr(initialRn));
8012 if (N == 0 && INSN(5,5))
8015 for (r = 0; r < regs; r++) {
8018 putDRegI64(rD + r, unop(Iop_Dup8x8,
8019 loadLE(Ity_I8, mkexpr(addr))),
8023 putDRegI64(rD + r, unop(Iop_Dup16x4,
8024 loadLE(Ity_I16, mkexpr(addr))),
8028 putDRegI64(rD + r, unop(Iop_Dup32x2,
8029 loadLE(Ity_I32, mkexpr(addr))),
8035 for (i = 1; i <= N; i++) {
8038 putDRegI64(rD + r + i * inc,
8040 loadLE(Ity_I8, binop(Iop_Add32,
8046 putDRegI64(rD + r + i * inc,
8048 loadLE(Ity_I16, binop(Iop_Add32,
8054 putDRegI64(rD + r + i * inc,
8056 loadLE(Ity_I32, binop(Iop_Add32,
8066 DIP("vld%u.%u {", N + 1, 8 << size);
8067 for (r = 0; r < regs; r++) {
8068 for (i = 0; i <= N; i++) {
8071 DIP("d%u[]", rD + r + i * inc);
8074 DIP("}, [r%u]", rN);
8075 if (rM != 13 && rM != 15) {
8078 DIP("%s\n", (rM != 15) ? "!" : "");
8081 /* Writeback. We're uncond here, so no condT-ing. */
8084 IRExpr* e = binop(Iop_Add32,
8086 mkU32((1 << size) * (N + 1)));
8088 putIRegT(rN, e, IRTemp_INVALID);
8090 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8092 IRExpr* e = binop(Iop_Add32,
8096 putIRegT(rN, e, IRTemp_INVALID);
8098 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8105 /* VSTn / VLDn (multiple n-element structures) */
8106 if (B == BITS4(0,0,1,0) || B == BITS4(0,1,1,0)
8107 || B == BITS4(0,1,1,1) || B == BITS4(1,0,1,0)) {
8109 } else if (B == BITS4(0,0,1,1) || B == BITS4(1,0,0,0)
8110 || B == BITS4(1,0,0,1)) {
8112 } else if (B == BITS4(0,1,0,0) || B == BITS4(0,1,0,1)) {
8114 } else if (B == BITS4(0,0,0,0) || B == BITS4(0,0,0,1)) {
8120 if (N == 1 && B == BITS4(0,0,1,1)) {
8122 } else if (N == 0) {
8123 if (B == BITS4(1,0,1,0)) {
8125 } else if (B == BITS4(0,1,1,0)) {
8127 } else if (B == BITS4(0,0,1,0)) {
8133 if (N == 0 && size == 3)
8138 elems = 8 / (1 << size);
8141 if (condT != IRTemp_INVALID)
8142 mk_skip_over_T32_if_cond_is_false(condT);
8145 IRTemp addr = newTemp(Ity_I32);
8146 assign(addr, mkexpr(initialRn));
8148 for (r = 0; r < regs; r++) {
8149 for (i = 0; i < elems; i++) {
8151 mk_neon_elem_load_to_one_lane(rD + r, inc, i, N, size, addr);
8153 mk_neon_elem_store_from_one_lane(rD + r, inc, i, N, size, addr);
8154 tmp = newTemp(Ity_I32);
8155 assign(tmp, binop(Iop_Add32, mkexpr(addr),
8156 mkU32((1 << size) * (N + 1))));
8163 IRExpr* e = binop(Iop_Add32,
8165 mkU32(8 * (N + 1) * regs));
8167 putIRegT(rN, e, IRTemp_INVALID);
8169 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8171 IRExpr* e = binop(Iop_Add32,
8175 putIRegT(rN, e, IRTemp_INVALID);
8177 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8180 DIP("v%s%u.%u {", L ? "ld" : "st", N + 1, 8 << INSN(7,6));
8181 if ((inc == 1 && regs * (N + 1) > 1)
8182 || (inc == 2 && regs > 1 && N > 0)) {
8183 DIP("d%u-d%u", rD, rD + regs * (N + 1) - 1);
8185 for (r = 0; r < regs; r++) {
8186 for (i = 0; i <= N; i++) {
8189 DIP("d%u", rD + r + i * inc);
8193 DIP("}, [r%u]", rN);
8194 if (rM != 13 && rM != 15) {
8197 DIP("%s\n", (rM != 15) ? "!" : "");
8205 /*------------------------------------------------------------*/
8206 /*--- NEON, top level control ---*/
8207 /*------------------------------------------------------------*/
8209 /* Both ARM and Thumb */
8211 /* Translate a NEON instruction. If successful, returns
8212 True and *dres may or may not be updated. If failure, returns
8213 False and doesn't change *dres nor create any IR.
8215 The Thumb and ARM encodings are similar for the 24 bottom bits, but
8216 the top 8 bits are slightly different. In both cases, the caller
8217 must pass the entire 32 bits. Callers may pass any instruction;
8218 this ignores non-NEON ones.
8220 Caller must supply an IRTemp 'condT' holding the gating condition,
8221 or IRTemp_INVALID indicating the insn is always executed. In ARM
8222 code, this must always be IRTemp_INVALID because NEON insns are
8223 unconditional for ARM.
8225 Finally, the caller must indicate whether this occurs in ARM or in
8228 static Bool decode_NEON_instruction (
8229 /*MOD*/DisResult* dres,
8235 # define INSN(_bMax,_bMin) SLICE_UInt(insn32, (_bMax), (_bMin))
8237 /* There are two kinds of instruction to deal with: load/store and
8238 data processing. In each case, in ARM mode we merely identify
8239 the kind, and pass it on to the relevant sub-handler. In Thumb
8240 mode we identify the kind, swizzle the bits around to make it
8241 have the same encoding as in ARM, and hand it on to the
8245 /* In ARM mode, NEON instructions can't be conditional. */
8247 vassert(condT == IRTemp_INVALID);
8250 Thumb: 111U 1111 AAAA Axxx xxxx BBBB CCCC xxxx
8251 ARM: 1111 001U AAAA Axxx xxxx BBBB CCCC xxxx
8253 if (!isT && INSN(31,25) == BITS7(1,1,1,1,0,0,1)) {
8255 return dis_neon_data_processing(INSN(31,0), condT);
8257 if (isT && INSN(31,29) == BITS3(1,1,1)
8258 && INSN(27,24) == BITS4(1,1,1,1)) {
8260 UInt reformatted = INSN(23,0);
8261 reformatted |= (INSN(28,28) << 24); // U bit
8262 reformatted |= (BITS7(1,1,1,1,0,0,1) << 25);
8263 return dis_neon_data_processing(reformatted, condT);
8267 Thumb: 1111 1001 AxL0 xxxx xxxx BBBB xxxx xxxx
8268 ARM: 1111 0100 AxL0 xxxx xxxx BBBB xxxx xxxx
8270 if (!isT && INSN(31,24) == BITS8(1,1,1,1,0,1,0,0)) {
8272 return dis_neon_elem_or_struct_load(INSN(31,0), isT, condT);
8274 if (isT && INSN(31,24) == BITS8(1,1,1,1,1,0,0,1)) {
8275 UInt reformatted = INSN(23,0);
8276 reformatted |= (BITS8(1,1,1,1,0,1,0,0) << 24);
8277 return dis_neon_elem_or_struct_load(reformatted, isT, condT);
8280 /* Doesn't match. */
8287 /*------------------------------------------------------------*/
8288 /*--- V6 MEDIA instructions ---*/
8289 /*------------------------------------------------------------*/
8291 /* Both ARM and Thumb */
8293 /* Translate a V6 media instruction. If successful, returns
8294 True and *dres may or may not be updated. If failure, returns
8295 False and doesn't change *dres nor create any IR.
8297 The Thumb and ARM encodings are completely different. In Thumb
8298 mode, the caller must pass the entire 32 bits. In ARM mode it must
8299 pass the lower 28 bits. Apart from that, callers may pass any
8300 instruction; this function ignores anything it doesn't recognise.
8302 Caller must supply an IRTemp 'condT' holding the gating condition,
8303 or IRTemp_INVALID indicating the insn is always executed.
8305 Caller must also supply an ARMCondcode 'cond'. This is only used
8306 for debug printing, no other purpose. For ARM, this is simply the
8307 top 4 bits of the original instruction. For Thumb, the condition
8308 is not (really) known until run time, and so ARMCondAL should be
8309 passed, only so that printing of these instructions does not show
8312 Finally, the caller must indicate whether this occurs in ARM or in
8315 static Bool decode_V6MEDIA_instruction (
8316 /*MOD*/DisResult* dres,
8323 # define INSNA(_bMax,_bMin) SLICE_UInt(insnv6m, (_bMax), (_bMin))
8324 # define INSNT0(_bMax,_bMin) SLICE_UInt( ((insnv6m >> 16) & 0xFFFF), \
8326 # define INSNT1(_bMax,_bMin) SLICE_UInt( ((insnv6m >> 0) & 0xFFFF), \
8332 vassert(conq == ARMCondAL);
8334 vassert(INSNA(31,28) == BITS4(0,0,0,0)); // caller's obligation
8335 vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
8338 /* ----------- smulbb, smulbt, smultb, smultt ----------- */
8340 UInt regD = 99, regM = 99, regN = 99, bitM = 0, bitN = 0;
8344 if (INSNT0(15,4) == 0xFB1 && INSNT1(15,12) == BITS4(1,1,1,1)
8345 && INSNT1(7,6) == BITS2(0,0)) {
8346 regD = INSNT1(11,8);
8351 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8355 if (BITS8(0,0,0,1,0,1,1,0) == INSNA(27,20) &&
8356 BITS4(0,0,0,0) == INSNA(15,12) &&
8357 BITS4(1,0,0,0) == (INSNA(7,4) & BITS4(1,0,0,1)) ) {
8358 regD = INSNA(19,16);
8363 if (regD != 15 && regN != 15 && regM != 15)
8369 IRTemp srcN = newTemp(Ity_I32);
8370 IRTemp srcM = newTemp(Ity_I32);
8371 IRTemp res = newTemp(Ity_I32);
8373 assign( srcN, binop(Iop_Sar32,
8375 isT ? getIRegT(regN) : getIRegA(regN),
8376 mkU8(bitN ? 0 : 16)), mkU8(16)) );
8377 assign( srcM, binop(Iop_Sar32,
8379 isT ? getIRegT(regM) : getIRegA(regM),
8380 mkU8(bitM ? 0 : 16)), mkU8(16)) );
8381 assign( res, binop(Iop_Mul32, mkexpr(srcN), mkexpr(srcM)) );
8384 putIRegT( regD, mkexpr(res), condT );
8386 putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8388 DIP( "smul%c%c%s r%u, r%u, r%u\n", bitN ? 't' : 'b', bitM ? 't' : 'b',
8389 nCC(conq), regD, regN, regM );
8395 /* ------------ smulwb<y><c> <Rd>,<Rn>,<Rm> ------------- */
8396 /* ------------ smulwt<y><c> <Rd>,<Rn>,<Rm> ------------- */
8398 UInt regD = 99, regN = 99, regM = 99, bitM = 0;
8402 if (INSNT0(15,4) == 0xFB3 && INSNT1(15,12) == BITS4(1,1,1,1)
8403 && INSNT1(7,5) == BITS3(0,0,0)) {
8405 regD = INSNT1(11,8);
8408 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8412 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
8413 INSNA(15,12) == BITS4(0,0,0,0) &&
8414 (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,1,0)) {
8415 regD = INSNA(19,16);
8419 if (regD != 15 && regN != 15 && regM != 15)
8425 IRTemp irt_prod = newTemp(Ity_I64);
8429 isT ? getIRegT(regN) : getIRegA(regN),
8432 isT ? getIRegT(regM) : getIRegA(regM),
8433 mkU8(bitM ? 0 : 16)),
8436 IRExpr* ire_result = binop(Iop_Or32,
8438 unop(Iop_64HIto32, mkexpr(irt_prod)),
8441 unop(Iop_64to32, mkexpr(irt_prod)),
8445 putIRegT( regD, ire_result, condT );
8447 putIRegA( regD, ire_result, condT, Ijk_Boring );
8449 DIP("smulw%c%s r%u, r%u, r%u\n",
8450 bitM ? 't' : 'b', nCC(conq),regD,regN,regM);
8456 /* ------------ pkhbt<c> Rd, Rn, Rm {,LSL #imm} ------------- */
8457 /* ------------ pkhtb<c> Rd, Rn, Rm {,ASR #imm} ------------- */
8459 UInt regD = 99, regN = 99, regM = 99, imm5 = 99, shift_type = 99;
8460 Bool tbform = False;
8464 if (INSNT0(15,4) == 0xEAC
8465 && INSNT1(15,15) == 0 && INSNT1(4,4) == 0) {
8467 regD = INSNT1(11,8);
8469 imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6);
8470 shift_type = (INSNT1(5,5) << 1) | 0;
8471 tbform = (INSNT1(5,5) == 0) ? False : True;
8472 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8476 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
8477 INSNA(5,4) == BITS2(0,1) &&
8478 (INSNA(6,6) == 0 || INSNA(6,6) == 1) ) {
8479 regD = INSNA(15,12);
8480 regN = INSNA(19,16);
8483 shift_type = (INSNA(6,6) << 1) | 0;
8484 tbform = (INSNA(6,6) == 0) ? False : True;
8485 if (regD != 15 && regN != 15 && regM != 15)
8491 IRTemp irt_regM = newTemp(Ity_I32);
8492 IRTemp irt_regM_shift = newTemp(Ity_I32);
8493 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
8494 compute_result_and_C_after_shift_by_imm5(
8495 dis_buf, &irt_regM_shift, NULL, irt_regM, shift_type, imm5, regM );
8497 UInt mask = (tbform == True) ? 0x0000FFFF : 0xFFFF0000;
8500 binop(Iop_And32, mkexpr(irt_regM_shift), mkU32(mask)),
8501 binop(Iop_And32, isT ? getIRegT(regN) : getIRegA(regN),
8502 unop(Iop_Not32, mkU32(mask))) );
8505 putIRegT( regD, ire_result, condT );
8507 putIRegA( regD, ire_result, condT, Ijk_Boring );
8509 DIP( "pkh%s%s r%u, r%u, r%u %s\n", tbform ? "tb" : "bt",
8510 nCC(conq), regD, regN, regM, dis_buf );
8517 /* ---------- usat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
8519 UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
8523 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,1,0)
8525 && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
8526 regD = INSNT1(11,8);
8528 shift_type = (INSNT0(5,5) << 1) | 0;
8529 imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6);
8530 sat_imm = INSNT1(4,0);
8531 if (!isBadRegT(regD) && !isBadRegT(regN))
8533 if (shift_type == BITS2(1,0) && imm5 == 0)
8537 if (INSNA(27,21) == BITS7(0,1,1,0,1,1,1) &&
8538 INSNA(5,4) == BITS2(0,1)) {
8539 regD = INSNA(15,12);
8541 shift_type = (INSNA(6,6) << 1) | 0;
8543 sat_imm = INSNA(20,16);
8544 if (regD != 15 && regN != 15)
8550 IRTemp irt_regN = newTemp(Ity_I32);
8551 IRTemp irt_regN_shift = newTemp(Ity_I32);
8552 IRTemp irt_sat_Q = newTemp(Ity_I32);
8553 IRTemp irt_result = newTemp(Ity_I32);
8555 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8556 compute_result_and_C_after_shift_by_imm5(
8557 dis_buf, &irt_regN_shift, NULL,
8558 irt_regN, shift_type, imm5, regN );
8560 armUnsignedSatQ( &irt_result, &irt_sat_Q, irt_regN_shift, sat_imm );
8561 or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
8564 putIRegT( regD, mkexpr(irt_result), condT );
8566 putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
8568 DIP("usat%s r%u, #0x%04x, %s\n",
8569 nCC(conq), regD, imm5, dis_buf);
8575 /* ----------- ssat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
8577 UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
8581 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0)
8583 && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
8584 regD = INSNT1(11,8);
8586 shift_type = (INSNT0(5,5) << 1) | 0;
8587 imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6);
8588 sat_imm = INSNT1(4,0) + 1;
8589 if (!isBadRegT(regD) && !isBadRegT(regN))
8591 if (shift_type == BITS2(1,0) && imm5 == 0)
8595 if (INSNA(27,21) == BITS7(0,1,1,0,1,0,1) &&
8596 INSNA(5,4) == BITS2(0,1)) {
8597 regD = INSNA(15,12);
8599 shift_type = (INSNA(6,6) << 1) | 0;
8601 sat_imm = INSNA(20,16) + 1;
8602 if (regD != 15 && regN != 15)
8608 IRTemp irt_regN = newTemp(Ity_I32);
8609 IRTemp irt_regN_shift = newTemp(Ity_I32);
8610 IRTemp irt_sat_Q = newTemp(Ity_I32);
8611 IRTemp irt_result = newTemp(Ity_I32);
8613 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8614 compute_result_and_C_after_shift_by_imm5(
8615 dis_buf, &irt_regN_shift, NULL,
8616 irt_regN, shift_type, imm5, regN );
8618 armSignedSatQ( irt_regN_shift, sat_imm, &irt_result, &irt_sat_Q );
8619 or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
8622 putIRegT( regD, mkexpr(irt_result), condT );
8624 putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
8626 DIP( "ssat%s r%u, #0x%04x, %s\n",
8627 nCC(conq), regD, imm5, dis_buf);
8633 /* -------------- usat16<c> <Rd>,#<imm4>,<Rn> --------------- */
8635 UInt regD = 99, regN = 99, sat_imm = 99;
8639 if (INSNT0(15,4) == 0xF3A && (INSNT1(15,0) & 0xF0F0) == 0x0000) {
8641 regD = INSNT1(11,8);
8642 sat_imm = INSNT1(3,0);
8643 if (!isBadRegT(regD) && !isBadRegT(regN))
8647 if (INSNA(27,20) == BITS8(0,1,1,0,1,1,1,0) &&
8648 INSNA(11,8) == BITS4(1,1,1,1) &&
8649 INSNA(7,4) == BITS4(0,0,1,1)) {
8650 regD = INSNA(15,12);
8652 sat_imm = INSNA(19,16);
8653 if (regD != 15 && regN != 15)
8659 IRTemp irt_regN = newTemp(Ity_I32);
8660 IRTemp irt_regN_lo = newTemp(Ity_I32);
8661 IRTemp irt_regN_hi = newTemp(Ity_I32);
8662 IRTemp irt_Q_lo = newTemp(Ity_I32);
8663 IRTemp irt_Q_hi = newTemp(Ity_I32);
8664 IRTemp irt_res_lo = newTemp(Ity_I32);
8665 IRTemp irt_res_hi = newTemp(Ity_I32);
8667 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8668 assign( irt_regN_lo, binop( Iop_Sar32,
8669 binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
8671 assign( irt_regN_hi, binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)) );
8673 armUnsignedSatQ( &irt_res_lo, &irt_Q_lo, irt_regN_lo, sat_imm );
8674 or_into_QFLAG32( mkexpr(irt_Q_lo), condT );
8676 armUnsignedSatQ( &irt_res_hi, &irt_Q_hi, irt_regN_hi, sat_imm );
8677 or_into_QFLAG32( mkexpr(irt_Q_hi), condT );
8679 IRExpr* ire_result = binop( Iop_Or32,
8680 binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)),
8681 mkexpr(irt_res_lo) );
8684 putIRegT( regD, ire_result, condT );
8686 putIRegA( regD, ire_result, condT, Ijk_Boring );
8688 DIP( "usat16%s r%u, #0x%04x, r%u\n", nCC(conq), regD, sat_imm, regN );
8694 /* -------------- uadd16<c> <Rd>,<Rn>,<Rm> -------------- */
8696 UInt regD = 99, regN = 99, regM = 99;
8700 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8702 regD = INSNT1(11,8);
8704 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8708 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
8709 INSNA(11,8) == BITS4(1,1,1,1) &&
8710 INSNA(7,4) == BITS4(0,0,0,1)) {
8711 regD = INSNA(15,12);
8712 regN = INSNA(19,16);
8714 if (regD != 15 && regN != 15 && regM != 15)
8720 IRTemp rNt = newTemp(Ity_I32);
8721 IRTemp rMt = newTemp(Ity_I32);
8722 IRTemp res = newTemp(Ity_I32);
8723 IRTemp reso = newTemp(Ity_I32);
8725 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8726 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8728 assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
8730 putIRegT( regD, mkexpr(res), condT );
8732 putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8734 assign(reso, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
8735 set_GE_32_10_from_bits_31_15(reso, condT);
8737 DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8743 /* -------------- sadd16<c> <Rd>,<Rn>,<Rm> -------------- */
8745 UInt regD = 99, regN = 99, regM = 99;
8749 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8751 regD = INSNT1(11,8);
8753 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8757 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
8758 INSNA(11,8) == BITS4(1,1,1,1) &&
8759 INSNA(7,4) == BITS4(0,0,0,1)) {
8760 regD = INSNA(15,12);
8761 regN = INSNA(19,16);
8763 if (regD != 15 && regN != 15 && regM != 15)
8769 IRTemp rNt = newTemp(Ity_I32);
8770 IRTemp rMt = newTemp(Ity_I32);
8771 IRTemp res = newTemp(Ity_I32);
8772 IRTemp reso = newTemp(Ity_I32);
8774 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8775 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8777 assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
8779 putIRegT( regD, mkexpr(res), condT );
8781 putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8783 assign(reso, unop(Iop_Not32,
8784 binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt))));
8785 set_GE_32_10_from_bits_31_15(reso, condT);
8787 DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8793 /* ---------------- usub16<c> <Rd>,<Rn>,<Rm> ---------------- */
8795 UInt regD = 99, regN = 99, regM = 99;
8799 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8801 regD = INSNT1(11,8);
8803 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8807 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
8808 INSNA(11,8) == BITS4(1,1,1,1) &&
8809 INSNA(7,4) == BITS4(0,1,1,1)) {
8810 regD = INSNA(15,12);
8811 regN = INSNA(19,16);
8813 if (regD != 15 && regN != 15 && regM != 15)
8819 IRTemp rNt = newTemp(Ity_I32);
8820 IRTemp rMt = newTemp(Ity_I32);
8821 IRTemp res = newTemp(Ity_I32);
8822 IRTemp reso = newTemp(Ity_I32);
8824 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8825 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8827 assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
8829 putIRegT( regD, mkexpr(res), condT );
8831 putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8833 assign(reso, unop(Iop_Not32,
8834 binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt))));
8835 set_GE_32_10_from_bits_31_15(reso, condT);
8837 DIP("usub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8843 /* -------------- ssub16<c> <Rd>,<Rn>,<Rm> -------------- */
8845 UInt regD = 99, regN = 99, regM = 99;
8849 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8851 regD = INSNT1(11,8);
8853 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8857 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
8858 INSNA(11,8) == BITS4(1,1,1,1) &&
8859 INSNA(7,4) == BITS4(0,1,1,1)) {
8860 regD = INSNA(15,12);
8861 regN = INSNA(19,16);
8863 if (regD != 15 && regN != 15 && regM != 15)
8869 IRTemp rNt = newTemp(Ity_I32);
8870 IRTemp rMt = newTemp(Ity_I32);
8871 IRTemp res = newTemp(Ity_I32);
8872 IRTemp reso = newTemp(Ity_I32);
8874 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8875 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8877 assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
8879 putIRegT( regD, mkexpr(res), condT );
8881 putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8883 assign(reso, unop(Iop_Not32,
8884 binop(Iop_HSub16Sx2, mkexpr(rNt), mkexpr(rMt))));
8885 set_GE_32_10_from_bits_31_15(reso, condT);
8887 DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8893 /* ----------------- uadd8<c> <Rd>,<Rn>,<Rm> ---------------- */
8895 UInt regD = 99, regN = 99, regM = 99;
8899 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8901 regD = INSNT1(11,8);
8903 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8907 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
8908 INSNA(11,8) == BITS4(1,1,1,1) &&
8909 (INSNA(7,4) == BITS4(1,0,0,1))) {
8910 regD = INSNA(15,12);
8911 regN = INSNA(19,16);
8913 if (regD != 15 && regN != 15 && regM != 15)
8919 IRTemp rNt = newTemp(Ity_I32);
8920 IRTemp rMt = newTemp(Ity_I32);
8921 IRTemp res = newTemp(Ity_I32);
8922 IRTemp reso = newTemp(Ity_I32);
8924 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8925 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8927 assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
8929 putIRegT( regD, mkexpr(res), condT );
8931 putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8933 assign(reso, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
8934 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
8936 DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8942 /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
8944 UInt regD = 99, regN = 99, regM = 99;
8948 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8950 regD = INSNT1(11,8);
8952 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8956 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
8957 INSNA(11,8) == BITS4(1,1,1,1) &&
8958 (INSNA(7,4) == BITS4(1,0,0,1))) {
8959 regD = INSNA(15,12);
8960 regN = INSNA(19,16);
8962 if (regD != 15 && regN != 15 && regM != 15)
8968 IRTemp rNt = newTemp(Ity_I32);
8969 IRTemp rMt = newTemp(Ity_I32);
8970 IRTemp res = newTemp(Ity_I32);
8971 IRTemp reso = newTemp(Ity_I32);
8973 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8974 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8976 assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
8978 putIRegT( regD, mkexpr(res), condT );
8980 putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8982 assign(reso, unop(Iop_Not32,
8983 binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt))));
8984 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
8986 DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8992 /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */
8994 UInt regD = 99, regN = 99, regM = 99;
8998 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
9000 regD = INSNT1(11,8);
9002 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9006 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9007 INSNA(11,8) == BITS4(1,1,1,1) &&
9008 (INSNA(7,4) == BITS4(1,1,1,1))) {
9009 regD = INSNA(15,12);
9010 regN = INSNA(19,16);
9012 if (regD != 15 && regN != 15 && regM != 15)
9018 IRTemp rNt = newTemp(Ity_I32);
9019 IRTemp rMt = newTemp(Ity_I32);
9020 IRTemp res = newTemp(Ity_I32);
9021 IRTemp reso = newTemp(Ity_I32);
9023 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9024 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9026 assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
9028 putIRegT( regD, mkexpr(res), condT );
9030 putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
9032 assign(reso, unop(Iop_Not32,
9033 binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt))));
9034 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
9036 DIP("usub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9042 /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9044 UInt regD = 99, regN = 99, regM = 99;
9048 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9050 regD = INSNT1(11,8);
9052 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9056 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9057 INSNA(11,8) == BITS4(1,1,1,1) &&
9058 INSNA(7,4) == BITS4(1,1,1,1)) {
9059 regD = INSNA(15,12);
9060 regN = INSNA(19,16);
9062 if (regD != 15 && regN != 15 && regM != 15)
9068 IRTemp rNt = newTemp(Ity_I32);
9069 IRTemp rMt = newTemp(Ity_I32);
9070 IRTemp res = newTemp(Ity_I32);
9071 IRTemp reso = newTemp(Ity_I32);
9073 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9074 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9076 assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
9078 putIRegT( regD, mkexpr(res), condT );
9080 putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
9082 assign(reso, unop(Iop_Not32,
9083 binop(Iop_HSub8Sx4, mkexpr(rNt), mkexpr(rMt))));
9084 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
9086 DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9092 /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9094 UInt regD = 99, regN = 99, regM = 99;
9098 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9100 regD = INSNT1(11,8);
9102 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9106 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9107 INSNA(11,8) == BITS4(1,1,1,1) &&
9108 INSNA(7,4) == BITS4(1,0,0,1)) {
9109 regD = INSNA(15,12);
9110 regN = INSNA(19,16);
9112 if (regD != 15 && regN != 15 && regM != 15)
9118 IRTemp rNt = newTemp(Ity_I32);
9119 IRTemp rMt = newTemp(Ity_I32);
9120 IRTemp res_q = newTemp(Ity_I32);
9122 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9123 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9125 assign(res_q, binop(Iop_QAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
9127 putIRegT( regD, mkexpr(res_q), condT );
9129 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9131 DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9137 /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
9139 UInt regD = 99, regN = 99, regM = 99;
9143 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9145 regD = INSNT1(11,8);
9147 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9151 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9152 INSNA(11,8) == BITS4(1,1,1,1) &&
9153 INSNA(7,4) == BITS4(1,1,1,1)) {
9154 regD = INSNA(15,12);
9155 regN = INSNA(19,16);
9157 if (regD != 15 && regN != 15 && regM != 15)
9163 IRTemp rNt = newTemp(Ity_I32);
9164 IRTemp rMt = newTemp(Ity_I32);
9165 IRTemp res_q = newTemp(Ity_I32);
9167 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9168 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9170 assign(res_q, binop(Iop_QSub8Sx4, mkexpr(rNt), mkexpr(rMt)));
9172 putIRegT( regD, mkexpr(res_q), condT );
9174 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9176 DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9182 /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
9184 UInt regD = 99, regN = 99, regM = 99;
9188 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9190 regD = INSNT1(11,8);
9192 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9196 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9197 INSNA(11,8) == BITS4(1,1,1,1) &&
9198 (INSNA(7,4) == BITS4(1,0,0,1))) {
9199 regD = INSNA(15,12);
9200 regN = INSNA(19,16);
9202 if (regD != 15 && regN != 15 && regM != 15)
9208 IRTemp rNt = newTemp(Ity_I32);
9209 IRTemp rMt = newTemp(Ity_I32);
9210 IRTemp res_q = newTemp(Ity_I32);
9212 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9213 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9215 assign(res_q, binop(Iop_QAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
9217 putIRegT( regD, mkexpr(res_q), condT );
9219 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9221 DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9227 /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9229 UInt regD = 99, regN = 99, regM = 99;
9233 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9235 regD = INSNT1(11,8);
9237 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9241 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9242 INSNA(11,8) == BITS4(1,1,1,1) &&
9243 (INSNA(7,4) == BITS4(1,1,1,1))) {
9244 regD = INSNA(15,12);
9245 regN = INSNA(19,16);
9247 if (regD != 15 && regN != 15 && regM != 15)
9253 IRTemp rNt = newTemp(Ity_I32);
9254 IRTemp rMt = newTemp(Ity_I32);
9255 IRTemp res_q = newTemp(Ity_I32);
9257 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9258 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9260 assign(res_q, binop(Iop_QSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
9262 putIRegT( regD, mkexpr(res_q), condT );
9264 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9266 DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9272 /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9274 UInt regD = 99, regN = 99, regM = 99;
9278 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
9280 regD = INSNT1(11,8);
9282 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9286 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
9287 INSNA(11,8) == BITS4(1,1,1,1) &&
9288 INSNA(7,4) == BITS4(1,0,0,1)) {
9289 regD = INSNA(15,12);
9290 regN = INSNA(19,16);
9292 if (regD != 15 && regN != 15 && regM != 15)
9298 IRTemp rNt = newTemp(Ity_I32);
9299 IRTemp rMt = newTemp(Ity_I32);
9300 IRTemp res_q = newTemp(Ity_I32);
9302 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9303 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9305 assign(res_q, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
9307 putIRegT( regD, mkexpr(res_q), condT );
9309 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9311 DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9317 /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9319 UInt regD = 99, regN = 99, regM = 99;
9323 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
9325 regD = INSNT1(11,8);
9327 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9331 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
9332 INSNA(11,8) == BITS4(1,1,1,1) &&
9333 INSNA(7,4) == BITS4(1,0,0,1)) {
9334 regD = INSNA(15,12);
9335 regN = INSNA(19,16);
9337 if (regD != 15 && regN != 15 && regM != 15)
9343 IRTemp rNt = newTemp(Ity_I32);
9344 IRTemp rMt = newTemp(Ity_I32);
9345 IRTemp res_q = newTemp(Ity_I32);
9347 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9348 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9350 assign(res_q, binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
9352 putIRegT( regD, mkexpr(res_q), condT );
9354 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9356 DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9362 /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
9364 UInt regD = 99, regN = 99, regM = 99;
9368 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9370 regD = INSNT1(11,8);
9372 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9376 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9377 INSNA(11,8) == BITS4(1,1,1,1) &&
9378 INSNA(7,4) == BITS4(0,0,0,1)) {
9379 regD = INSNA(15,12);
9380 regN = INSNA(19,16);
9382 if (regD != 15 && regN != 15 && regM != 15)
9388 IRTemp rNt = newTemp(Ity_I32);
9389 IRTemp rMt = newTemp(Ity_I32);
9390 IRTemp res_q = newTemp(Ity_I32);
9392 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9393 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9395 assign(res_q, binop(Iop_QAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
9397 putIRegT( regD, mkexpr(res_q), condT );
9399 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9401 DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9407 /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
9409 UInt regD = 99, regN = 99, regM = 99;
9413 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9415 regD = INSNT1(11,8);
9417 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9421 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9422 INSNA(11,8) == BITS4(1,1,1,1) &&
9423 INSNA(7,4) == BITS4(0,1,1,1)) {
9424 regD = INSNA(15,12);
9425 regN = INSNA(19,16);
9427 if (regD != 15 && regN != 15 && regM != 15)
9433 IRTemp rNt = newTemp(Ity_I32);
9434 IRTemp rMt = newTemp(Ity_I32);
9435 IRTemp res_q = newTemp(Ity_I32);
9437 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9438 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9440 assign(res_q, binop(Iop_QSub16Sx2, mkexpr(rNt), mkexpr(rMt)));
9442 putIRegT( regD, mkexpr(res_q), condT );
9444 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9446 DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9452 /////////////////////////////////////////////////////////////////
9453 /////////////////////////////////////////////////////////////////
9454 /////////////////////////////////////////////////////////////////
9455 /////////////////////////////////////////////////////////////////
9456 /////////////////////////////////////////////////////////////////
9458 /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
9459 /* note: the hardware seems to construct the result differently
9460 from wot the manual says. */
9462 UInt regD = 99, regN = 99, regM = 99;
9466 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9468 regD = INSNT1(11,8);
9470 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9474 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9475 INSNA(11,8) == BITS4(1,1,1,1) &&
9476 INSNA(7,4) == BITS4(0,1,0,1)) {
9477 regD = INSNA(15,12);
9478 regN = INSNA(19,16);
9480 if (regD != 15 && regN != 15 && regM != 15)
9486 IRTemp irt_regN = newTemp(Ity_I32);
9487 IRTemp irt_regM = newTemp(Ity_I32);
9488 IRTemp irt_sum = newTemp(Ity_I32);
9489 IRTemp irt_diff = newTemp(Ity_I32);
9490 IRTemp irt_sum_res = newTemp(Ity_I32);
9491 IRTemp irt_diff_res = newTemp(Ity_I32);
9493 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9494 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9498 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9500 binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
9502 armSignedSatQ( irt_diff, 0x10, &irt_diff_res, NULL);
9507 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9509 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) )) );
9510 armSignedSatQ( irt_sum, 0x10, &irt_sum_res, NULL );
9512 IRExpr* ire_result = binop( Iop_Or32,
9513 binop( Iop_Shl32, mkexpr(irt_diff_res),
9515 binop( Iop_And32, mkexpr(irt_sum_res),
9519 putIRegT( regD, ire_result, condT );
9521 putIRegA( regD, ire_result, condT, Ijk_Boring );
9523 DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9529 /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */
9531 UInt regD = 99, regN = 99, regM = 99;
9535 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9537 regD = INSNT1(11,8);
9539 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9543 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9544 INSNA(11,8) == BITS4(1,1,1,1) &&
9545 INSNA(7,4) == BITS4(0,0,1,1)) {
9546 regD = INSNA(15,12);
9547 regN = INSNA(19,16);
9549 if (regD != 15 && regN != 15 && regM != 15)
9555 IRTemp irt_regN = newTemp(Ity_I32);
9556 IRTemp irt_regM = newTemp(Ity_I32);
9557 IRTemp irt_sum = newTemp(Ity_I32);
9558 IRTemp irt_diff = newTemp(Ity_I32);
9559 IRTemp irt_res_sum = newTemp(Ity_I32);
9560 IRTemp irt_res_diff = newTemp(Ity_I32);
9562 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9563 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9568 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9570 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9571 armSignedSatQ( irt_diff, 0x10, &irt_res_diff, NULL );
9575 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9577 binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
9579 armSignedSatQ( irt_sum, 0x10, &irt_res_sum, NULL );
9583 binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ),
9584 binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) );
9587 putIRegT( regD, ire_result, condT );
9589 putIRegA( regD, ire_result, condT, Ijk_Boring );
9591 DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9597 /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */
9599 UInt regD = 99, regN = 99, regM = 99;
9603 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9605 regD = INSNT1(11,8);
9607 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9611 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9612 INSNA(11,8) == BITS4(1,1,1,1) &&
9613 INSNA(7,4) == BITS4(0,0,1,1)) {
9614 regD = INSNA(15,12);
9615 regN = INSNA(19,16);
9617 if (regD != 15 && regN != 15 && regM != 15)
9623 IRTemp irt_regN = newTemp(Ity_I32);
9624 IRTemp irt_regM = newTemp(Ity_I32);
9625 IRTemp irt_sum = newTemp(Ity_I32);
9626 IRTemp irt_diff = newTemp(Ity_I32);
9628 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9629 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9634 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9636 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9640 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9642 binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
9647 binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ),
9648 binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) );
9650 IRTemp ge10 = newTemp(Ity_I32);
9651 assign(ge10, unop(Iop_Not32, mkexpr(irt_diff)));
9652 put_GEFLAG32( 0, 31, mkexpr(ge10), condT );
9653 put_GEFLAG32( 1, 31, mkexpr(ge10), condT );
9655 IRTemp ge32 = newTemp(Ity_I32);
9656 assign(ge32, unop(Iop_Not32, mkexpr(irt_sum)));
9657 put_GEFLAG32( 2, 31, mkexpr(ge32), condT );
9658 put_GEFLAG32( 3, 31, mkexpr(ge32), condT );
9661 putIRegT( regD, ire_result, condT );
9663 putIRegA( regD, ire_result, condT, Ijk_Boring );
9665 DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9671 /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */
9672 /* --------------- smsad, smsadx<c><Rd>,<Rn>,<Rm> --------------- */
9674 UInt regD = 99, regN = 99, regM = 99, bitM = 99;
9675 Bool gate = False, isAD = False;
9678 if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
9679 && (INSNT1(15,0) & 0xF0E0) == 0xF000) {
9681 regD = INSNT1(11,8);
9684 isAD = INSNT0(15,4) == 0xFB2;
9685 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9689 if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
9690 INSNA(15,12) == BITS4(1,1,1,1) &&
9691 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1) ) {
9692 regD = INSNA(19,16);
9696 isAD = INSNA(6,6) == 0;
9697 if (regD != 15 && regN != 15 && regM != 15)
9703 IRTemp irt_regN = newTemp(Ity_I32);
9704 IRTemp irt_regM = newTemp(Ity_I32);
9705 IRTemp irt_prod_lo = newTemp(Ity_I32);
9706 IRTemp irt_prod_hi = newTemp(Ity_I32);
9707 IRTemp tmpM = newTemp(Ity_I32);
9709 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9711 assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
9712 assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
9714 assign( irt_prod_lo,
9717 binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
9720 binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
9722 assign( irt_prod_hi, binop(Iop_Mul32,
9723 binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)),
9724 binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
9726 = binop( isAD ? Iop_Add32 : Iop_Sub32,
9727 mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) );
9730 putIRegT( regD, ire_result, condT );
9732 putIRegA( regD, ire_result, condT, Ijk_Boring );
9736 signed_overflow_after_Add32( ire_result,
9737 irt_prod_lo, irt_prod_hi ),
9742 DIP("smu%cd%s%s r%u, r%u, r%u\n",
9744 bitM ? "x" : "", nCC(conq), regD, regN, regM);
9750 /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
9751 /* --------------- smlsd{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
9753 UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
9754 Bool gate = False, isAD = False;
9757 if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
9758 && INSNT1(7,5) == BITS3(0,0,0)) {
9760 regD = INSNT1(11,8);
9762 regA = INSNT1(15,12);
9764 isAD = INSNT0(15,4) == 0xFB2;
9765 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
9766 && !isBadRegT(regA))
9770 if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
9771 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
9772 regD = INSNA(19,16);
9773 regA = INSNA(15,12);
9777 isAD = INSNA(6,6) == 0;
9778 if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
9784 IRTemp irt_regN = newTemp(Ity_I32);
9785 IRTemp irt_regM = newTemp(Ity_I32);
9786 IRTemp irt_regA = newTemp(Ity_I32);
9787 IRTemp irt_prod_lo = newTemp(Ity_I32);
9788 IRTemp irt_prod_hi = newTemp(Ity_I32);
9789 IRTemp irt_sum = newTemp(Ity_I32);
9790 IRTemp tmpM = newTemp(Ity_I32);
9792 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9793 assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
9795 assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
9796 assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
9798 assign( irt_prod_lo,
9801 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9804 binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
9806 assign( irt_prod_hi,
9808 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9809 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9810 assign( irt_sum, binop( isAD ? Iop_Add32 : Iop_Sub32,
9811 mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ) );
9813 IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_sum), mkexpr(irt_regA));
9816 putIRegT( regD, ire_result, condT );
9818 putIRegA( regD, ire_result, condT, Ijk_Boring );
9822 signed_overflow_after_Add32( mkexpr(irt_sum),
9823 irt_prod_lo, irt_prod_hi ),
9829 signed_overflow_after_Add32( ire_result, irt_sum, irt_regA ),
9833 DIP("sml%cd%s%s r%u, r%u, r%u, r%u\n",
9835 bitM ? "x" : "", nCC(conq), regD, regN, regM, regA);
9841 /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */
9843 UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99, bitN = 99;
9847 if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) {
9849 regD = INSNT1(11,8);
9851 regA = INSNT1(15,12);
9854 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
9855 && !isBadRegT(regA))
9859 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
9860 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
9861 regD = INSNA(19,16);
9864 regA = INSNA(15,12);
9867 if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
9873 IRTemp irt_regA = newTemp(Ity_I32);
9874 IRTemp irt_prod = newTemp(Ity_I32);
9880 isT ? getIRegT(regN) : getIRegA(regN),
9881 mkU8(bitN ? 0 : 16)),
9885 isT ? getIRegT(regM) : getIRegA(regM),
9886 mkU8(bitM ? 0 : 16)),
9889 assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
9891 IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_prod), mkexpr(irt_regA));
9894 putIRegT( regD, ire_result, condT );
9896 putIRegA( regD, ire_result, condT, Ijk_Boring );
9899 signed_overflow_after_Add32( ire_result, irt_prod, irt_regA ),
9903 DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n",
9904 bitN ? 't' : 'b', bitM ? 't' : 'b',
9905 nCC(conq), regD, regN, regM, regA );
9911 /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */
9913 UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
9917 if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) {
9919 regD = INSNT1(11,8);
9921 regA = INSNT1(15,12);
9923 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
9924 && !isBadRegT(regA))
9928 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
9929 (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) {
9930 regD = INSNA(19,16);
9933 regA = INSNA(15,12);
9935 if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
9941 IRTemp irt_regA = newTemp(Ity_I32);
9942 IRTemp irt_prod = newTemp(Ity_I64);
9946 isT ? getIRegT(regN) : getIRegA(regN),
9949 isT ? getIRegT(regM) : getIRegA(regM),
9950 mkU8(bitM ? 0 : 16)),
9953 assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
9955 IRTemp prod32 = newTemp(Ity_I32);
9958 binop(Iop_Shl32, unop(Iop_64HIto32, mkexpr(irt_prod)), mkU8(16)),
9959 binop(Iop_Shr32, unop(Iop_64to32, mkexpr(irt_prod)), mkU8(16))
9962 IRExpr* ire_result = binop(Iop_Add32, mkexpr(prod32), mkexpr(irt_regA));
9965 putIRegT( regD, ire_result, condT );
9967 putIRegA( regD, ire_result, condT, Ijk_Boring );
9970 signed_overflow_after_Add32( ire_result, prod32, irt_regA ),
9974 DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n",
9976 nCC(conq), regD, regN, regM, regA );
9982 /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */
9983 /* fixme: fix up the test in v6media.c so that we can pass the ge
9984 flags as part of the test. */
9986 UInt regD = 99, regN = 99, regM = 99;
9990 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
9992 regD = INSNT1(11,8);
9994 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9998 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
9999 INSNA(11,8) == BITS4(1,1,1,1) &&
10000 INSNA(7,4) == BITS4(1,0,1,1)) {
10001 regD = INSNA(15,12);
10002 regN = INSNA(19,16);
10004 if (regD != 15 && regN != 15 && regM != 15)
10010 IRTemp irt_ge_flag0 = newTemp(Ity_I32);
10011 IRTemp irt_ge_flag1 = newTemp(Ity_I32);
10012 IRTemp irt_ge_flag2 = newTemp(Ity_I32);
10013 IRTemp irt_ge_flag3 = newTemp(Ity_I32);
10015 assign( irt_ge_flag0, get_GEFLAG32(0) );
10016 assign( irt_ge_flag1, get_GEFLAG32(1) );
10017 assign( irt_ge_flag2, get_GEFLAG32(2) );
10018 assign( irt_ge_flag3, get_GEFLAG32(3) );
10020 IRExpr* ire_ge_flag0_or
10021 = binop(Iop_Or32, mkexpr(irt_ge_flag0),
10022 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag0)));
10023 IRExpr* ire_ge_flag1_or
10024 = binop(Iop_Or32, mkexpr(irt_ge_flag1),
10025 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag1)));
10026 IRExpr* ire_ge_flag2_or
10027 = binop(Iop_Or32, mkexpr(irt_ge_flag2),
10028 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag2)));
10029 IRExpr* ire_ge_flag3_or
10030 = binop(Iop_Or32, mkexpr(irt_ge_flag3),
10031 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag3)));
10033 IRExpr* ire_ge_flags
10037 binop(Iop_Sar32, ire_ge_flag0_or, mkU8(31)),
10038 mkU32(0x000000ff)),
10040 binop(Iop_Sar32, ire_ge_flag1_or, mkU8(31)),
10041 mkU32(0x0000ff00))),
10044 binop(Iop_Sar32, ire_ge_flag2_or, mkU8(31)),
10045 mkU32(0x00ff0000)),
10047 binop(Iop_Sar32, ire_ge_flag3_or, mkU8(31)),
10048 mkU32(0xff000000))) );
10053 isT ? getIRegT(regN) : getIRegA(regN),
10056 isT ? getIRegT(regM) : getIRegA(regM),
10057 unop(Iop_Not32, ire_ge_flags)));
10060 putIRegT( regD, ire_result, condT );
10062 putIRegA( regD, ire_result, condT, Ijk_Boring );
10064 DIP("sel%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
10070 /* ----------------- uxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
10072 UInt regD = 99, regN = 99, regM = 99, rotate = 99;
10076 if (INSNT0(15,4) == 0xFA3 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
10077 regN = INSNT0(3,0);
10078 regD = INSNT1(11,8);
10079 regM = INSNT1(3,0);
10080 rotate = INSNT1(5,4);
10081 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10085 if (INSNA(27,20) == BITS8(0,1,1,0,1,1,0,0) &&
10086 INSNA(9,4) == BITS6(0,0,0,1,1,1) ) {
10087 regD = INSNA(15,12);
10088 regN = INSNA(19,16);
10090 rotate = INSNA(11,10);
10091 if (regD != 15 && regN != 15 && regM != 15)
10097 IRTemp irt_regN = newTemp(Ity_I32);
10098 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
10100 IRTemp irt_regM = newTemp(Ity_I32);
10101 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
10103 IRTemp irt_rot = newTemp(Ity_I32);
10104 assign( irt_rot, binop(Iop_And32,
10105 genROR32(irt_regM, 8 * rotate),
10106 mkU32(0x00FF00FF)) );
10110 binop(Iop_Add32, mkexpr(irt_regN), mkexpr(irt_rot)),
10111 mkU32(0x0000FFFF));
10115 binop(Iop_And32, mkexpr(irt_regN), mkU32(0xFFFF0000)),
10116 binop(Iop_And32, mkexpr(irt_rot), mkU32(0xFFFF0000)));
10119 = binop( Iop_Or32, resHi, resLo );
10122 putIRegT( regD, ire_result, condT );
10124 putIRegA( regD, ire_result, condT, Ijk_Boring );
10126 DIP( "uxtab16%s r%u, r%u, r%u, ROR #%u\n",
10127 nCC(conq), regD, regN, regM, 8 * rotate );
10133 /* --------------- usad8 Rd,Rn,Rm ---------------- */
10134 /* --------------- usada8 Rd,Rn,Rm,Ra ---------------- */
10136 UInt rD = 99, rN = 99, rM = 99, rA = 99;
10140 if (INSNT0(15,4) == 0xFB7 && INSNT1(7,4) == BITS4(0,0,0,0)) {
10142 rA = INSNT1(15,12);
10145 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && rA != 13)
10149 if (INSNA(27,20) == BITS8(0,1,1,1,1,0,0,0) &&
10150 INSNA(7,4) == BITS4(0,0,0,1) ) {
10155 if (rD != 15 && rN != 15 && rM != 15 /* but rA can be 15 */)
10159 /* We allow rA == 15, to denote the usad8 (no accumulator) case. */
10162 IRExpr* rNe = isT ? getIRegT(rN) : getIRegA(rN);
10163 IRExpr* rMe = isT ? getIRegT(rM) : getIRegA(rM);
10164 IRExpr* rAe = rA == 15 ? mkU32(0)
10165 : (isT ? getIRegT(rA) : getIRegA(rA));
10166 IRExpr* res = binop(Iop_Add32,
10167 binop(Iop_Sad8Ux4, rNe, rMe),
10170 putIRegT( rD, res, condT );
10172 putIRegA( rD, res, condT, Ijk_Boring );
10175 DIP( "usad8%s r%u, r%u, r%u\n",
10176 nCC(conq), rD, rN, rM );
10178 DIP( "usada8%s r%u, r%u, r%u, r%u\n",
10179 nCC(conq), rD, rN, rM, rA );
10186 /* ---------- Doesn't match anything. ---------- */
10195 /*------------------------------------------------------------*/
10196 /*--- LDMxx/STMxx helper (both ARM and Thumb32) ---*/
10197 /*------------------------------------------------------------*/
10199 /* Generate IR for LDMxx and STMxx. This is complex. Assumes it's
10200 unconditional, so the caller must produce a jump-around before
10201 calling this, if the insn is to be conditional. Caller is
10202 responsible for all validation of parameters. For LDMxx, if PC is
10203 amongst the values loaded, caller is also responsible for
10204 generating the jump. */
10205 static void mk_ldm_stm ( Bool arm, /* True: ARM, False: Thumb */
10206 UInt rN, /* base reg */
10207 UInt bINC, /* 1: inc, 0: dec */
10208 UInt bBEFORE, /* 1: inc/dec before, 0: after */
10209 UInt bW, /* 1: writeback to Rn */
10210 UInt bL, /* 1: load, 0: store */
10213 Int i, r, m, nRegs;
10215 /* Get hold of the old Rn value. We might need to write its value
10216 to memory during a store, and if it's also the writeback
10217 register then we need to get its value now. We can't treat it
10218 exactly like the other registers we're going to transfer,
10219 because for xxMDA and xxMDB writeback forms, the generated IR
10220 updates Rn in the guest state before any transfers take place.
10221 We have to do this as per comments below, in order that if Rn is
10222 the stack pointer then it always has a value is below or equal
10223 to any of the transfer addresses. Ick. */
10224 IRTemp oldRnT = newTemp(Ity_I32);
10225 assign(oldRnT, arm ? getIRegA(rN) : getIRegT(rN));
10227 IRTemp anchorT = newTemp(Ity_I32);
10228 /* The old (Addison-Wesley) ARM ARM seems to say that LDMxx/STMxx
10229 ignore the bottom two bits of the address. However, Cortex-A8
10230 doesn't seem to care. Hence: */
10231 /* No .. don't force alignment .. */
10232 /* assign(anchorT, binop(Iop_And32, mkexpr(oldRnT), mkU32(~3U))); */
10233 /* Instead, use the potentially misaligned address directly. */
10234 assign(anchorT, mkexpr(oldRnT));
10236 IROp opADDorSUB = bINC ? Iop_Add32 : Iop_Sub32;
10237 // bINC == 1: xxMIA, xxMIB
10238 // bINC == 0: xxMDA, xxMDB
10240 // For xxMDA and xxMDB, update Rn first if necessary. We have
10241 // to do this first so that, for the common idiom of the transfers
10242 // faulting because we're pushing stuff onto a stack and the stack
10243 // is growing down onto allocate-on-fault pages (as Valgrind simulates),
10244 // we need to have the SP up-to-date "covering" (pointing below) the
10245 // transfer area. For the same reason, if we are doing xxMIA or xxMIB,
10246 // do the transfer first, and then update rN afterwards.
10248 for (i = 0; i < 16; i++) {
10249 if ((regList & (1 << i)) != 0)
10252 if (bW == 1 && !bINC) {
10253 IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
10255 putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
10257 putIRegT( rN, e, IRTemp_INVALID );
10260 // Make up a list of the registers to transfer, and their offsets
10261 // in memory relative to the anchor. If the base reg (Rn) is part
10262 // of the transfer, then do it last for a load and first for a store.
10263 UInt xReg[16], xOff[16];
10266 for (i = 0; i < 16; i++) {
10267 r = bINC ? i : (15-i);
10268 if (0 == (regList & (1<<r)))
10272 /* paranoia: check we aren't transferring the writeback
10273 register during a load. Should be assured by decode-point
10275 if (bW == 1 && bL == 1)
10285 vassert(m == nRegs);
10286 vassert(nX == nRegs);
10289 if (bW == 0 && (regList & (1<<rN)) != 0) {
10290 /* Non-writeback, and basereg is to be transferred. Do its
10291 transfer last for a load and first for a store. Requires
10292 reordering xOff/xReg. */
10294 vex_printf("\nREG_LIST_PRE: (rN=%d)\n", rN);
10295 for (i = 0; i < nX; i++)
10296 vex_printf("reg %d off %d\n", xReg[i], xOff[i]);
10301 for (i = 0; i < nX; i++) {
10305 vassert(i < nX); /* else we didn't find it! */
10306 UInt tReg = xReg[i];
10307 UInt tOff = xOff[i];
10309 /* load; make this transfer happen last */
10311 for (m = i+1; m < nX; m++) {
10312 xReg[m-1] = xReg[m];
10313 xOff[m-1] = xOff[m];
10320 /* store; make this transfer happen first */
10322 for (m = i-1; m >= 0; m--) {
10323 xReg[m+1] = xReg[m];
10324 xOff[m+1] = xOff[m];
10333 vex_printf("REG_LIST_POST:\n");
10334 for (i = 0; i < nX; i++)
10335 vex_printf("reg %d off %d\n", xReg[i], xOff[i]);
10340 /* Actually generate the transfers */
10341 for (i = 0; i < nX; i++) {
10344 IRExpr* e = loadLE(Ity_I32,
10345 binop(opADDorSUB, mkexpr(anchorT),
10348 putIRegA( r, e, IRTemp_INVALID, Ijk_Ret );
10350 // no: putIRegT( r, e, IRTemp_INVALID );
10351 // putIRegT refuses to write to R15. But that might happen.
10352 // Since this is uncond, and we need to be able to
10353 // write the PC, just use the low level put:
10357 /* if we're storing Rn, make sure we use the correct
10358 value, as per extensive comments above */
10359 storeLE( binop(opADDorSUB, mkexpr(anchorT), mkU32(xOff[i])),
10360 r == rN ? mkexpr(oldRnT)
10361 : (arm ? getIRegA(r) : getIRegT(r) ) );
10365 // If we are doing xxMIA or xxMIB,
10366 // do the transfer first, and then update rN afterwards.
10367 if (bW == 1 && bINC) {
10368 IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
10370 putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
10372 putIRegT( rN, e, IRTemp_INVALID );
10377 /*------------------------------------------------------------*/
10378 /*--- VFP (CP 10 and 11) instructions ---*/
10379 /*------------------------------------------------------------*/
10381 /* Both ARM and Thumb */
10383 /* Translate a CP10 or CP11 instruction. If successful, returns
10384 True and *dres may or may not be updated. If failure, returns
10385 False and doesn't change *dres nor create any IR.
10387 The ARM and Thumb encodings are identical for the low 28 bits of
10388 the insn (yay!) and that's what the caller must supply, iow, imm28
10389 has the top 4 bits masked out. Caller is responsible for
10390 determining whether the masked-out bits are valid for a CP10/11
10391 insn. The rules for the top 4 bits are:
10393 ARM: 0000 to 1110 allowed, and this is the gating condition.
10394 1111 (NV) is not allowed.
10396 Thumb: must be 1110. The gating condition is taken from
10397 ITSTATE in the normal way.
10399 Conditionalisation:
10401 Caller must supply an IRTemp 'condT' holding the gating condition,
10402 or IRTemp_INVALID indicating the insn is always executed.
10404 Caller must also supply an ARMCondcode 'cond'. This is only used
10405 for debug printing, no other purpose. For ARM, this is simply the
10406 top 4 bits of the original instruction. For Thumb, the condition
10407 is not (really) known until run time, and so ARMCondAL should be
10408 passed, only so that printing of these instructions does not show
10411 Finally, the caller must indicate whether this occurs in ARM or
10414 static Bool decode_CP10_CP11_instruction (
10415 /*MOD*/DisResult* dres,
10422 # define INSN(_bMax,_bMin) SLICE_UInt(insn28, (_bMax), (_bMin))
10424 vassert(INSN(31,28) == BITS4(0,0,0,0)); // caller's obligation
10427 vassert(conq == ARMCondAL);
10429 vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
10432 /* ----------------------------------------------------------- */
10433 /* -- VFP instructions -- double precision (mostly) -- */
10434 /* ----------------------------------------------------------- */
10436 /* --------------------- fldmx, fstmx --------------------- */
10438 31 27 23 19 15 11 7 0
10440 C4-100, C5-26 1 FSTMX cond 1100 1000 Rn Dd 1011 offset
10441 C4-100, C5-28 2 FSTMIAX cond 1100 1010 Rn Dd 1011 offset
10442 C4-100, C5-30 3 FSTMDBX cond 1101 0010 Rn Dd 1011 offset
10444 C4-42, C5-26 1 FLDMX cond 1100 1001 Rn Dd 1011 offset
10445 C4-42, C5-28 2 FLDMIAX cond 1100 1011 Rn Dd 1011 offset
10446 C4-42, C5-30 3 FLDMDBX cond 1101 0011 Rn Dd 1011 offset
10448 Regs transferred: Dd .. D(d + (offset-3)/2)
10449 offset must be odd, must not imply a reg > 15
10450 IA/DB: Rn is changed by (4 + 8 x # regs transferred)
10453 1 at-Rn (access at Rn)
10454 2 ia-Rn (access at Rn, then Rn += 4+8n)
10455 3 db-Rn (Rn -= 4+8n, then access at Rn)
10457 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
10458 && INSN(11,8) == BITS4(1,0,1,1)) {
10459 UInt bP = (insn28 >> 24) & 1;
10460 UInt bU = (insn28 >> 23) & 1;
10461 UInt bW = (insn28 >> 21) & 1;
10462 UInt bL = (insn28 >> 20) & 1;
10463 UInt offset = (insn28 >> 0) & 0xFF;
10464 UInt rN = INSN(19,16);
10465 UInt dD = (INSN(22,22) << 4) | INSN(15,12);
10466 UInt nRegs = (offset - 1) / 2;
10470 /**/ if (bP == 0 && bU == 1 && bW == 0) {
10473 else if (bP == 0 && bU == 1 && bW == 1) {
10476 else if (bP == 1 && bU == 0 && bW == 1) {
10479 else goto after_vfp_fldmx_fstmx;
10481 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */
10482 if (rN == 15 && (summary == 2 || summary == 3 || isT))
10483 goto after_vfp_fldmx_fstmx;
10485 /* offset must be odd, and specify at least one register */
10486 if (0 == (offset & 1) || offset < 3)
10487 goto after_vfp_fldmx_fstmx;
10489 /* can't transfer regs after D15 */
10490 if (dD + nRegs - 1 >= 32)
10491 goto after_vfp_fldmx_fstmx;
10493 /* Now, we can't do a conditional load or store, since that very
10494 likely will generate an exception. So we have to take a side
10495 exit at this point if the condition is false. */
10496 if (condT != IRTemp_INVALID) {
10498 mk_skip_over_T32_if_cond_is_false( condT );
10500 mk_skip_over_A32_if_cond_is_false( condT );
10501 condT = IRTemp_INVALID;
10503 /* Ok, now we're unconditional. Do the load or store. */
10505 /* get the old Rn value */
10506 IRTemp rnT = newTemp(Ity_I32);
10507 assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
10510 /* make a new value for Rn, post-insn */
10511 IRTemp rnTnew = IRTemp_INVALID;
10512 if (summary == 2 || summary == 3) {
10513 rnTnew = newTemp(Ity_I32);
10514 assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
10516 mkU32(4 + 8 * nRegs)));
10519 /* decide on the base transfer address */
10520 IRTemp taT = newTemp(Ity_I32);
10521 assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
10523 /* update Rn if necessary -- in case 3, we're moving it down, so
10524 update before any memory reference, in order to keep Memcheck
10525 and V's stack-extending logic (on linux) happy */
10526 if (summary == 3) {
10528 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
10530 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
10533 /* generate the transfers */
10534 for (i = 0; i < nRegs; i++) {
10535 IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
10537 putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
10539 storeLE(addr, getDReg(dD + i));
10543 /* update Rn if necessary -- in case 2, we're moving it up, so
10544 update after any memory reference, in order to keep Memcheck
10545 and V's stack-extending logic (on linux) happy */
10546 if (summary == 2) {
10548 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
10550 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
10553 HChar* nm = bL==1 ? "ld" : "st";
10555 case 1: DIP("f%smx%s r%u, {d%u-d%u}\n",
10556 nm, nCC(conq), rN, dD, dD + nRegs - 1);
10558 case 2: DIP("f%smiax%s r%u!, {d%u-d%u}\n",
10559 nm, nCC(conq), rN, dD, dD + nRegs - 1);
10561 case 3: DIP("f%smdbx%s r%u!, {d%u-d%u}\n",
10562 nm, nCC(conq), rN, dD, dD + nRegs - 1);
10564 default: vassert(0);
10567 goto decode_success_vfp;
10568 /* FIXME alignment constraints? */
10571 after_vfp_fldmx_fstmx:
10573 /* --------------------- fldmd, fstmd --------------------- */
10575 31 27 23 19 15 11 7 0
10577 C4-96, C5-26 1 FSTMD cond 1100 1000 Rn Dd 1011 offset
10578 C4-96, C5-28 2 FSTMDIA cond 1100 1010 Rn Dd 1011 offset
10579 C4-96, C5-30 3 FSTMDDB cond 1101 0010 Rn Dd 1011 offset
10581 C4-38, C5-26 1 FLDMD cond 1100 1001 Rn Dd 1011 offset
10582 C4-38, C5-28 2 FLDMIAD cond 1100 1011 Rn Dd 1011 offset
10583 C4-38, C5-30 3 FLDMDBD cond 1101 0011 Rn Dd 1011 offset
10585 Regs transferred: Dd .. D(d + (offset-2)/2)
10586 offset must be even, must not imply a reg > 15
10587 IA/DB: Rn is changed by (8 x # regs transferred)
10590 1 at-Rn (access at Rn)
10591 2 ia-Rn (access at Rn, then Rn += 8n)
10592 3 db-Rn (Rn -= 8n, then access at Rn)
10594 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
10595 && INSN(11,8) == BITS4(1,0,1,1)) {
10596 UInt bP = (insn28 >> 24) & 1;
10597 UInt bU = (insn28 >> 23) & 1;
10598 UInt bW = (insn28 >> 21) & 1;
10599 UInt bL = (insn28 >> 20) & 1;
10600 UInt offset = (insn28 >> 0) & 0xFF;
10601 UInt rN = INSN(19,16);
10602 UInt dD = (INSN(22,22) << 4) | INSN(15,12);
10603 UInt nRegs = offset / 2;
10607 /**/ if (bP == 0 && bU == 1 && bW == 0) {
10610 else if (bP == 0 && bU == 1 && bW == 1) {
10613 else if (bP == 1 && bU == 0 && bW == 1) {
10616 else goto after_vfp_fldmd_fstmd;
10618 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */
10619 if (rN == 15 && (summary == 2 || summary == 3 || isT))
10620 goto after_vfp_fldmd_fstmd;
10622 /* offset must be even, and specify at least one register */
10623 if (1 == (offset & 1) || offset < 2)
10624 goto after_vfp_fldmd_fstmd;
10626 /* can't transfer regs after D15 */
10627 if (dD + nRegs - 1 >= 32)
10628 goto after_vfp_fldmd_fstmd;
10630 /* Now, we can't do a conditional load or store, since that very
10631 likely will generate an exception. So we have to take a side
10632 exit at this point if the condition is false. */
10633 if (condT != IRTemp_INVALID) {
10635 mk_skip_over_T32_if_cond_is_false( condT );
10637 mk_skip_over_A32_if_cond_is_false( condT );
10638 condT = IRTemp_INVALID;
10640 /* Ok, now we're unconditional. Do the load or store. */
10642 /* get the old Rn value */
10643 IRTemp rnT = newTemp(Ity_I32);
10644 assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
10647 /* make a new value for Rn, post-insn */
10648 IRTemp rnTnew = IRTemp_INVALID;
10649 if (summary == 2 || summary == 3) {
10650 rnTnew = newTemp(Ity_I32);
10651 assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
10653 mkU32(8 * nRegs)));
10656 /* decide on the base transfer address */
10657 IRTemp taT = newTemp(Ity_I32);
10658 assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
10660 /* update Rn if necessary -- in case 3, we're moving it down, so
10661 update before any memory reference, in order to keep Memcheck
10662 and V's stack-extending logic (on linux) happy */
10663 if (summary == 3) {
10665 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
10667 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
10670 /* generate the transfers */
10671 for (i = 0; i < nRegs; i++) {
10672 IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
10674 putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
10676 storeLE(addr, getDReg(dD + i));
10680 /* update Rn if necessary -- in case 2, we're moving it up, so
10681 update after any memory reference, in order to keep Memcheck
10682 and V's stack-extending logic (on linux) happy */
10683 if (summary == 2) {
10685 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
10687 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
10690 HChar* nm = bL==1 ? "ld" : "st";
10692 case 1: DIP("f%smd%s r%u, {d%u-d%u}\n",
10693 nm, nCC(conq), rN, dD, dD + nRegs - 1);
10695 case 2: DIP("f%smiad%s r%u!, {d%u-d%u}\n",
10696 nm, nCC(conq), rN, dD, dD + nRegs - 1);
10698 case 3: DIP("f%smdbd%s r%u!, {d%u-d%u}\n",
10699 nm, nCC(conq), rN, dD, dD + nRegs - 1);
10701 default: vassert(0);
10704 goto decode_success_vfp;
10705 /* FIXME alignment constraints? */
10708 after_vfp_fldmd_fstmd:
10710 /* ------------------- fmrx, fmxr ------------------- */
10711 if (BITS8(1,1,1,0,1,1,1,1) == INSN(27,20)
10712 && BITS4(1,0,1,0) == INSN(11,8)
10713 && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
10714 UInt rD = INSN(15,12);
10715 UInt reg = INSN(19,16);
10716 if (reg == BITS4(0,0,0,1)) {
10718 IRTemp nzcvT = newTemp(Ity_I32);
10719 /* When rD is 15, we are copying the top 4 bits of FPSCR
10720 into CPSR. That is, set the flags thunk to COPY and
10721 install FPSCR[31:28] as the value to copy. */
10722 assign(nzcvT, binop(Iop_And32,
10723 IRExpr_Get(OFFB_FPSCR, Ity_I32),
10724 mkU32(0xF0000000)));
10725 setFlags_D1(ARMG_CC_OP_COPY, nzcvT, condT);
10726 DIP("fmstat%s\n", nCC(conq));
10728 /* Otherwise, merely transfer FPSCR to r0 .. r14. */
10729 IRExpr* e = IRExpr_Get(OFFB_FPSCR, Ity_I32);
10731 putIRegT(rD, e, condT);
10733 putIRegA(rD, e, condT, Ijk_Boring);
10734 DIP("fmrx%s r%u, fpscr\n", nCC(conq), rD);
10736 goto decode_success_vfp;
10741 if (BITS8(1,1,1,0,1,1,1,0) == INSN(27,20)
10742 && BITS4(1,0,1,0) == INSN(11,8)
10743 && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
10744 UInt rD = INSN(15,12);
10745 UInt reg = INSN(19,16);
10746 if (reg == BITS4(0,0,0,1)) {
10747 putMiscReg32(OFFB_FPSCR,
10748 isT ? getIRegT(rD) : getIRegA(rD), condT);
10749 DIP("fmxr%s fpscr, r%u\n", nCC(conq), rD);
10750 goto decode_success_vfp;
10755 /* --------------------- vmov --------------------- */
10757 if (0x0C400B10 == (insn28 & 0x0FF00FD0)) {
10758 UInt dM = INSN(3,0) | (INSN(5,5) << 4);
10759 UInt rD = INSN(15,12); /* lo32 */
10760 UInt rN = INSN(19,16); /* hi32 */
10761 if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))) {
10765 unop(Iop_ReinterpI64asF64,
10766 binop(Iop_32HLto64,
10767 isT ? getIRegT(rN) : getIRegA(rN),
10768 isT ? getIRegT(rD) : getIRegA(rD))),
10770 DIP("vmov%s d%u, r%u, r%u\n", nCC(conq), dM, rD, rN);
10771 goto decode_success_vfp;
10777 if (0x0C500B10 == (insn28 & 0x0FF00FD0)) {
10778 UInt dM = INSN(3,0) | (INSN(5,5) << 4);
10779 UInt rD = INSN(15,12); /* lo32 */
10780 UInt rN = INSN(19,16); /* hi32 */
10781 if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))
10785 IRTemp i64 = newTemp(Ity_I64);
10786 assign(i64, unop(Iop_ReinterpF64asI64, getDReg(dM)));
10787 IRExpr* hi32 = unop(Iop_64HIto32, mkexpr(i64));
10788 IRExpr* lo32 = unop(Iop_64to32, mkexpr(i64));
10790 putIRegT(rN, hi32, condT);
10791 putIRegT(rD, lo32, condT);
10793 putIRegA(rN, hi32, condT, Ijk_Boring);
10794 putIRegA(rD, lo32, condT, Ijk_Boring);
10796 DIP("vmov%s r%u, r%u, d%u\n", nCC(conq), rD, rN, dM);
10797 goto decode_success_vfp;
10802 // VMOV sD, sD+1, rN, rM
10803 if (0x0C400A10 == (insn28 & 0x0FF00FD0)) {
10804 UInt sD = (INSN(3,0) << 1) | INSN(5,5);
10805 UInt rN = INSN(15,12);
10806 UInt rM = INSN(19,16);
10807 if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
10812 unop(Iop_ReinterpI32asF32, isT ? getIRegT(rN) : getIRegA(rN)),
10815 unop(Iop_ReinterpI32asF32, isT ? getIRegT(rM) : getIRegA(rM)),
10817 DIP("vmov%s, s%u, s%u, r%u, r%u\n",
10818 nCC(conq), sD, sD + 1, rN, rM);
10819 goto decode_success_vfp;
10823 // VMOV rN, rM, sD, sD+1
10824 if (0x0C500A10 == (insn28 & 0x0FF00FD0)) {
10825 UInt sD = (INSN(3,0) << 1) | INSN(5,5);
10826 UInt rN = INSN(15,12);
10827 UInt rM = INSN(19,16);
10828 if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
10829 || sD == 31 || rN == rM) {
10832 IRExpr* res0 = unop(Iop_ReinterpF32asI32, getFReg(sD));
10833 IRExpr* res1 = unop(Iop_ReinterpF32asI32, getFReg(sD+1));
10835 putIRegT(rN, res0, condT);
10836 putIRegT(rM, res1, condT);
10838 putIRegA(rN, res0, condT, Ijk_Boring);
10839 putIRegA(rM, res1, condT, Ijk_Boring);
10841 DIP("vmov%s, r%u, r%u, s%u, s%u\n",
10842 nCC(conq), rN, rM, sD, sD + 1);
10843 goto decode_success_vfp;
10847 // VMOV rD[x], rT (ARM core register to scalar)
10848 if (0x0E000B10 == (insn28 & 0x0F900F1F)) {
10849 UInt rD = (INSN(7,7) << 4) | INSN(19,16);
10850 UInt rT = INSN(15,12);
10851 UInt opc = (INSN(22,21) << 2) | INSN(6,5);
10853 if (rT == 15 || (isT && rT == 13)) {
10856 if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
10858 putDRegI64(rD, triop(Iop_SetElem8x8,
10862 isT ? getIRegT(rT) : getIRegA(rT))),
10864 DIP("vmov%s.8 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
10865 goto decode_success_vfp;
10867 else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
10868 index = (opc >> 1) & 3;
10869 putDRegI64(rD, triop(Iop_SetElem16x4,
10873 isT ? getIRegT(rT) : getIRegA(rT))),
10875 DIP("vmov%s.16 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
10876 goto decode_success_vfp;
10878 else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0)) {
10879 index = (opc >> 2) & 1;
10880 putDRegI64(rD, triop(Iop_SetElem32x2,
10883 isT ? getIRegT(rT) : getIRegA(rT)),
10885 DIP("vmov%s.32 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
10886 goto decode_success_vfp;
10893 // VMOV (scalar to ARM core register)
10895 if (0x0E100B10 == (insn28 & 0x0F100F1F)) {
10896 UInt rN = (INSN(7,7) << 4) | INSN(19,16);
10897 UInt rT = INSN(15,12);
10898 UInt U = INSN(23,23);
10899 UInt opc = (INSN(22,21) << 2) | INSN(6,5);
10901 if (rT == 15 || (isT && rT == 13)) {
10904 if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
10906 IRExpr* e = unop(U ? Iop_8Uto32 : Iop_8Sto32,
10907 binop(Iop_GetElem8x8,
10911 putIRegT(rT, e, condT);
10913 putIRegA(rT, e, condT, Ijk_Boring);
10914 DIP("vmov%s.%c8 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
10916 goto decode_success_vfp;
10918 else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
10919 index = (opc >> 1) & 3;
10920 IRExpr* e = unop(U ? Iop_16Uto32 : Iop_16Sto32,
10921 binop(Iop_GetElem16x4,
10925 putIRegT(rT, e, condT);
10927 putIRegA(rT, e, condT, Ijk_Boring);
10928 DIP("vmov%s.%c16 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
10930 goto decode_success_vfp;
10932 else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0) && U == 0) {
10933 index = (opc >> 2) & 1;
10934 IRExpr* e = binop(Iop_GetElem32x2, getDRegI64(rN), mkU8(index));
10936 putIRegT(rT, e, condT);
10938 putIRegA(rT, e, condT, Ijk_Boring);
10939 DIP("vmov%s.32 r%u, d%u[%u]\n", nCC(conq), rT, rN, index);
10940 goto decode_success_vfp;
10947 // VMOV.F32 sD, #imm
10948 // FCONSTS sD, #imm
10949 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
10950 && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,0)) {
10951 UInt rD = (INSN(15,12) << 1) | INSN(22,22);
10952 UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
10953 UInt b = (imm8 >> 6) & 1;
10955 imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,(imm8 >> 5) & 1) << 8)
10956 | ((imm8 & 0x1f) << 3);
10958 putFReg(rD, unop(Iop_ReinterpI32asF32, mkU32(imm)), condT);
10959 DIP("fconsts%s s%u #%u", nCC(conq), rD, imm8);
10960 goto decode_success_vfp;
10963 // VMOV.F64 dD, #imm
10964 // FCONSTD dD, #imm
10965 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
10966 && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,1)) {
10967 UInt rD = INSN(15,12) | (INSN(22,22) << 4);
10968 UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
10969 UInt b = (imm8 >> 6) & 1;
10971 imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,b) << 8)
10972 | BITS8(b,b,0,0,0,0,0,0) | (imm8 & 0x3f);
10974 putDReg(rD, unop(Iop_ReinterpI64asF64, mkU64(imm)), condT);
10975 DIP("fconstd%s d%u #%u", nCC(conq), rD, imm8);
10976 goto decode_success_vfp;
10979 /* ---------------------- vdup ------------------------- */
10982 if (BITS8(1,1,1,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,1))
10983 && BITS4(1,0,1,1) == INSN(11,8) && INSN(6,6) == 0 && INSN(4,4) == 1) {
10984 UInt rD = (INSN(7,7) << 4) | INSN(19,16);
10985 UInt rT = INSN(15,12);
10986 UInt Q = INSN(21,21);
10987 UInt size = (INSN(22,22) << 1) | INSN(5,5);
10988 if (rT == 15 || (isT && rT == 13) || size == 3 || (Q && (rD & 1))) {
10991 IRExpr* e = isT ? getIRegT(rT) : getIRegA(rT);
10996 putQReg(rD, unop(Iop_Dup32x4, e), condT);
10999 putQReg(rD, unop(Iop_Dup16x8, unop(Iop_32to16, e)),
11003 putQReg(rD, unop(Iop_Dup8x16, unop(Iop_32to8, e)),
11009 DIP("vdup.%u q%u, r%u\n", 32 / (1<<size), rD, rT);
11013 putDRegI64(rD, unop(Iop_Dup32x2, e), condT);
11016 putDRegI64(rD, unop(Iop_Dup16x4, unop(Iop_32to16, e)),
11020 putDRegI64(rD, unop(Iop_Dup8x8, unop(Iop_32to8, e)),
11026 DIP("vdup.%u d%u, r%u\n", 32 / (1<<size), rD, rT);
11028 goto decode_success_vfp;
11032 /* --------------------- f{ld,st}d --------------------- */
11034 if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
11035 && BITS4(1,0,1,1) == INSN(11,8)) {
11036 UInt dD = INSN(15,12) | (INSN(22,22) << 4);
11037 UInt rN = INSN(19,16);
11038 UInt offset = (insn28 & 0xFF) << 2;
11039 UInt bU = (insn28 >> 23) & 1; /* 1: +offset 0: -offset */
11040 UInt bL = (insn28 >> 20) & 1; /* 1: load 0: store */
11041 /* make unconditional */
11042 if (condT != IRTemp_INVALID) {
11044 mk_skip_over_T32_if_cond_is_false( condT );
11046 mk_skip_over_A32_if_cond_is_false( condT );
11047 condT = IRTemp_INVALID;
11049 IRTemp ea = newTemp(Ity_I32);
11050 assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
11051 align4if(isT ? getIRegT(rN) : getIRegA(rN),
11055 putDReg(dD, loadLE(Ity_F64,mkexpr(ea)), IRTemp_INVALID);
11057 storeLE(mkexpr(ea), getDReg(dD));
11059 DIP("f%sd%s d%u, [r%u, %c#%u]\n",
11060 bL ? "ld" : "st", nCC(conq), dD, rN,
11061 bU ? '+' : '-', offset);
11062 goto decode_success_vfp;
11065 /* --------------------- dp insns (D) --------------------- */
11066 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
11067 && BITS4(1,0,1,1) == INSN(11,8)
11068 && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
11069 UInt dM = INSN(3,0) | (INSN(5,5) << 4); /* argR */
11070 UInt dD = INSN(15,12) | (INSN(22,22) << 4); /* dst/acc */
11071 UInt dN = INSN(19,16) | (INSN(7,7) << 4); /* argL */
11072 UInt bP = (insn28 >> 23) & 1;
11073 UInt bQ = (insn28 >> 21) & 1;
11074 UInt bR = (insn28 >> 20) & 1;
11075 UInt bS = (insn28 >> 6) & 1;
11076 UInt opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
11077 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11079 case BITS4(0,0,0,0): /* MAC: d + n * m */
11080 putDReg(dD, triop(Iop_AddF64, rm,
11082 triop(Iop_MulF64, rm, getDReg(dN),
11085 DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11086 goto decode_success_vfp;
11087 case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
11088 putDReg(dD, triop(Iop_AddF64, rm,
11091 triop(Iop_MulF64, rm, getDReg(dN),
11094 DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11095 goto decode_success_vfp;
11096 case BITS4(0,0,1,0): /* MSC: - d + n * m */
11097 putDReg(dD, triop(Iop_AddF64, rm,
11098 unop(Iop_NegF64, getDReg(dD)),
11099 triop(Iop_MulF64, rm, getDReg(dN),
11102 DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11103 goto decode_success_vfp;
11104 case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
11105 putDReg(dD, triop(Iop_AddF64, rm,
11106 unop(Iop_NegF64, getDReg(dD)),
11108 triop(Iop_MulF64, rm, getDReg(dN),
11111 DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11112 goto decode_success_vfp;
11113 case BITS4(0,1,0,0): /* MUL: n * m */
11114 putDReg(dD, triop(Iop_MulF64, rm, getDReg(dN), getDReg(dM)),
11116 DIP("fmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11117 goto decode_success_vfp;
11118 case BITS4(0,1,0,1): /* NMUL: - n * m */
11119 putDReg(dD, unop(Iop_NegF64,
11120 triop(Iop_MulF64, rm, getDReg(dN),
11123 DIP("fnmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11124 goto decode_success_vfp;
11125 case BITS4(0,1,1,0): /* ADD: n + m */
11126 putDReg(dD, triop(Iop_AddF64, rm, getDReg(dN), getDReg(dM)),
11128 DIP("faddd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11129 goto decode_success_vfp;
11130 case BITS4(0,1,1,1): /* SUB: n - m */
11131 putDReg(dD, triop(Iop_SubF64, rm, getDReg(dN), getDReg(dM)),
11133 DIP("fsubd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11134 goto decode_success_vfp;
11135 case BITS4(1,0,0,0): /* DIV: n / m */
11136 putDReg(dD, triop(Iop_DivF64, rm, getDReg(dN), getDReg(dM)),
11138 DIP("fdivd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11139 goto decode_success_vfp;
11145 /* --------------------- compares (D) --------------------- */
11146 /* 31 27 23 19 15 11 7 3
11147 28 24 20 16 12 8 4 0
11148 FCMPD cond 1110 1D11 0100 Dd 1011 0100 Dm
11149 FCMPED cond 1110 1D11 0100 Dd 1011 1100 Dm
11150 FCMPZD cond 1110 1D11 0101 Dd 1011 0100 0000
11151 FCMPZED cond 1110 1D11 0101 Dd 1011 1100 0000
11154 Z=0 Compare Dd vs Dm and set FPSCR 31:28 accordingly
11155 Z=1 Compare Dd vs zero
11157 N=1 generates Invalid Operation exn if either arg is any kind of NaN
11158 N=0 generates Invalid Operation exn if either arg is a signalling NaN
11159 (Not that we pay any attention to N here)
11161 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11162 && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11163 && BITS4(1,0,1,1) == INSN(11,8)
11164 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11165 UInt bZ = (insn28 >> 16) & 1;
11166 UInt bN = (insn28 >> 7) & 1;
11167 UInt dD = INSN(15,12) | (INSN(22,22) << 4);
11168 UInt dM = INSN(3,0) | (INSN(5,5) << 4);
11169 if (bZ && INSN(3,0) != 0) {
11170 /* does not decode; fall through */
11172 IRTemp argL = newTemp(Ity_F64);
11173 IRTemp argR = newTemp(Ity_F64);
11174 IRTemp irRes = newTemp(Ity_I32);
11175 assign(argL, getDReg(dD));
11176 assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0)) : getDReg(dM));
11177 assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
11179 IRTemp nzcv = IRTemp_INVALID;
11180 IRTemp oldFPSCR = newTemp(Ity_I32);
11181 IRTemp newFPSCR = newTemp(Ity_I32);
11183 /* This is where the fun starts. We have to convert 'irRes'
11184 from an IR-convention return result (IRCmpF64Result) to an
11185 ARM-encoded (N,Z,C,V) group. The final result is in the
11186 bottom 4 bits of 'nzcv'. */
11187 /* Map compare result from IR to ARM(nzcv) */
11189 FP cmp result | IR | ARM(nzcv)
11190 --------------------------------
11196 nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
11198 /* And update FPSCR accordingly */
11199 assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
11202 binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
11203 binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
11205 putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
11208 DIP("fcmpz%sd%s d%u\n", bN ? "e" : "", nCC(conq), dD);
11210 DIP("fcmp%sd%s d%u, d%u\n", bN ? "e" : "", nCC(conq), dD, dM);
11212 goto decode_success_vfp;
11217 /* --------------------- unary (D) --------------------- */
11218 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11219 && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11220 && BITS4(1,0,1,1) == INSN(11,8)
11221 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11222 UInt dD = INSN(15,12) | (INSN(22,22) << 4);
11223 UInt dM = INSN(3,0) | (INSN(5,5) << 4);
11224 UInt b16 = (insn28 >> 16) & 1;
11225 UInt b7 = (insn28 >> 7) & 1;
11226 /**/ if (b16 == 0 && b7 == 0) {
11228 putDReg(dD, getDReg(dM), condT);
11229 DIP("fcpyd%s d%u, d%u\n", nCC(conq), dD, dM);
11230 goto decode_success_vfp;
11232 else if (b16 == 0 && b7 == 1) {
11234 putDReg(dD, unop(Iop_AbsF64, getDReg(dM)), condT);
11235 DIP("fabsd%s d%u, d%u\n", nCC(conq), dD, dM);
11236 goto decode_success_vfp;
11238 else if (b16 == 1 && b7 == 0) {
11240 putDReg(dD, unop(Iop_NegF64, getDReg(dM)), condT);
11241 DIP("fnegd%s d%u, d%u\n", nCC(conq), dD, dM);
11242 goto decode_success_vfp;
11244 else if (b16 == 1 && b7 == 1) {
11246 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11247 putDReg(dD, binop(Iop_SqrtF64, rm, getDReg(dM)), condT);
11248 DIP("fsqrtd%s d%u, d%u\n", nCC(conq), dD, dM);
11249 goto decode_success_vfp;
11257 /* ----------------- I <-> D conversions ----------------- */
11259 // F{S,U}ITOD dD, fM
11260 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11261 && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1))
11262 && BITS4(1,0,1,1) == INSN(11,8)
11263 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11264 UInt bM = (insn28 >> 5) & 1;
11265 UInt fM = (INSN(3,0) << 1) | bM;
11266 UInt dD = INSN(15,12) | (INSN(22,22) << 4);
11267 UInt syned = (insn28 >> 7) & 1;
11270 putDReg(dD, unop(Iop_I32StoF64,
11271 unop(Iop_ReinterpF32asI32, getFReg(fM))),
11273 DIP("fsitod%s d%u, s%u\n", nCC(conq), dD, fM);
11276 putDReg(dD, unop(Iop_I32UtoF64,
11277 unop(Iop_ReinterpF32asI32, getFReg(fM))),
11279 DIP("fuitod%s d%u, s%u\n", nCC(conq), dD, fM);
11281 goto decode_success_vfp;
11284 // FTO{S,U}ID fD, dM
11285 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11286 && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11287 && BITS4(1,0,1,1) == INSN(11,8)
11288 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11289 UInt bD = (insn28 >> 22) & 1;
11290 UInt fD = (INSN(15,12) << 1) | bD;
11291 UInt dM = INSN(3,0) | (INSN(5,5) << 4);
11292 UInt bZ = (insn28 >> 7) & 1;
11293 UInt syned = (insn28 >> 16) & 1;
11294 IRTemp rmode = newTemp(Ity_I32);
11295 assign(rmode, bZ ? mkU32(Irrm_ZERO)
11296 : mkexpr(mk_get_IR_rounding_mode()));
11299 putFReg(fD, unop(Iop_ReinterpI32asF32,
11300 binop(Iop_F64toI32S, mkexpr(rmode),
11303 DIP("ftosi%sd%s s%u, d%u\n", bZ ? "z" : "",
11304 nCC(conq), fD, dM);
11307 putFReg(fD, unop(Iop_ReinterpI32asF32,
11308 binop(Iop_F64toI32U, mkexpr(rmode),
11311 DIP("ftoui%sd%s s%u, d%u\n", bZ ? "z" : "",
11312 nCC(conq), fD, dM);
11314 goto decode_success_vfp;
11317 /* ----------------------------------------------------------- */
11318 /* -- VFP instructions -- single precision -- */
11319 /* ----------------------------------------------------------- */
11321 /* --------------------- fldms, fstms --------------------- */
11323 31 27 23 19 15 11 7 0
11325 C4-98, C5-26 1 FSTMD cond 1100 1x00 Rn Fd 1010 offset
11326 C4-98, C5-28 2 FSTMDIA cond 1100 1x10 Rn Fd 1010 offset
11327 C4-98, C5-30 3 FSTMDDB cond 1101 0x10 Rn Fd 1010 offset
11329 C4-40, C5-26 1 FLDMD cond 1100 1x01 Rn Fd 1010 offset
11330 C4-40, C5-26 2 FLDMIAD cond 1100 1x11 Rn Fd 1010 offset
11331 C4-40, C5-26 3 FLDMDBD cond 1101 0x11 Rn Fd 1010 offset
11333 Regs transferred: F(Fd:D) .. F(Fd:d + offset)
11334 offset must not imply a reg > 15
11335 IA/DB: Rn is changed by (4 x # regs transferred)
11338 1 at-Rn (access at Rn)
11339 2 ia-Rn (access at Rn, then Rn += 4n)
11340 3 db-Rn (Rn -= 4n, then access at Rn)
11342 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
11343 && INSN(11,8) == BITS4(1,0,1,0)) {
11344 UInt bP = (insn28 >> 24) & 1;
11345 UInt bU = (insn28 >> 23) & 1;
11346 UInt bW = (insn28 >> 21) & 1;
11347 UInt bL = (insn28 >> 20) & 1;
11348 UInt bD = (insn28 >> 22) & 1;
11349 UInt offset = (insn28 >> 0) & 0xFF;
11350 UInt rN = INSN(19,16);
11351 UInt fD = (INSN(15,12) << 1) | bD;
11352 UInt nRegs = offset;
11356 /**/ if (bP == 0 && bU == 1 && bW == 0) {
11359 else if (bP == 0 && bU == 1 && bW == 1) {
11362 else if (bP == 1 && bU == 0 && bW == 1) {
11365 else goto after_vfp_fldms_fstms;
11367 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */
11368 if (rN == 15 && (summary == 2 || summary == 3 || isT))
11369 goto after_vfp_fldms_fstms;
11371 /* offset must specify at least one register */
11373 goto after_vfp_fldms_fstms;
11375 /* can't transfer regs after S31 */
11376 if (fD + nRegs - 1 >= 32)
11377 goto after_vfp_fldms_fstms;
11379 /* Now, we can't do a conditional load or store, since that very
11380 likely will generate an exception. So we have to take a side
11381 exit at this point if the condition is false. */
11382 if (condT != IRTemp_INVALID) {
11384 mk_skip_over_T32_if_cond_is_false( condT );
11386 mk_skip_over_A32_if_cond_is_false( condT );
11387 condT = IRTemp_INVALID;
11389 /* Ok, now we're unconditional. Do the load or store. */
11391 /* get the old Rn value */
11392 IRTemp rnT = newTemp(Ity_I32);
11393 assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
11396 /* make a new value for Rn, post-insn */
11397 IRTemp rnTnew = IRTemp_INVALID;
11398 if (summary == 2 || summary == 3) {
11399 rnTnew = newTemp(Ity_I32);
11400 assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
11402 mkU32(4 * nRegs)));
11405 /* decide on the base transfer address */
11406 IRTemp taT = newTemp(Ity_I32);
11407 assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
11409 /* update Rn if necessary -- in case 3, we're moving it down, so
11410 update before any memory reference, in order to keep Memcheck
11411 and V's stack-extending logic (on linux) happy */
11412 if (summary == 3) {
11414 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11416 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11419 /* generate the transfers */
11420 for (i = 0; i < nRegs; i++) {
11421 IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(4*i));
11423 putFReg(fD + i, loadLE(Ity_F32, addr), IRTemp_INVALID);
11425 storeLE(addr, getFReg(fD + i));
11429 /* update Rn if necessary -- in case 2, we're moving it up, so
11430 update after any memory reference, in order to keep Memcheck
11431 and V's stack-extending logic (on linux) happy */
11432 if (summary == 2) {
11434 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11436 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11439 HChar* nm = bL==1 ? "ld" : "st";
11441 case 1: DIP("f%sms%s r%u, {s%u-s%u}\n",
11442 nm, nCC(conq), rN, fD, fD + nRegs - 1);
11444 case 2: DIP("f%smias%s r%u!, {s%u-s%u}\n",
11445 nm, nCC(conq), rN, fD, fD + nRegs - 1);
11447 case 3: DIP("f%smdbs%s r%u!, {s%u-s%u}\n",
11448 nm, nCC(conq), rN, fD, fD + nRegs - 1);
11450 default: vassert(0);
11453 goto decode_success_vfp;
11454 /* FIXME alignment constraints? */
11457 after_vfp_fldms_fstms:
11459 /* --------------------- fmsr, fmrs --------------------- */
11460 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
11461 && BITS4(1,0,1,0) == INSN(11,8)
11462 && BITS4(0,0,0,0) == INSN(3,0)
11463 && BITS4(0,0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
11464 UInt rD = INSN(15,12);
11465 UInt b7 = (insn28 >> 7) & 1;
11466 UInt fN = (INSN(19,16) << 1) | b7;
11467 UInt b20 = (insn28 >> 20) & 1;
11470 /* Let's assume that no sane person would want to do
11471 floating-point transfers to or from the program counter,
11472 and simply decline to decode the instruction. The ARM ARM
11473 doesn't seem to explicitly disallow this case, though. */
11476 IRExpr* res = unop(Iop_ReinterpF32asI32, getFReg(fN));
11478 putIRegT(rD, res, condT);
11480 putIRegA(rD, res, condT, Ijk_Boring);
11481 DIP("fmrs%s r%u, s%u\n", nCC(conq), rD, fN);
11483 putFReg(fN, unop(Iop_ReinterpI32asF32,
11484 isT ? getIRegT(rD) : getIRegA(rD)),
11486 DIP("fmsr%s s%u, r%u\n", nCC(conq), fN, rD);
11488 goto decode_success_vfp;
11493 /* --------------------- f{ld,st}s --------------------- */
11495 if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
11496 && BITS4(1,0,1,0) == INSN(11,8)) {
11497 UInt bD = (insn28 >> 22) & 1;
11498 UInt fD = (INSN(15,12) << 1) | bD;
11499 UInt rN = INSN(19,16);
11500 UInt offset = (insn28 & 0xFF) << 2;
11501 UInt bU = (insn28 >> 23) & 1; /* 1: +offset 0: -offset */
11502 UInt bL = (insn28 >> 20) & 1; /* 1: load 0: store */
11503 /* make unconditional */
11504 if (condT != IRTemp_INVALID) {
11506 mk_skip_over_T32_if_cond_is_false( condT );
11508 mk_skip_over_A32_if_cond_is_false( condT );
11509 condT = IRTemp_INVALID;
11511 IRTemp ea = newTemp(Ity_I32);
11512 assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
11513 align4if(isT ? getIRegT(rN) : getIRegA(rN),
11517 putFReg(fD, loadLE(Ity_F32,mkexpr(ea)), IRTemp_INVALID);
11519 storeLE(mkexpr(ea), getFReg(fD));
11521 DIP("f%ss%s s%u, [r%u, %c#%u]\n",
11522 bL ? "ld" : "st", nCC(conq), fD, rN,
11523 bU ? '+' : '-', offset);
11524 goto decode_success_vfp;
11527 /* --------------------- dp insns (F) --------------------- */
11528 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
11529 && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
11530 && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
11531 UInt bM = (insn28 >> 5) & 1;
11532 UInt bD = (insn28 >> 22) & 1;
11533 UInt bN = (insn28 >> 7) & 1;
11534 UInt fM = (INSN(3,0) << 1) | bM; /* argR */
11535 UInt fD = (INSN(15,12) << 1) | bD; /* dst/acc */
11536 UInt fN = (INSN(19,16) << 1) | bN; /* argL */
11537 UInt bP = (insn28 >> 23) & 1;
11538 UInt bQ = (insn28 >> 21) & 1;
11539 UInt bR = (insn28 >> 20) & 1;
11540 UInt bS = (insn28 >> 6) & 1;
11541 UInt opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
11542 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11544 case BITS4(0,0,0,0): /* MAC: d + n * m */
11545 putFReg(fD, triop(Iop_AddF32, rm,
11547 triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
11549 DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11550 goto decode_success_vfp;
11551 case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
11552 putFReg(fD, triop(Iop_AddF32, rm,
11555 triop(Iop_MulF32, rm, getFReg(fN),
11558 DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11559 goto decode_success_vfp;
11560 case BITS4(0,0,1,0): /* MSC: - d + n * m */
11561 putFReg(fD, triop(Iop_AddF32, rm,
11562 unop(Iop_NegF32, getFReg(fD)),
11563 triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
11565 DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11566 goto decode_success_vfp;
11567 case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
11568 putFReg(fD, triop(Iop_AddF32, rm,
11569 unop(Iop_NegF32, getFReg(fD)),
11571 triop(Iop_MulF32, rm,
11575 DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11576 goto decode_success_vfp;
11577 case BITS4(0,1,0,0): /* MUL: n * m */
11578 putFReg(fD, triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM)),
11580 DIP("fmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11581 goto decode_success_vfp;
11582 case BITS4(0,1,0,1): /* NMUL: - n * m */
11583 putFReg(fD, unop(Iop_NegF32,
11584 triop(Iop_MulF32, rm, getFReg(fN),
11587 DIP("fnmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11588 goto decode_success_vfp;
11589 case BITS4(0,1,1,0): /* ADD: n + m */
11590 putFReg(fD, triop(Iop_AddF32, rm, getFReg(fN), getFReg(fM)),
11592 DIP("fadds%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11593 goto decode_success_vfp;
11594 case BITS4(0,1,1,1): /* SUB: n - m */
11595 putFReg(fD, triop(Iop_SubF32, rm, getFReg(fN), getFReg(fM)),
11597 DIP("fsubs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11598 goto decode_success_vfp;
11599 case BITS4(1,0,0,0): /* DIV: n / m */
11600 putFReg(fD, triop(Iop_DivF32, rm, getFReg(fN), getFReg(fM)),
11602 DIP("fdivs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11603 goto decode_success_vfp;
11609 /* --------------------- compares (S) --------------------- */
11610 /* 31 27 23 19 15 11 7 3
11611 28 24 20 16 12 8 4 0
11612 FCMPS cond 1110 1D11 0100 Fd 1010 01M0 Fm
11613 FCMPES cond 1110 1D11 0100 Fd 1010 11M0 Fm
11614 FCMPZS cond 1110 1D11 0101 Fd 1010 0100 0000
11615 FCMPZED cond 1110 1D11 0101 Fd 1010 1100 0000
11618 Z=0 Compare Fd:D vs Fm:M and set FPSCR 31:28 accordingly
11619 Z=1 Compare Fd:D vs zero
11621 N=1 generates Invalid Operation exn if either arg is any kind of NaN
11622 N=0 generates Invalid Operation exn if either arg is a signalling NaN
11623 (Not that we pay any attention to N here)
11625 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11626 && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11627 && BITS4(1,0,1,0) == INSN(11,8)
11628 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11629 UInt bZ = (insn28 >> 16) & 1;
11630 UInt bN = (insn28 >> 7) & 1;
11631 UInt bD = (insn28 >> 22) & 1;
11632 UInt bM = (insn28 >> 5) & 1;
11633 UInt fD = (INSN(15,12) << 1) | bD;
11634 UInt fM = (INSN(3,0) << 1) | bM;
11635 if (bZ && (INSN(3,0) != 0 || (INSN(7,4) & 3) != 0)) {
11636 /* does not decode; fall through */
11638 IRTemp argL = newTemp(Ity_F64);
11639 IRTemp argR = newTemp(Ity_F64);
11640 IRTemp irRes = newTemp(Ity_I32);
11642 assign(argL, unop(Iop_F32toF64, getFReg(fD)));
11643 assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0))
11644 : unop(Iop_F32toF64, getFReg(fM)));
11645 assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
11647 IRTemp nzcv = IRTemp_INVALID;
11648 IRTemp oldFPSCR = newTemp(Ity_I32);
11649 IRTemp newFPSCR = newTemp(Ity_I32);
11651 /* This is where the fun starts. We have to convert 'irRes'
11652 from an IR-convention return result (IRCmpF64Result) to an
11653 ARM-encoded (N,Z,C,V) group. The final result is in the
11654 bottom 4 bits of 'nzcv'. */
11655 /* Map compare result from IR to ARM(nzcv) */
11657 FP cmp result | IR | ARM(nzcv)
11658 --------------------------------
11664 nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
11666 /* And update FPSCR accordingly */
11667 assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
11670 binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
11671 binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
11673 putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
11676 DIP("fcmpz%ss%s s%u\n", bN ? "e" : "", nCC(conq), fD);
11678 DIP("fcmp%ss%s s%u, s%u\n", bN ? "e" : "",
11679 nCC(conq), fD, fM);
11681 goto decode_success_vfp;
11686 /* --------------------- unary (S) --------------------- */
11687 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11688 && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11689 && BITS4(1,0,1,0) == INSN(11,8)
11690 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11691 UInt bD = (insn28 >> 22) & 1;
11692 UInt bM = (insn28 >> 5) & 1;
11693 UInt fD = (INSN(15,12) << 1) | bD;
11694 UInt fM = (INSN(3,0) << 1) | bM;
11695 UInt b16 = (insn28 >> 16) & 1;
11696 UInt b7 = (insn28 >> 7) & 1;
11697 /**/ if (b16 == 0 && b7 == 0) {
11699 putFReg(fD, getFReg(fM), condT);
11700 DIP("fcpys%s s%u, s%u\n", nCC(conq), fD, fM);
11701 goto decode_success_vfp;
11703 else if (b16 == 0 && b7 == 1) {
11705 putFReg(fD, unop(Iop_AbsF32, getFReg(fM)), condT);
11706 DIP("fabss%s s%u, s%u\n", nCC(conq), fD, fM);
11707 goto decode_success_vfp;
11709 else if (b16 == 1 && b7 == 0) {
11711 putFReg(fD, unop(Iop_NegF32, getFReg(fM)), condT);
11712 DIP("fnegs%s s%u, s%u\n", nCC(conq), fD, fM);
11713 goto decode_success_vfp;
11715 else if (b16 == 1 && b7 == 1) {
11717 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11718 putFReg(fD, binop(Iop_SqrtF32, rm, getFReg(fM)), condT);
11719 DIP("fsqrts%s s%u, s%u\n", nCC(conq), fD, fM);
11720 goto decode_success_vfp;
11728 /* ----------------- I <-> S conversions ----------------- */
11730 // F{S,U}ITOS fD, fM
11731 /* These are more complex than FSITOD/FUITOD. In the D cases, a 32
11732 bit int will always fit within the 53 bit mantissa, so there's
11733 no possibility of a loss of precision, but that's obviously not
11734 the case here. Hence this case possibly requires rounding, and
11735 so it drags in the current rounding mode. */
11736 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11737 && BITS4(1,0,0,0) == INSN(19,16)
11738 && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
11739 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11740 UInt bM = (insn28 >> 5) & 1;
11741 UInt bD = (insn28 >> 22) & 1;
11742 UInt fM = (INSN(3,0) << 1) | bM;
11743 UInt fD = (INSN(15,12) << 1) | bD;
11744 UInt syned = (insn28 >> 7) & 1;
11745 IRTemp rmode = newTemp(Ity_I32);
11746 assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
11749 putFReg(fD, binop(Iop_F64toF32,
11751 unop(Iop_I32StoF64,
11752 unop(Iop_ReinterpF32asI32, getFReg(fM)))),
11754 DIP("fsitos%s s%u, s%u\n", nCC(conq), fD, fM);
11757 putFReg(fD, binop(Iop_F64toF32,
11759 unop(Iop_I32UtoF64,
11760 unop(Iop_ReinterpF32asI32, getFReg(fM)))),
11762 DIP("fuitos%s s%u, s%u\n", nCC(conq), fD, fM);
11764 goto decode_success_vfp;
11767 // FTO{S,U}IS fD, fM
11768 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11769 && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11770 && BITS4(1,0,1,0) == INSN(11,8)
11771 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11772 UInt bM = (insn28 >> 5) & 1;
11773 UInt bD = (insn28 >> 22) & 1;
11774 UInt fD = (INSN(15,12) << 1) | bD;
11775 UInt fM = (INSN(3,0) << 1) | bM;
11776 UInt bZ = (insn28 >> 7) & 1;
11777 UInt syned = (insn28 >> 16) & 1;
11778 IRTemp rmode = newTemp(Ity_I32);
11779 assign(rmode, bZ ? mkU32(Irrm_ZERO)
11780 : mkexpr(mk_get_IR_rounding_mode()));
11783 putFReg(fD, unop(Iop_ReinterpI32asF32,
11784 binop(Iop_F64toI32S, mkexpr(rmode),
11785 unop(Iop_F32toF64, getFReg(fM)))),
11787 DIP("ftosi%ss%s s%u, d%u\n", bZ ? "z" : "",
11788 nCC(conq), fD, fM);
11789 goto decode_success_vfp;
11792 putFReg(fD, unop(Iop_ReinterpI32asF32,
11793 binop(Iop_F64toI32U, mkexpr(rmode),
11794 unop(Iop_F32toF64, getFReg(fM)))),
11796 DIP("ftoui%ss%s s%u, d%u\n", bZ ? "z" : "",
11797 nCC(conq), fD, fM);
11798 goto decode_success_vfp;
11802 /* ----------------- S <-> D conversions ----------------- */
11805 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11806 && BITS4(0,1,1,1) == INSN(19,16)
11807 && BITS4(1,0,1,0) == INSN(11,8)
11808 && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
11809 UInt dD = INSN(15,12) | (INSN(22,22) << 4);
11810 UInt bM = (insn28 >> 5) & 1;
11811 UInt fM = (INSN(3,0) << 1) | bM;
11812 putDReg(dD, unop(Iop_F32toF64, getFReg(fM)), condT);
11813 DIP("fcvtds%s d%u, s%u\n", nCC(conq), dD, fM);
11814 goto decode_success_vfp;
11818 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11819 && BITS4(0,1,1,1) == INSN(19,16)
11820 && BITS4(1,0,1,1) == INSN(11,8)
11821 && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
11822 UInt bD = (insn28 >> 22) & 1;
11823 UInt fD = (INSN(15,12) << 1) | bD;
11824 UInt dM = INSN(3,0) | (INSN(5,5) << 4);
11825 IRTemp rmode = newTemp(Ity_I32);
11826 assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
11827 putFReg(fD, binop(Iop_F64toF32, mkexpr(rmode), getDReg(dM)),
11829 DIP("fcvtsd%s s%u, d%u\n", nCC(conq), fD, dM);
11830 goto decode_success_vfp;
11836 decode_success_vfp:
11837 /* Check that any accepted insn really is a CP10 or CP11 insn, iow,
11838 assert that we aren't accepting, in this fn, insns that actually
11839 should be handled somewhere else. */
11840 vassert(INSN(11,9) == BITS3(1,0,1)); // 11:8 = 1010 or 1011
11847 /*------------------------------------------------------------*/
11848 /*--- Instructions in NV (never) space ---*/
11849 /*------------------------------------------------------------*/
11852 /* Translate a NV space instruction. If successful, returns True and
11853 *dres may or may not be updated. If failure, returns False and
11854 doesn't change *dres nor create any IR.
11856 Note that all NEON instructions (in ARM mode) are handled through
11857 here, since they are all in NV space.
11859 static Bool decode_NV_instruction ( /*MOD*/DisResult* dres,
11860 VexArchInfo* archinfo,
11863 # define INSN(_bMax,_bMin) SLICE_UInt(insn, (_bMax), (_bMin))
11864 # define INSN_COND SLICE_UInt(insn, 31, 28)
11866 HChar dis_buf[128];
11868 // Should only be called for NV instructions
11869 vassert(BITS4(1,1,1,1) == INSN_COND);
11871 /* ------------------------ pld ------------------------ */
11872 if (BITS8(0,1,0,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
11873 && BITS4(1,1,1,1) == INSN(15,12)) {
11874 UInt rN = INSN(19,16);
11875 UInt imm12 = INSN(11,0);
11876 UInt bU = INSN(23,23);
11877 DIP("pld [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
11881 if (BITS8(0,1,1,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
11882 && BITS4(1,1,1,1) == INSN(15,12)
11883 && 0 == INSN(4,4)) {
11884 UInt rN = INSN(19,16);
11885 UInt rM = INSN(3,0);
11886 UInt imm5 = INSN(11,7);
11887 UInt sh2 = INSN(6,5);
11888 UInt bU = INSN(23,23);
11890 IRExpr* eaE = mk_EA_reg_plusminus_shifted_reg(rN, bU, rM,
11891 sh2, imm5, dis_buf);
11892 IRTemp eaT = newTemp(Ity_I32);
11893 /* Bind eaE to a temp merely for debugging-vex purposes, so we
11894 can check it's a plausible decoding. It will get removed
11895 by iropt a little later on. */
11898 DIP("pld %s\n", dis_buf);
11904 /* ------------------------ pli ------------------------ */
11905 if (BITS8(0,1,0,0, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
11906 && BITS4(1,1,1,1) == INSN(15,12)) {
11907 UInt rN = INSN(19,16);
11908 UInt imm12 = INSN(11,0);
11909 UInt bU = INSN(23,23);
11910 DIP("pli [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
11914 /* --------------------- Interworking branches --------------------- */
11916 // BLX (1), viz, unconditional branch and link to R15+simm24
11917 // and set CPSR.T = 1, that is, switch to Thumb mode
11918 if (INSN(31,25) == BITS7(1,1,1,1,1,0,1)) {
11919 UInt bitH = INSN(24,24);
11920 Int uimm24 = INSN(23,0);
11921 Int simm24 = (((uimm24 << 8) >> 8) << 2) + (bitH << 1);
11922 /* Now this is a bit tricky. Since we're decoding an ARM insn,
11923 it is implies that CPSR.T == 0. Hence the current insn's
11924 address is guaranteed to be of the form X--(30)--X00. So, no
11925 need to mask any bits off it. But need to set the lowest bit
11926 to 1 to denote we're in Thumb mode after this, since
11927 guest_R15T has CPSR.T as the lowest bit. And we can't chase
11928 into the call, so end the block at this point. */
11929 UInt dst = guest_R15_curr_instr_notENC + 8 + (simm24 | 1);
11930 putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
11931 IRTemp_INVALID/*because AL*/, Ijk_Boring );
11932 irsb->next = mkU32(dst);
11933 irsb->jumpkind = Ijk_Call;
11934 dres->whatNext = Dis_StopHere;
11935 DIP("blx 0x%x (and switch to Thumb mode)\n", dst - 1);
11939 /* ------------------- v7 barrier insns ------------------- */
11941 case 0xF57FF06F: /* ISB */
11942 stmt( IRStmt_MBE(Imbe_Fence) );
11945 case 0xF57FF04F: /* DSB sy */
11946 case 0xF57FF04E: /* DSB st */
11947 case 0xF57FF04B: /* DSB ish */
11948 case 0xF57FF04A: /* DSB ishst */
11949 case 0xF57FF047: /* DSB nsh */
11950 case 0xF57FF046: /* DSB nshst */
11951 case 0xF57FF043: /* DSB osh */
11952 case 0xF57FF042: /* DSB oshst */
11953 stmt( IRStmt_MBE(Imbe_Fence) );
11956 case 0xF57FF05F: /* DMB sy */
11957 case 0xF57FF05E: /* DMB st */
11958 case 0xF57FF05B: /* DMB ish */
11959 case 0xF57FF05A: /* DMB ishst */
11960 case 0xF57FF057: /* DMB nsh */
11961 case 0xF57FF056: /* DMB nshst */
11962 case 0xF57FF053: /* DMB osh */
11963 case 0xF57FF052: /* DMB oshst */
11964 stmt( IRStmt_MBE(Imbe_Fence) );
11971 /* ------------------- NEON ------------------- */
11972 if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
11973 Bool ok_neon = decode_NEON_instruction(
11974 dres, insn, IRTemp_INVALID/*unconditional*/,
11989 /*------------------------------------------------------------*/
11990 /*--- Disassemble a single ARM instruction ---*/
11991 /*------------------------------------------------------------*/
11993 /* Disassemble a single ARM instruction into IR. The instruction is
11994 located in host memory at guest_instr, and has (decoded) guest IP
11995 of guest_R15_curr_instr_notENC, which will have been set before the
11999 DisResult disInstr_ARM_WRK (
12001 Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
12003 void* callback_opaque,
12004 UChar* guest_instr,
12005 VexArchInfo* archinfo,
12006 VexAbiInfo* abiinfo
12009 // A macro to fish bits out of 'insn'.
12010 # define INSN(_bMax,_bMin) SLICE_UInt(insn, (_bMax), (_bMin))
12011 # define INSN_COND SLICE_UInt(insn, 31, 28)
12015 //Bool allow_VFP = False;
12016 //UInt hwcaps = archinfo->hwcaps;
12017 IRTemp condT; /* :: Ity_I32 */
12019 HChar dis_buf[128]; // big enough to hold LDMIA etc text
12021 /* What insn variants are we supporting today? */
12022 //allow_VFP = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
12025 /* Set result defaults. */
12026 dres.whatNext = Dis_Continue;
12028 dres.continueAt = 0;
12030 /* Set default actions for post-insn handling of writes to r15, if
12032 r15written = False;
12033 r15guard = IRTemp_INVALID; /* unconditional */
12034 r15kind = Ijk_Boring;
12036 /* At least this is simple on ARM: insns are all 4 bytes long, and
12037 4-aligned. So just fish the whole thing out of memory right now
12039 insn = getUIntLittleEndianly( guest_instr );
12041 if (0) vex_printf("insn: 0x%x\n", insn);
12043 DIP("\t(arm) 0x%x: ", (UInt)guest_R15_curr_instr_notENC);
12045 /* We may be asked to update the guest R15 before going further. */
12046 vassert(0 == (guest_R15_curr_instr_notENC & 3));
12048 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) );
12051 /* ----------------------------------------------------------- */
12053 /* Spot "Special" instructions (see comment at top of file). */
12055 UChar* code = (UChar*)guest_instr;
12056 /* Spot the 16-byte preamble:
12058 e1a0c1ec mov r12, r12, ROR #3
12059 e1a0c6ec mov r12, r12, ROR #13
12060 e1a0ceec mov r12, r12, ROR #29
12061 e1a0c9ec mov r12, r12, ROR #19
12063 UInt word1 = 0xE1A0C1EC;
12064 UInt word2 = 0xE1A0C6EC;
12065 UInt word3 = 0xE1A0CEEC;
12066 UInt word4 = 0xE1A0C9EC;
12067 if (getUIntLittleEndianly(code+ 0) == word1 &&
12068 getUIntLittleEndianly(code+ 4) == word2 &&
12069 getUIntLittleEndianly(code+ 8) == word3 &&
12070 getUIntLittleEndianly(code+12) == word4) {
12071 /* Got a "Special" instruction preamble. Which one is it? */
12072 if (getUIntLittleEndianly(code+16) == 0xE18AA00A
12073 /* orr r10,r10,r10 */) {
12074 /* R3 = client_request ( R4 ) */
12075 DIP("r3 = client_request ( %%r4 )\n");
12076 irsb->next = mkU32( guest_R15_curr_instr_notENC + 20 );
12077 irsb->jumpkind = Ijk_ClientReq;
12078 dres.whatNext = Dis_StopHere;
12079 goto decode_success;
12082 if (getUIntLittleEndianly(code+16) == 0xE18BB00B
12083 /* orr r11,r11,r11 */) {
12084 /* R3 = guest_NRADDR */
12085 DIP("r3 = guest_NRADDR\n");
12087 llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
12088 goto decode_success;
12091 if (getUIntLittleEndianly(code+16) == 0xE18CC00C
12092 /* orr r12,r12,r12 */) {
12093 /* branch-and-link-to-noredir R4 */
12094 DIP("branch-and-link-to-noredir r4\n");
12095 llPutIReg(14, mkU32( guest_R15_curr_instr_notENC + 20) );
12096 irsb->next = llGetIReg(4);
12097 irsb->jumpkind = Ijk_NoRedir;
12098 dres.whatNext = Dis_StopHere;
12099 goto decode_success;
12101 /* We don't know what it is. Set opc1/opc2 so decode_failure
12102 can print the insn following the Special-insn preamble. */
12103 insn = getUIntLittleEndianly(code+16);
12104 goto decode_failure;
12110 /* ----------------------------------------------------------- */
12112 /* Main ARM instruction decoder starts here. */
12114 /* Deal with the condition. Strategy is to merely generate a
12115 condition temporary at this point (or IRTemp_INVALID, meaning
12116 unconditional). We leave it to lower-level instruction decoders
12117 to decide whether they can generate straight-line code, or
12118 whether they must generate a side exit before the instruction.
12119 condT :: Ity_I32 and is always either zero or one. */
12120 condT = IRTemp_INVALID;
12121 switch ( (ARMCondcode)INSN_COND ) {
12123 // Illegal instruction prior to v5 (see ARM ARM A3-5), but
12124 // some cases are acceptable
12125 Bool ok = decode_NV_instruction(&dres, archinfo, insn);
12127 goto decode_success;
12129 goto decode_failure;
12131 case ARMCondAL: // Always executed
12133 case ARMCondEQ: case ARMCondNE: case ARMCondHS: case ARMCondLO:
12134 case ARMCondMI: case ARMCondPL: case ARMCondVS: case ARMCondVC:
12135 case ARMCondHI: case ARMCondLS: case ARMCondGE: case ARMCondLT:
12136 case ARMCondGT: case ARMCondLE:
12137 condT = newTemp(Ity_I32);
12138 assign( condT, mk_armg_calculate_condition( INSN_COND ));
12142 /* ----------------------------------------------------------- */
12143 /* -- ARMv5 integer instructions -- */
12144 /* ----------------------------------------------------------- */
12146 /* ---------------- Data processing ops ------------------- */
12148 if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0))
12149 && !(INSN(25,25) == 0 && INSN(7,7) == 1 && INSN(4,4) == 1)) {
12150 IRTemp shop = IRTemp_INVALID; /* shifter operand */
12151 IRTemp shco = IRTemp_INVALID; /* shifter carry out */
12152 UInt rD = (insn >> 12) & 0xF; /* 15:12 */
12153 UInt rN = (insn >> 16) & 0xF; /* 19:16 */
12154 UInt bitS = (insn >> 20) & 1; /* 20:20 */
12155 IRTemp rNt = IRTemp_INVALID;
12156 IRTemp res = IRTemp_INVALID;
12157 IRTemp oldV = IRTemp_INVALID;
12158 IRTemp oldC = IRTemp_INVALID;
12159 HChar* name = NULL;
12160 IROp op = Iop_INVALID;
12163 switch (INSN(24,21)) {
12165 /* --------- ADD, SUB, AND, OR --------- */
12166 case BITS4(0,1,0,0): /* ADD: Rd = Rn + shifter_operand */
12167 name = "add"; op = Iop_Add32; goto rd_eq_rn_op_SO;
12168 case BITS4(0,0,1,0): /* SUB: Rd = Rn - shifter_operand */
12169 name = "sub"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
12170 case BITS4(0,0,1,1): /* RSB: Rd = shifter_operand - Rn */
12171 name = "rsb"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
12172 case BITS4(0,0,0,0): /* AND: Rd = Rn & shifter_operand */
12173 name = "and"; op = Iop_And32; goto rd_eq_rn_op_SO;
12174 case BITS4(1,1,0,0): /* OR: Rd = Rn | shifter_operand */
12175 name = "orr"; op = Iop_Or32; goto rd_eq_rn_op_SO;
12176 case BITS4(0,0,0,1): /* EOR: Rd = Rn ^ shifter_operand */
12177 name = "eor"; op = Iop_Xor32; goto rd_eq_rn_op_SO;
12178 case BITS4(1,1,1,0): /* BIC: Rd = Rn & ~shifter_operand */
12179 name = "bic"; op = Iop_And32; goto rd_eq_rn_op_SO;
12181 Bool isRSB = False;
12182 Bool isBIC = False;
12183 switch (INSN(24,21)) {
12184 case BITS4(0,0,1,1):
12185 vassert(op == Iop_Sub32); isRSB = True; break;
12186 case BITS4(1,1,1,0):
12187 vassert(op == Iop_And32); isBIC = True; break;
12191 rNt = newTemp(Ity_I32);
12192 assign(rNt, getIRegA(rN));
12193 ok = mk_shifter_operand(
12194 INSN(25,25), INSN(11,0),
12195 &shop, bitS ? &shco : NULL, dis_buf
12199 res = newTemp(Ity_I32);
12200 // compute the main result
12202 // reverse-subtract: shifter_operand - Rn
12203 vassert(op == Iop_Sub32);
12204 assign(res, binop(op, mkexpr(shop), mkexpr(rNt)) );
12205 } else if (isBIC) {
12206 // andn: shifter_operand & ~Rn
12207 vassert(op == Iop_And32);
12208 assign(res, binop(op, mkexpr(rNt),
12209 unop(Iop_Not32, mkexpr(shop))) );
12211 // normal: Rn op shifter_operand
12212 assign(res, binop(op, mkexpr(rNt), mkexpr(shop)) );
12214 // but don't commit it until after we've finished
12215 // all necessary reads from the guest state
12217 && (op == Iop_And32 || op == Iop_Or32 || op == Iop_Xor32)) {
12218 oldV = newTemp(Ity_I32);
12219 assign( oldV, mk_armg_calculate_flag_v() );
12221 // can't safely read guest state after here
12222 // now safe to put the main result
12223 putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
12224 // XXXX!! not safe to read any guest state after
12225 // this point (I think the code below doesn't do that).
12227 vassert(shco == IRTemp_INVALID);
12228 /* Update the flags thunk if necessary */
12230 vassert(shco != IRTemp_INVALID);
12233 setFlags_D1_D2( ARMG_CC_OP_ADD, rNt, shop, condT );
12237 setFlags_D1_D2( ARMG_CC_OP_SUB, shop, rNt, condT );
12239 setFlags_D1_D2( ARMG_CC_OP_SUB, rNt, shop, condT );
12242 case Iop_And32: /* BIC and AND set the flags the same */
12245 // oldV has been read just above
12246 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
12247 res, shco, oldV, condT );
12253 DIP("%s%s%s r%u, r%u, %s\n",
12254 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
12255 goto decode_success;
12258 /* --------- MOV, MVN --------- */
12259 case BITS4(1,1,0,1): /* MOV: Rd = shifter_operand */
12260 case BITS4(1,1,1,1): { /* MVN: Rd = not(shifter_operand) */
12261 Bool isMVN = INSN(24,21) == BITS4(1,1,1,1);
12263 break; /* rN must be zero */
12264 ok = mk_shifter_operand(
12265 INSN(25,25), INSN(11,0),
12266 &shop, bitS ? &shco : NULL, dis_buf
12270 res = newTemp(Ity_I32);
12271 assign( res, isMVN ? unop(Iop_Not32, mkexpr(shop))
12274 vassert(shco != IRTemp_INVALID);
12275 oldV = newTemp(Ity_I32);
12276 assign( oldV, mk_armg_calculate_flag_v() );
12278 vassert(shco == IRTemp_INVALID);
12280 // can't safely read guest state after here
12281 putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
12282 /* Update the flags thunk if necessary */
12284 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
12285 res, shco, oldV, condT );
12287 DIP("%s%s%s r%u, %s\n",
12288 isMVN ? "mvn" : "mov",
12289 nCC(INSN_COND), bitS ? "s" : "", rD, dis_buf );
12290 goto decode_success;
12293 /* --------- CMP --------- */
12294 case BITS4(1,0,1,0): /* CMP: (void) Rn - shifter_operand */
12295 case BITS4(1,0,1,1): { /* CMN: (void) Rn + shifter_operand */
12296 Bool isCMN = INSN(24,21) == BITS4(1,0,1,1);
12298 break; /* rD must be zero */
12300 break; /* if S (bit 20) is not set, it's not CMP/CMN */
12301 rNt = newTemp(Ity_I32);
12302 assign(rNt, getIRegA(rN));
12303 ok = mk_shifter_operand(
12304 INSN(25,25), INSN(11,0),
12305 &shop, NULL, dis_buf
12309 // can't safely read guest state after here
12310 /* Update the flags thunk. */
12311 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
12312 rNt, shop, condT );
12313 DIP("%s%s r%u, %s\n",
12314 isCMN ? "cmn" : "cmp",
12315 nCC(INSN_COND), rN, dis_buf );
12316 goto decode_success;
12319 /* --------- TST --------- */
12320 case BITS4(1,0,0,0): /* TST: (void) Rn & shifter_operand */
12321 case BITS4(1,0,0,1): { /* TEQ: (void) Rn ^ shifter_operand */
12322 Bool isTEQ = INSN(24,21) == BITS4(1,0,0,1);
12324 break; /* rD must be zero */
12326 break; /* if S (bit 20) is not set, it's not TST/TEQ */
12327 rNt = newTemp(Ity_I32);
12328 assign(rNt, getIRegA(rN));
12329 ok = mk_shifter_operand(
12330 INSN(25,25), INSN(11,0),
12331 &shop, &shco, dis_buf
12335 /* Update the flags thunk. */
12336 res = newTemp(Ity_I32);
12337 assign( res, binop(isTEQ ? Iop_Xor32 : Iop_And32,
12338 mkexpr(rNt), mkexpr(shop)) );
12339 oldV = newTemp(Ity_I32);
12340 assign( oldV, mk_armg_calculate_flag_v() );
12341 // can't safely read guest state after here
12342 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
12343 res, shco, oldV, condT );
12344 DIP("%s%s r%u, %s\n",
12345 isTEQ ? "teq" : "tst",
12346 nCC(INSN_COND), rN, dis_buf );
12347 goto decode_success;
12350 /* --------- ADC, SBC, RSC --------- */
12351 case BITS4(0,1,0,1): /* ADC: Rd = Rn + shifter_operand + oldC */
12352 name = "adc"; goto rd_eq_rn_op_SO_op_oldC;
12353 case BITS4(0,1,1,0): /* SBC: Rd = Rn - shifter_operand - (oldC ^ 1) */
12354 name = "sbc"; goto rd_eq_rn_op_SO_op_oldC;
12355 case BITS4(0,1,1,1): /* RSC: Rd = shifter_operand - Rn - (oldC ^ 1) */
12356 name = "rsc"; goto rd_eq_rn_op_SO_op_oldC;
12357 rd_eq_rn_op_SO_op_oldC: {
12358 // FIXME: shco isn't used for anything. Get rid of it.
12359 rNt = newTemp(Ity_I32);
12360 assign(rNt, getIRegA(rN));
12361 ok = mk_shifter_operand(
12362 INSN(25,25), INSN(11,0),
12363 &shop, bitS ? &shco : NULL, dis_buf
12367 oldC = newTemp(Ity_I32);
12368 assign( oldC, mk_armg_calculate_flag_c() );
12369 res = newTemp(Ity_I32);
12370 // compute the main result
12371 switch (INSN(24,21)) {
12372 case BITS4(0,1,0,1): /* ADC */
12375 binop(Iop_Add32, mkexpr(rNt), mkexpr(shop)),
12378 case BITS4(0,1,1,0): /* SBC */
12381 binop(Iop_Sub32, mkexpr(rNt), mkexpr(shop)),
12382 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
12384 case BITS4(0,1,1,1): /* RSC */
12387 binop(Iop_Sub32, mkexpr(shop), mkexpr(rNt)),
12388 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
12393 // but don't commit it until after we've finished
12394 // all necessary reads from the guest state
12395 // now safe to put the main result
12396 putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
12397 // XXXX!! not safe to read any guest state after
12398 // this point (I think the code below doesn't do that).
12400 vassert(shco == IRTemp_INVALID);
12401 /* Update the flags thunk if necessary */
12403 vassert(shco != IRTemp_INVALID);
12404 switch (INSN(24,21)) {
12405 case BITS4(0,1,0,1): /* ADC */
12406 setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
12407 rNt, shop, oldC, condT );
12409 case BITS4(0,1,1,0): /* SBC */
12410 setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
12411 rNt, shop, oldC, condT );
12413 case BITS4(0,1,1,1): /* RSC */
12414 setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
12415 shop, rNt, oldC, condT );
12421 DIP("%s%s%s r%u, r%u, %s\n",
12422 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
12423 goto decode_success;
12426 /* --------- ??? --------- */
12430 } /* if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) */
12432 /* --------------------- Load/store (ubyte & word) -------- */
12433 // LDR STR LDRB STRB
12434 /* 31 27 23 19 15 11 6 4 3 # highest bit
12436 A5-20 1 | 16 cond 0101 UB0L Rn Rd imm12
12437 A5-22 1 | 32 cond 0111 UBOL Rn Rd imm5 sh2 0 Rm
12438 A5-24 2 | 16 cond 0101 UB1L Rn Rd imm12
12439 A5-26 2 | 32 cond 0111 UB1L Rn Rd imm5 sh2 0 Rm
12440 A5-28 3 | 16 cond 0100 UB0L Rn Rd imm12
12441 A5-32 3 | 32 cond 0110 UB0L Rn Rd imm5 sh2 0 Rm
12444 1 at-ea (access at ea)
12445 2 at-ea-then-upd (access at ea, then Rn = ea)
12446 3 at-Rn-then-upd (access at Rn, then Rn = ea)
12449 32 Rn +/- Rm sh2 imm5
12451 /* Quickly skip over all of this for hopefully most instructions */
12452 if ((INSN(27,24) & BITS4(1,1,0,0)) != BITS4(0,1,0,0))
12453 goto after_load_store_ubyte_or_word;
12457 /**/ if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 0) {
12460 else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 0
12461 && INSN(4,4) == 0) {
12464 else if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 1) {
12467 else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 1
12468 && INSN(4,4) == 0) {
12471 else if (INSN(27,24) == BITS4(0,1,0,0) && INSN(21,21) == 0) {
12474 else if (INSN(27,24) == BITS4(0,1,1,0) && INSN(21,21) == 0
12475 && INSN(4,4) == 0) {
12478 else goto after_load_store_ubyte_or_word;
12480 { UInt rN = (insn >> 16) & 0xF; /* 19:16 */
12481 UInt rD = (insn >> 12) & 0xF; /* 15:12 */
12482 UInt rM = (insn >> 0) & 0xF; /* 3:0 */
12483 UInt bU = (insn >> 23) & 1; /* 23 */
12484 UInt bB = (insn >> 22) & 1; /* 22 */
12485 UInt bL = (insn >> 20) & 1; /* 20 */
12486 UInt imm12 = (insn >> 0) & 0xFFF; /* 11:0 */
12487 UInt imm5 = (insn >> 7) & 0x1F; /* 11:7 */
12488 UInt sh2 = (insn >> 5) & 3; /* 6:5 */
12490 /* Skip some invalid cases, which would lead to two competing
12491 updates to the same register, or which are otherwise
12492 disallowed by the spec. */
12497 if (rM == 15) goto after_load_store_ubyte_or_word;
12499 case 2 | 16: case 3 | 16:
12500 if (rN == 15) goto after_load_store_ubyte_or_word;
12501 if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
12503 case 2 | 32: case 3 | 32:
12504 if (rM == 15) goto after_load_store_ubyte_or_word;
12505 if (rN == 15) goto after_load_store_ubyte_or_word;
12506 if (rN == rM) goto after_load_store_ubyte_or_word;
12507 if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
12513 /* Now, we can't do a conditional load or store, since that very
12514 likely will generate an exception. So we have to take a side
12515 exit at this point if the condition is false. */
12516 if (condT != IRTemp_INVALID) {
12517 mk_skip_over_A32_if_cond_is_false( condT );
12518 condT = IRTemp_INVALID;
12520 /* Ok, now we're unconditional. Do the load or store. */
12522 /* compute the effective address. Bind it to a tmp since we
12523 may need to use it twice. */
12524 IRExpr* eaE = NULL;
12525 switch (summary & 0xF0) {
12527 eaE = mk_EA_reg_plusminus_imm12( rN, bU, imm12, dis_buf );
12530 eaE = mk_EA_reg_plusminus_shifted_reg( rN, bU, rM, sh2, imm5,
12535 IRTemp eaT = newTemp(Ity_I32);
12538 /* get the old Rn value */
12539 IRTemp rnT = newTemp(Ity_I32);
12540 assign(rnT, getIRegA(rN));
12542 /* decide on the transfer address */
12543 IRTemp taT = IRTemp_INVALID;
12544 switch (summary & 0x0F) {
12545 case 1: case 2: taT = eaT; break;
12546 case 3: taT = rnT; break;
12548 vassert(taT != IRTemp_INVALID);
12551 /* Store. If necessary, update the base register before the
12552 store itself, so that the common idiom of "str rX, [sp,
12553 #-4]!" (store rX at sp-4, then do new sp = sp-4, a.k.a "push
12554 rX") doesn't cause Memcheck to complain that the access is
12555 below the stack pointer. Also, not updating sp before the
12556 store confuses Valgrind's dynamic stack-extending logic. So
12557 do it before the store. Hence we need to snarf the store
12558 data before doing the basereg update. */
12560 /* get hold of the data to be stored */
12561 IRTemp rDt = newTemp(Ity_I32);
12562 assign(rDt, getIRegA(rD));
12564 /* Update Rn if necessary. */
12565 switch (summary & 0x0F) {
12567 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
12571 /* generate the transfer */
12572 if (bB == 0) { // word store
12573 storeLE( mkexpr(taT), mkexpr(rDt) );
12574 } else { // byte store
12576 storeLE( mkexpr(taT), unop(Iop_32to8, mkexpr(rDt)) );
12583 /* generate the transfer */
12584 if (bB == 0) { // word load
12585 putIRegA( rD, loadLE(Ity_I32, mkexpr(taT)),
12586 IRTemp_INVALID, Ijk_Boring );
12587 } else { // byte load
12589 putIRegA( rD, unop(Iop_8Uto32, loadLE(Ity_I8, mkexpr(taT))),
12590 IRTemp_INVALID, Ijk_Boring );
12593 /* Update Rn if necessary. */
12594 switch (summary & 0x0F) {
12596 // should be assured by logic above:
12598 vassert(rD != rN); /* since we just wrote rD */
12599 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
12604 switch (summary & 0x0F) {
12605 case 1: DIP("%sr%s%s r%u, %s\n",
12606 bL == 0 ? "st" : "ld",
12607 bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
12609 case 2: DIP("%sr%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
12610 bL == 0 ? "st" : "ld",
12611 bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
12613 case 3: DIP("%sr%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
12614 bL == 0 ? "st" : "ld",
12615 bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
12617 default: vassert(0);
12620 /* XXX deal with alignment constraints */
12622 goto decode_success;
12626 For all loads: if the Amode specifies base register
12627 writeback, and the same register is specified for Rd and Rn,
12628 the results are UNPREDICTABLE.
12630 For all loads and stores: if R15 is written, branch to
12631 that address afterwards.
12633 STRB: straightforward
12634 LDRB: loaded data is zero extended
12635 STR: lowest 2 bits of address are ignored
12636 LDR: if the lowest 2 bits of the address are nonzero
12637 then the loaded value is rotated right by 8 * the lowest 2 bits
12641 after_load_store_ubyte_or_word:
12643 /* --------------------- Load/store (sbyte & hword) -------- */
12644 // LDRH LDRSH STRH LDRSB
12645 /* 31 27 23 19 15 11 7 3 # highest bit
12646 28 24 20 16 12 8 4 0
12647 A5-36 1 | 16 cond 0001 U10L Rn Rd im4h 1SH1 im4l
12648 A5-38 1 | 32 cond 0001 U00L Rn Rd 0000 1SH1 Rm
12649 A5-40 2 | 16 cond 0001 U11L Rn Rd im4h 1SH1 im4l
12650 A5-42 2 | 32 cond 0001 U01L Rn Rd 0000 1SH1 Rm
12651 A5-44 3 | 16 cond 0000 U10L Rn Rd im4h 1SH1 im4l
12652 A5-46 3 | 32 cond 0000 U00L Rn Rd 0000 1SH1 Rm
12655 1 at-ea (access at ea)
12656 2 at-ea-then-upd (access at ea, then Rn = ea)
12657 3 at-Rn-then-upd (access at Rn, then Rn = ea)
12662 /* Quickly skip over all of this for hopefully most instructions */
12663 if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
12664 goto after_load_store_sbyte_or_hword;
12666 /* Check the "1SH1" thing. */
12667 if ((INSN(7,4) & BITS4(1,0,0,1)) != BITS4(1,0,0,1))
12668 goto after_load_store_sbyte_or_hword;
12672 /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,0)) {
12675 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,0)) {
12678 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,1)) {
12681 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,1)) {
12684 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(1,0)) {
12687 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(0,0)) {
12690 else goto after_load_store_sbyte_or_hword;
12692 { UInt rN = (insn >> 16) & 0xF; /* 19:16 */
12693 UInt rD = (insn >> 12) & 0xF; /* 15:12 */
12694 UInt rM = (insn >> 0) & 0xF; /* 3:0 */
12695 UInt bU = (insn >> 23) & 1; /* 23 U=1 offset+, U=0 offset- */
12696 UInt bL = (insn >> 20) & 1; /* 20 L=1 load, L=0 store */
12697 UInt bH = (insn >> 5) & 1; /* H=1 halfword, H=0 byte */
12698 UInt bS = (insn >> 6) & 1; /* S=1 signed, S=0 unsigned */
12699 UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
12701 /* Skip combinations that are either meaningless or already
12702 handled by main word-or-unsigned-byte load-store
12704 if (bS == 0 && bH == 0) /* "unsigned byte" */
12705 goto after_load_store_sbyte_or_hword;
12706 if (bS == 1 && bL == 0) /* "signed store" */
12707 goto after_load_store_sbyte_or_hword;
12709 /* Require 11:8 == 0 for Rn +/- Rm cases */
12710 if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
12711 goto after_load_store_sbyte_or_hword;
12713 /* Skip some invalid cases, which would lead to two competing
12714 updates to the same register, or which are otherwise
12715 disallowed by the spec. */
12720 if (rM == 15) goto after_load_store_sbyte_or_hword;
12722 case 2 | 16: case 3 | 16:
12723 if (rN == 15) goto after_load_store_sbyte_or_hword;
12724 if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
12726 case 2 | 32: case 3 | 32:
12727 if (rM == 15) goto after_load_store_sbyte_or_hword;
12728 if (rN == 15) goto after_load_store_sbyte_or_hword;
12729 if (rN == rM) goto after_load_store_sbyte_or_hword;
12730 if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
12736 /* Now, we can't do a conditional load or store, since that very
12737 likely will generate an exception. So we have to take a side
12738 exit at this point if the condition is false. */
12739 if (condT != IRTemp_INVALID) {
12740 mk_skip_over_A32_if_cond_is_false( condT );
12741 condT = IRTemp_INVALID;
12743 /* Ok, now we're unconditional. Do the load or store. */
12745 /* compute the effective address. Bind it to a tmp since we
12746 may need to use it twice. */
12747 IRExpr* eaE = NULL;
12748 switch (summary & 0xF0) {
12750 eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
12753 eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
12757 IRTemp eaT = newTemp(Ity_I32);
12760 /* get the old Rn value */
12761 IRTemp rnT = newTemp(Ity_I32);
12762 assign(rnT, getIRegA(rN));
12764 /* decide on the transfer address */
12765 IRTemp taT = IRTemp_INVALID;
12766 switch (summary & 0x0F) {
12767 case 1: case 2: taT = eaT; break;
12768 case 3: taT = rnT; break;
12770 vassert(taT != IRTemp_INVALID);
12772 /* halfword store H 1 L 0 S 0
12773 uhalf load H 1 L 1 S 0
12774 shalf load H 1 L 1 S 1
12775 sbyte load H 0 L 1 S 1
12777 HChar* name = NULL;
12778 /* generate the transfer */
12779 /**/ if (bH == 1 && bL == 0 && bS == 0) { // halfword store
12780 storeLE( mkexpr(taT), unop(Iop_32to16, getIRegA(rD)) );
12783 else if (bH == 1 && bL == 1 && bS == 0) { // uhalf load
12784 putIRegA( rD, unop(Iop_16Uto32, loadLE(Ity_I16, mkexpr(taT))),
12785 IRTemp_INVALID, Ijk_Boring );
12788 else if (bH == 1 && bL == 1 && bS == 1) { // shalf load
12789 putIRegA( rD, unop(Iop_16Sto32, loadLE(Ity_I16, mkexpr(taT))),
12790 IRTemp_INVALID, Ijk_Boring );
12793 else if (bH == 0 && bL == 1 && bS == 1) { // sbyte load
12794 putIRegA( rD, unop(Iop_8Sto32, loadLE(Ity_I8, mkexpr(taT))),
12795 IRTemp_INVALID, Ijk_Boring );
12799 vassert(0); // should be assured by logic above
12801 /* Update Rn if necessary. */
12802 switch (summary & 0x0F) {
12804 // should be assured by logic above:
12806 vassert(rD != rN); /* since we just wrote rD */
12807 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
12811 switch (summary & 0x0F) {
12812 case 1: DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
12814 case 2: DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
12815 name, nCC(INSN_COND), rD, dis_buf);
12817 case 3: DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
12818 name, nCC(INSN_COND), rD, dis_buf);
12820 default: vassert(0);
12823 /* XXX deal with alignment constraints */
12825 goto decode_success;
12829 For all loads: if the Amode specifies base register
12830 writeback, and the same register is specified for Rd and Rn,
12831 the results are UNPREDICTABLE.
12833 For all loads and stores: if R15 is written, branch to
12834 that address afterwards.
12836 Misaligned halfword stores => Unpredictable
12837 Misaligned halfword loads => Unpredictable
12841 after_load_store_sbyte_or_hword:
12843 /* --------------------- Load/store multiple -------------- */
12844 // LD/STMIA LD/STMIB LD/STMDA LD/STMDB
12845 // Remarkably complex and difficult to get right
12846 // match 27:20 as 100XX0WL
12847 if (BITS8(1,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,1,0,0))) {
12848 // A5-50 LD/STMIA cond 1000 10WL Rn RegList
12849 // A5-51 LD/STMIB cond 1001 10WL Rn RegList
12850 // A5-53 LD/STMDA cond 1000 00WL Rn RegList
12851 // A5-53 LD/STMDB cond 1001 00WL Rn RegList
12854 UInt bINC = (insn >> 23) & 1;
12855 UInt bBEFORE = (insn >> 24) & 1;
12857 UInt bL = (insn >> 20) & 1; /* load=1, store=0 */
12858 UInt bW = (insn >> 21) & 1; /* Rn wback=1, no wback=0 */
12859 UInt rN = (insn >> 16) & 0xF;
12860 UInt regList = insn & 0xFFFF;
12861 /* Skip some invalid cases, which would lead to two competing
12862 updates to the same register, or which are otherwise
12863 disallowed by the spec. Note the test above has required
12864 that S == 0, since that looks like a kernel-mode only thing.
12865 Done by forcing the real pattern, viz 100XXSWL to actually be
12867 if (rN == 15) goto after_load_store_multiple;
12868 // reglist can't be empty
12869 if (regList == 0) goto after_load_store_multiple;
12870 // if requested to writeback Rn, and this is a load instruction,
12871 // then Rn can't appear in RegList, since we'd have two competing
12872 // new values for Rn. We do however accept this case for store
12874 if (bW == 1 && bL == 1 && ((1 << rN) & regList) > 0)
12875 goto after_load_store_multiple;
12877 /* Now, we can't do a conditional load or store, since that very
12878 likely will generate an exception. So we have to take a side
12879 exit at this point if the condition is false. */
12880 if (condT != IRTemp_INVALID) {
12881 mk_skip_over_A32_if_cond_is_false( condT );
12882 condT = IRTemp_INVALID;
12885 /* Ok, now we're unconditional. Generate the IR. */
12886 mk_ldm_stm( True/*arm*/, rN, bINC, bBEFORE, bW, bL, regList );
12888 DIP("%sm%c%c%s r%u%s, {0x%04x}\n",
12889 bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
12891 rN, bW ? "!" : "", regList);
12893 goto decode_success;
12896 after_load_store_multiple:
12898 /* --------------------- Control flow --------------------- */
12899 // B, BL (Branch, or Branch-and-Link, to immediate offset)
12901 if (BITS8(1,0,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))) {
12902 UInt link = (insn >> 24) & 1;
12903 UInt uimm24 = insn & ((1<<24)-1);
12904 Int simm24 = (Int)uimm24;
12905 UInt dst = guest_R15_curr_instr_notENC + 8
12906 + (((simm24 << 8) >> 8) << 2);
12907 IRJumpKind jk = link ? Ijk_Call : Ijk_Boring;
12909 putIRegA(14, mkU32(guest_R15_curr_instr_notENC + 4),
12910 condT, Ijk_Boring);
12912 if (condT == IRTemp_INVALID) {
12913 /* unconditional transfer to 'dst'. See if we can simply
12914 continue tracing at the destination. */
12915 if (resteerOkFn( callback_opaque, (Addr64)dst )) {
12917 dres.whatNext = Dis_ResteerU;
12918 dres.continueAt = (Addr64)dst;
12920 /* no; terminate the SB at this point. */
12921 irsb->next = mkU32(dst);
12922 irsb->jumpkind = jk;
12923 dres.whatNext = Dis_StopHere;
12925 DIP("b%s 0x%x\n", link ? "l" : "", dst);
12927 /* conditional transfer to 'dst' */
12928 HChar* comment = "";
12930 /* First see if we can do some speculative chasing into one
12931 arm or the other. Be conservative and only chase if
12932 !link, that is, this is a normal conditional branch to a
12933 known destination. */
12936 && vex_control.guest_chase_cond
12937 && dst < guest_R15_curr_instr_notENC
12938 && resteerOkFn( callback_opaque, (Addr64)(Addr32)dst) ) {
12939 /* Speculation: assume this backward branch is taken. So
12940 we need to emit a side-exit to the insn following this
12941 one, on the negation of the condition, and continue at
12942 the branch target address (dst). */
12943 stmt( IRStmt_Exit( unop(Iop_Not1,
12944 unop(Iop_32to1, mkexpr(condT))),
12946 IRConst_U32(guest_R15_curr_instr_notENC+4) ));
12947 dres.whatNext = Dis_ResteerC;
12948 dres.continueAt = (Addr64)(Addr32)dst;
12949 comment = "(assumed taken)";
12954 && vex_control.guest_chase_cond
12955 && dst >= guest_R15_curr_instr_notENC
12956 && resteerOkFn( callback_opaque,
12958 (guest_R15_curr_instr_notENC+4)) ) {
12959 /* Speculation: assume this forward branch is not taken.
12960 So we need to emit a side-exit to dst (the dest) and
12961 continue disassembling at the insn immediately
12962 following this one. */
12963 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
12965 IRConst_U32(dst) ));
12966 dres.whatNext = Dis_ResteerC;
12967 dres.continueAt = (Addr64)(Addr32)
12968 (guest_R15_curr_instr_notENC+4);
12969 comment = "(assumed not taken)";
12972 /* Conservative default translation - end the block at
12974 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
12975 jk, IRConst_U32(dst) ));
12976 irsb->next = mkU32(guest_R15_curr_instr_notENC + 4);
12977 irsb->jumpkind = jk;
12978 dres.whatNext = Dis_StopHere;
12980 DIP("b%s%s 0x%x %s\n", link ? "l" : "", nCC(INSN_COND),
12983 goto decode_success;
12986 // B, BL (Branch, or Branch-and-Link, to a register)
12987 // NB: interworking branch
12988 if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
12989 && INSN(19,12) == BITS8(1,1,1,1,1,1,1,1)
12990 && (INSN(11,4) == BITS8(1,1,1,1,0,0,1,1)
12991 || INSN(11,4) == BITS8(1,1,1,1,0,0,0,1))) {
12993 UInt link = (INSN(11,4) >> 1) & 1;
12994 UInt rM = INSN(3,0);
12995 // we don't decode the case (link && rM == 15), as that's
12997 if (!(link && rM == 15)) {
12998 if (condT != IRTemp_INVALID) {
12999 mk_skip_over_A32_if_cond_is_false( condT );
13001 // rM contains an interworking address exactly as we require
13002 // (with continuation CPSR.T in bit 0), so we can use it
13003 // as-is, with no masking.
13004 dst = getIRegA(rM);
13006 putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
13007 IRTemp_INVALID/*because AL*/, Ijk_Boring );
13010 irsb->jumpkind = link ? Ijk_Call
13011 : (rM == 14 ? Ijk_Ret : Ijk_Boring);
13012 dres.whatNext = Dis_StopHere;
13013 if (condT == IRTemp_INVALID) {
13014 DIP("b%sx r%u\n", link ? "l" : "", rM);
13016 DIP("b%sx%s r%u\n", link ? "l" : "", nCC(INSN_COND), rM);
13018 goto decode_success;
13020 /* else: (link && rM == 15): just fall through */
13023 /* --- NB: ARM interworking branches are in NV space, hence
13024 are handled elsewhere by decode_NV_instruction.
13028 /* --------------------- Clz --------------------- */
13030 if (INSN(27,20) == BITS8(0,0,0,1,0,1,1,0)
13031 && INSN(19,16) == BITS4(1,1,1,1)
13032 && INSN(11,4) == BITS8(1,1,1,1,0,0,0,1)) {
13033 UInt rD = INSN(15,12);
13034 UInt rM = INSN(3,0);
13035 IRTemp arg = newTemp(Ity_I32);
13036 IRTemp res = newTemp(Ity_I32);
13037 assign(arg, getIRegA(rM));
13038 assign(res, IRExpr_Mux0X(
13039 unop(Iop_1Uto8,binop(Iop_CmpEQ32, mkexpr(arg),
13041 unop(Iop_Clz32, mkexpr(arg)),
13044 putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13045 DIP("clz%s r%u, r%u\n", nCC(INSN_COND), rD, rM);
13046 goto decode_success;
13049 /* --------------------- Mul etc --------------------- */
13051 if (BITS8(0,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
13052 && INSN(15,12) == BITS4(0,0,0,0)
13053 && INSN(7,4) == BITS4(1,0,0,1)) {
13054 UInt bitS = (insn >> 20) & 1; /* 20:20 */
13055 UInt rD = INSN(19,16);
13056 UInt rS = INSN(11,8);
13057 UInt rM = INSN(3,0);
13058 if (rD == 15 || rM == 15 || rS == 15) {
13059 /* Unpredictable; don't decode; fall through */
13061 IRTemp argL = newTemp(Ity_I32);
13062 IRTemp argR = newTemp(Ity_I32);
13063 IRTemp res = newTemp(Ity_I32);
13064 IRTemp oldC = IRTemp_INVALID;
13065 IRTemp oldV = IRTemp_INVALID;
13066 assign( argL, getIRegA(rM));
13067 assign( argR, getIRegA(rS));
13068 assign( res, binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) );
13070 oldC = newTemp(Ity_I32);
13071 assign(oldC, mk_armg_calculate_flag_c());
13072 oldV = newTemp(Ity_I32);
13073 assign(oldV, mk_armg_calculate_flag_v());
13075 // now update guest state
13076 putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
13078 IRTemp pair = newTemp(Ity_I32);
13079 assign( pair, binop(Iop_Or32,
13080 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13082 setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
13084 DIP("mul%c%s r%u, r%u, r%u\n",
13085 bitS ? 's' : ' ', nCC(INSN_COND), rD, rM, rS);
13086 goto decode_success;
13092 if (BITS8(0,0,0,0,0,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13093 && INSN(7,4) == BITS4(1,0,0,1)) {
13094 UInt bitS = (insn >> 20) & 1; /* 20:20 */
13095 UInt isMLS = (insn >> 22) & 1; /* 22:22 */
13096 UInt rD = INSN(19,16);
13097 UInt rN = INSN(15,12);
13098 UInt rS = INSN(11,8);
13099 UInt rM = INSN(3,0);
13100 if (bitS == 1 && isMLS == 1) {
13101 /* This isn't allowed (MLS that sets flags). don't decode;
13105 if (rD == 15 || rM == 15 || rS == 15 || rN == 15) {
13106 /* Unpredictable; don't decode; fall through */
13108 IRTemp argL = newTemp(Ity_I32);
13109 IRTemp argR = newTemp(Ity_I32);
13110 IRTemp argP = newTemp(Ity_I32);
13111 IRTemp res = newTemp(Ity_I32);
13112 IRTemp oldC = IRTemp_INVALID;
13113 IRTemp oldV = IRTemp_INVALID;
13114 assign( argL, getIRegA(rM));
13115 assign( argR, getIRegA(rS));
13116 assign( argP, getIRegA(rN));
13117 assign( res, binop(isMLS ? Iop_Sub32 : Iop_Add32,
13119 binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) ));
13121 vassert(!isMLS); // guaranteed above
13122 oldC = newTemp(Ity_I32);
13123 assign(oldC, mk_armg_calculate_flag_c());
13124 oldV = newTemp(Ity_I32);
13125 assign(oldV, mk_armg_calculate_flag_v());
13127 // now update guest state
13128 putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
13130 IRTemp pair = newTemp(Ity_I32);
13131 assign( pair, binop(Iop_Or32,
13132 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13134 setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
13136 DIP("ml%c%c%s r%u, r%u, r%u, r%u\n",
13137 isMLS ? 's' : 'a', bitS ? 's' : ' ',
13138 nCC(INSN_COND), rD, rM, rS, rN);
13139 goto decode_success;
13145 if (BITS8(0,0,0,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13146 && INSN(7,4) == BITS4(1,0,0,1)) {
13147 UInt bitS = (insn >> 20) & 1; /* 20:20 */
13148 UInt rDhi = INSN(19,16);
13149 UInt rDlo = INSN(15,12);
13150 UInt rS = INSN(11,8);
13151 UInt rM = INSN(3,0);
13152 UInt isS = (INSN(27,20) >> 2) & 1; /* 22:22 */
13153 if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo) {
13154 /* Unpredictable; don't decode; fall through */
13156 IRTemp argL = newTemp(Ity_I32);
13157 IRTemp argR = newTemp(Ity_I32);
13158 IRTemp res = newTemp(Ity_I64);
13159 IRTemp resHi = newTemp(Ity_I32);
13160 IRTemp resLo = newTemp(Ity_I32);
13161 IRTemp oldC = IRTemp_INVALID;
13162 IRTemp oldV = IRTemp_INVALID;
13163 IROp mulOp = isS ? Iop_MullS32 : Iop_MullU32;
13164 assign( argL, getIRegA(rM));
13165 assign( argR, getIRegA(rS));
13166 assign( res, binop(mulOp, mkexpr(argL), mkexpr(argR)) );
13167 assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
13168 assign( resLo, unop(Iop_64to32, mkexpr(res)) );
13170 oldC = newTemp(Ity_I32);
13171 assign(oldC, mk_armg_calculate_flag_c());
13172 oldV = newTemp(Ity_I32);
13173 assign(oldV, mk_armg_calculate_flag_v());
13175 // now update guest state
13176 putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
13177 putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
13179 IRTemp pair = newTemp(Ity_I32);
13180 assign( pair, binop(Iop_Or32,
13181 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13183 setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
13185 DIP("%cmull%c%s r%u, r%u, r%u, r%u\n",
13186 isS ? 's' : 'u', bitS ? 's' : ' ',
13187 nCC(INSN_COND), rDlo, rDhi, rM, rS);
13188 goto decode_success;
13194 if (BITS8(0,0,0,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13195 && INSN(7,4) == BITS4(1,0,0,1)) {
13196 UInt bitS = (insn >> 20) & 1; /* 20:20 */
13197 UInt rDhi = INSN(19,16);
13198 UInt rDlo = INSN(15,12);
13199 UInt rS = INSN(11,8);
13200 UInt rM = INSN(3,0);
13201 UInt isS = (INSN(27,20) >> 2) & 1; /* 22:22 */
13202 if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo) {
13203 /* Unpredictable; don't decode; fall through */
13205 IRTemp argL = newTemp(Ity_I32);
13206 IRTemp argR = newTemp(Ity_I32);
13207 IRTemp old = newTemp(Ity_I64);
13208 IRTemp res = newTemp(Ity_I64);
13209 IRTemp resHi = newTemp(Ity_I32);
13210 IRTemp resLo = newTemp(Ity_I32);
13211 IRTemp oldC = IRTemp_INVALID;
13212 IRTemp oldV = IRTemp_INVALID;
13213 IROp mulOp = isS ? Iop_MullS32 : Iop_MullU32;
13214 assign( argL, getIRegA(rM));
13215 assign( argR, getIRegA(rS));
13216 assign( old, binop(Iop_32HLto64, getIRegA(rDhi), getIRegA(rDlo)) );
13217 assign( res, binop(Iop_Add64,
13219 binop(mulOp, mkexpr(argL), mkexpr(argR))) );
13220 assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
13221 assign( resLo, unop(Iop_64to32, mkexpr(res)) );
13223 oldC = newTemp(Ity_I32);
13224 assign(oldC, mk_armg_calculate_flag_c());
13225 oldV = newTemp(Ity_I32);
13226 assign(oldV, mk_armg_calculate_flag_v());
13228 // now update guest state
13229 putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
13230 putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
13232 IRTemp pair = newTemp(Ity_I32);
13233 assign( pair, binop(Iop_Or32,
13234 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13236 setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
13238 DIP("%cmlal%c%s r%u, r%u, r%u, r%u\n",
13239 isS ? 's' : 'u', bitS ? 's' : ' ', nCC(INSN_COND),
13240 rDlo, rDhi, rM, rS);
13241 goto decode_success;
13246 /* --------------------- Msr etc --------------------- */
13249 if (INSN(27,20) == BITS8(0,0,1,1,0,0,1,0)
13250 && INSN(17,12) == BITS6(0,0,1,1,1,1)) {
13251 UInt write_ge = INSN(18,18);
13252 UInt write_nzcvq = INSN(19,19);
13253 if (write_nzcvq || write_ge) {
13254 UInt imm = (INSN(11,0) >> 0) & 0xFF;
13255 UInt rot = 2 * ((INSN(11,0) >> 8) & 0xF);
13256 IRTemp immT = newTemp(Ity_I32);
13257 vassert(rot <= 30);
13258 imm = ROR32(imm, rot);
13259 assign(immT, mkU32(imm));
13260 desynthesise_APSR( write_nzcvq, write_ge, immT, condT );
13261 DIP("msr%s cpsr%s%sf, #0x%08x\n", nCC(INSN_COND),
13262 write_nzcvq ? "f" : "", write_ge ? "g" : "", imm);
13263 goto decode_success;
13269 if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
13270 && INSN(17,12) == BITS6(0,0,1,1,1,1)
13271 && INSN(11,4) == BITS8(0,0,0,0,0,0,0,0)) {
13272 UInt rN = INSN(3,0);
13273 UInt write_ge = INSN(18,18);
13274 UInt write_nzcvq = INSN(19,19);
13275 if (rN != 15 && (write_nzcvq || write_ge)) {
13276 IRTemp rNt = newTemp(Ity_I32);
13277 assign(rNt, getIRegA(rN));
13278 desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
13279 DIP("msr%s cpsr_%s%s, r%u\n", nCC(INSN_COND),
13280 write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
13281 goto decode_success;
13287 if ((insn & 0x0FFF0FFF) == 0x010F0000) {
13288 UInt rD = INSN(15,12);
13290 IRTemp apsr = synthesise_APSR();
13291 putIRegA( rD, mkexpr(apsr), condT, Ijk_Boring );
13292 DIP("mrs%s r%u, cpsr\n", nCC(INSN_COND), rD);
13293 goto decode_success;
13298 /* --------------------- Svc --------------------- */
13299 if (BITS8(1,1,1,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))) {
13300 UInt imm24 = (insn >> 0) & 0xFFFFFF;
13302 /* A syscall. We can't do this conditionally, hence: */
13303 if (condT != IRTemp_INVALID) {
13304 mk_skip_over_A32_if_cond_is_false( condT );
13307 irsb->next = mkU32( guest_R15_curr_instr_notENC + 4 );
13308 irsb->jumpkind = Ijk_Sys_syscall;
13309 dres.whatNext = Dis_StopHere;
13310 DIP("svc%s #0x%08x\n", nCC(INSN_COND), imm24);
13311 goto decode_success;
13316 /* ------------------------ swp ------------------------ */
13319 if (BITS8(0,0,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
13320 && BITS4(0,0,0,0) == INSN(11,8)
13321 && BITS4(1,0,0,1) == INSN(7,4)) {
13322 UInt rN = INSN(19,16);
13323 UInt rD = INSN(15,12);
13324 UInt rM = INSN(3,0);
13325 IRTemp tRn = newTemp(Ity_I32);
13326 IRTemp tNew = newTemp(Ity_I32);
13327 IRTemp tOld = IRTemp_INVALID;
13328 IRTemp tSC1 = newTemp(Ity_I1);
13329 UInt isB = (insn >> 22) & 1;
13331 if (rD == 15 || rN == 15 || rM == 15 || rN == rM || rN == rD) {
13332 /* undecodable; fall through */
13334 /* make unconditional */
13335 if (condT != IRTemp_INVALID) {
13336 mk_skip_over_A32_if_cond_is_false( condT );
13337 condT = IRTemp_INVALID;
13339 /* Ok, now we're unconditional. Generate a LL-SC loop. */
13340 assign(tRn, getIRegA(rN));
13341 assign(tNew, getIRegA(rM));
13344 tOld = newTemp(Ity_I8);
13345 stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
13347 stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
13348 unop(Iop_32to8, mkexpr(tNew))) );
13351 tOld = newTemp(Ity_I32);
13352 stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
13354 stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
13357 stmt( IRStmt_Exit(unop(Iop_Not1, mkexpr(tSC1)),
13358 /*Ijk_NoRedir*/Ijk_Boring,
13359 IRConst_U32(guest_R15_curr_instr_notENC)) );
13360 putIRegA(rD, isB ? unop(Iop_8Uto32, mkexpr(tOld)) : mkexpr(tOld),
13361 IRTemp_INVALID, Ijk_Boring);
13362 DIP("swp%s%s r%u, r%u, [r%u]\n",
13363 isB ? "b" : "", nCC(INSN_COND), rD, rM, rN);
13364 goto decode_success;
13369 /* ----------------------------------------------------------- */
13370 /* -- ARMv6 instructions -- */
13371 /* ----------------------------------------------------------- */
13373 /* --------------------- ldrex, strex --------------------- */
13376 if (0x01900F9F == (insn & 0x0FF00FFF)) {
13377 UInt rT = INSN(15,12);
13378 UInt rN = INSN(19,16);
13379 if (rT == 15 || rN == 15) {
13380 /* undecodable; fall through */
13383 /* make unconditional */
13384 if (condT != IRTemp_INVALID) {
13385 mk_skip_over_A32_if_cond_is_false( condT );
13386 condT = IRTemp_INVALID;
13388 /* Ok, now we're unconditional. Do the load. */
13389 res = newTemp(Ity_I32);
13390 stmt( IRStmt_LLSC(Iend_LE, res, getIRegA(rN),
13391 NULL/*this is a load*/) );
13392 putIRegA(rT, mkexpr(res), IRTemp_INVALID, Ijk_Boring);
13393 DIP("ldrex%s r%u, [r%u]\n", nCC(INSN_COND), rT, rN);
13394 goto decode_success;
13400 if (0x01800F90 == (insn & 0x0FF00FF0)) {
13401 UInt rT = INSN(3,0);
13402 UInt rN = INSN(19,16);
13403 UInt rD = INSN(15,12);
13404 if (rT == 15 || rN == 15 || rD == 15
13405 || rD == rT || rD == rN) {
13406 /* undecodable; fall through */
13408 IRTemp resSC1, resSC32;
13410 /* make unconditional */
13411 if (condT != IRTemp_INVALID) {
13412 mk_skip_over_A32_if_cond_is_false( condT );
13413 condT = IRTemp_INVALID;
13416 /* Ok, now we're unconditional. Do the store. */
13417 resSC1 = newTemp(Ity_I1);
13418 stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegA(rN), getIRegA(rT)) );
13420 /* Set rD to 1 on failure, 0 on success. Currently we have
13421 resSC1 == 0 on failure, 1 on success. */
13422 resSC32 = newTemp(Ity_I32);
13424 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
13426 putIRegA(rD, mkexpr(resSC32),
13427 IRTemp_INVALID, Ijk_Boring);
13428 DIP("strex%s r%u, r%u, [r%u]\n", nCC(INSN_COND), rD, rT, rN);
13429 goto decode_success;
13434 /* --------------------- movw, movt --------------------- */
13435 if (0x03000000 == (insn & 0x0FF00000)
13436 || 0x03400000 == (insn & 0x0FF00000)) /* pray for CSE */ {
13437 UInt rD = INSN(15,12);
13438 UInt imm16 = (insn & 0xFFF) | ((insn >> 4) & 0x0000F000);
13439 UInt isT = (insn >> 22) & 1;
13446 binop(Iop_And32, getIRegA(rD), mkU32(0xFFFF)),
13447 mkU32(imm16 << 16)),
13448 condT, Ijk_Boring);
13449 DIP("movt%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
13450 goto decode_success;
13452 putIRegA(rD, mkU32(imm16), condT, Ijk_Boring);
13453 DIP("movw%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
13454 goto decode_success;
13460 /* ----------- uxtb, sxtb, uxth, sxth, uxtb16, sxtb16 ----------- */
13461 /* FIXME: this is an exact duplicate of the Thumb version. They
13462 should be commoned up. */
13463 if (BITS8(0,1,1,0,1, 0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,0))
13464 && BITS4(1,1,1,1) == INSN(19,16)
13465 && BITS4(0,1,1,1) == INSN(7,4)
13466 && BITS4(0,0, 0,0) == (INSN(11,8) & BITS4(0,0,1,1))) {
13467 UInt subopc = INSN(27,20) & BITS8(0,0,0,0,0, 1,1,1);
13468 if (subopc != BITS4(0,0,0,1) && subopc != BITS4(0,1,0,1)) {
13469 Int rot = (INSN(11,8) >> 2) & 3;
13470 UInt rM = INSN(3,0);
13471 UInt rD = INSN(15,12);
13472 IRTemp srcT = newTemp(Ity_I32);
13473 IRTemp rotT = newTemp(Ity_I32);
13474 IRTemp dstT = newTemp(Ity_I32);
13476 assign(srcT, getIRegA(rM));
13477 assign(rotT, genROR32(srcT, 8 * rot)); /* 0, 8, 16 or 24 only */
13479 case BITS4(0,1,1,0): // UXTB
13480 assign(dstT, unop(Iop_8Uto32, unop(Iop_32to8, mkexpr(rotT))));
13483 case BITS4(0,0,1,0): // SXTB
13484 assign(dstT, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rotT))));
13487 case BITS4(0,1,1,1): // UXTH
13488 assign(dstT, unop(Iop_16Uto32, unop(Iop_32to16, mkexpr(rotT))));
13491 case BITS4(0,0,1,1): // SXTH
13492 assign(dstT, unop(Iop_16Sto32, unop(Iop_32to16, mkexpr(rotT))));
13495 case BITS4(0,1,0,0): // UXTB16
13496 assign(dstT, binop(Iop_And32, mkexpr(rotT), mkU32(0x00FF00FF)));
13499 case BITS4(0,0,0,0): { // SXTB16
13500 IRTemp lo32 = newTemp(Ity_I32);
13501 IRTemp hi32 = newTemp(Ity_I32);
13502 assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
13503 assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
13509 unop(Iop_32to8, mkexpr(lo32))),
13513 unop(Iop_32to8, mkexpr(hi32))),
13520 vassert(0); // guarded by "if" above
13522 putIRegA(rD, mkexpr(dstT), condT, Ijk_Boring);
13523 DIP("%s%s r%u, r%u, ROR #%u\n", nm, nCC(INSN_COND), rD, rM, rot);
13524 goto decode_success;
13529 /* ------------------- bfi, bfc ------------------- */
13530 if (BITS8(0,1,1,1,1,1,0, 0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
13531 && BITS4(0, 0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
13532 UInt rD = INSN(15,12);
13533 UInt rN = INSN(3,0);
13534 UInt msb = (insn >> 16) & 0x1F; /* 20:16 */
13535 UInt lsb = (insn >> 7) & 0x1F; /* 11:7 */
13536 if (rD == 15 || msb < lsb) {
13537 /* undecodable; fall through */
13539 IRTemp src = newTemp(Ity_I32);
13540 IRTemp olddst = newTemp(Ity_I32);
13541 IRTemp newdst = newTemp(Ity_I32);
13542 UInt mask = 1 << (msb - lsb);
13543 mask = (mask - 1) + mask;
13544 vassert(mask != 0); // guaranteed by "msb < lsb" check above
13547 assign(src, rN == 15 ? mkU32(0) : getIRegA(rN));
13548 assign(olddst, getIRegA(rD));
13552 binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
13559 putIRegA(rD, mkexpr(newdst), condT, Ijk_Boring);
13562 DIP("bfc%s r%u, #%u, #%u\n",
13563 nCC(INSN_COND), rD, lsb, msb-lsb+1);
13565 DIP("bfi%s r%u, r%u, #%u, #%u\n",
13566 nCC(INSN_COND), rD, rN, lsb, msb-lsb+1);
13568 goto decode_success;
13573 /* ------------------- {u,s}bfx ------------------- */
13574 if (BITS8(0,1,1,1,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13575 && BITS4(0,1,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
13576 UInt rD = INSN(15,12);
13577 UInt rN = INSN(3,0);
13578 UInt wm1 = (insn >> 16) & 0x1F; /* 20:16 */
13579 UInt lsb = (insn >> 7) & 0x1F; /* 11:7 */
13580 UInt msb = lsb + wm1;
13581 UInt isU = (insn >> 22) & 1; /* 22:22 */
13582 if (rD == 15 || rN == 15 || msb >= 32) {
13583 /* undecodable; fall through */
13585 IRTemp src = newTemp(Ity_I32);
13586 IRTemp tmp = newTemp(Ity_I32);
13587 IRTemp res = newTemp(Ity_I32);
13588 UInt mask = ((1 << wm1) - 1) + (1 << wm1);
13589 vassert(msb >= 0 && msb <= 31);
13590 vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
13592 assign(src, getIRegA(rN));
13593 assign(tmp, binop(Iop_And32,
13594 binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
13596 assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
13597 binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
13600 putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13602 DIP("%s%s r%u, r%u, #%u, #%u\n",
13603 isU ? "ubfx" : "sbfx",
13604 nCC(INSN_COND), rD, rN, lsb, wm1 + 1);
13605 goto decode_success;
13610 /* --------------------- Load/store doubleword ------------- */
13612 /* 31 27 23 19 15 11 7 3 # highest bit
13613 28 24 20 16 12 8 4 0
13614 A5-36 1 | 16 cond 0001 U100 Rn Rd im4h 11S1 im4l
13615 A5-38 1 | 32 cond 0001 U000 Rn Rd 0000 11S1 Rm
13616 A5-40 2 | 16 cond 0001 U110 Rn Rd im4h 11S1 im4l
13617 A5-42 2 | 32 cond 0001 U010 Rn Rd 0000 11S1 Rm
13618 A5-44 3 | 16 cond 0000 U100 Rn Rd im4h 11S1 im4l
13619 A5-46 3 | 32 cond 0000 U000 Rn Rd 0000 11S1 Rm
13622 1 at-ea (access at ea)
13623 2 at-ea-then-upd (access at ea, then Rn = ea)
13624 3 at-Rn-then-upd (access at Rn, then Rn = ea)
13629 /* Quickly skip over all of this for hopefully most instructions */
13630 if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
13631 goto after_load_store_doubleword;
13633 /* Check the "11S1" thing. */
13634 if ((INSN(7,4) & BITS4(1,1,0,1)) != BITS4(1,1,0,1))
13635 goto after_load_store_doubleword;
13639 /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,0,0)) {
13642 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,0,0)) {
13645 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,1,0)) {
13648 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,1,0)) {
13651 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(1,0,0)) {
13654 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(0,0,0)) {
13657 else goto after_load_store_doubleword;
13659 { UInt rN = (insn >> 16) & 0xF; /* 19:16 */
13660 UInt rD = (insn >> 12) & 0xF; /* 15:12 */
13661 UInt rM = (insn >> 0) & 0xF; /* 3:0 */
13662 UInt bU = (insn >> 23) & 1; /* 23 U=1 offset+, U=0 offset- */
13663 UInt bS = (insn >> 5) & 1; /* S=1 store, S=0 load */
13664 UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
13666 /* Require rD to be an even numbered register */
13668 goto after_load_store_doubleword;
13670 /* Require 11:8 == 0 for Rn +/- Rm cases */
13671 if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
13672 goto after_load_store_doubleword;
13674 /* Skip some invalid cases, which would lead to two competing
13675 updates to the same register, or which are otherwise
13676 disallowed by the spec. */
13681 if (rM == 15) goto after_load_store_doubleword;
13683 case 2 | 16: case 3 | 16:
13684 if (rN == 15) goto after_load_store_doubleword;
13685 if (bS == 0 && (rN == rD || rN == rD+1))
13686 goto after_load_store_doubleword;
13688 case 2 | 32: case 3 | 32:
13689 if (rM == 15) goto after_load_store_doubleword;
13690 if (rN == 15) goto after_load_store_doubleword;
13691 if (rN == rM) goto after_load_store_doubleword;
13692 if (bS == 0 && (rN == rD || rN == rD+1))
13693 goto after_load_store_doubleword;
13699 /* Now, we can't do a conditional load or store, since that very
13700 likely will generate an exception. So we have to take a side
13701 exit at this point if the condition is false. */
13702 if (condT != IRTemp_INVALID) {
13703 mk_skip_over_A32_if_cond_is_false( condT );
13704 condT = IRTemp_INVALID;
13706 /* Ok, now we're unconditional. Do the load or store. */
13708 /* compute the effective address. Bind it to a tmp since we
13709 may need to use it twice. */
13710 IRExpr* eaE = NULL;
13711 switch (summary & 0xF0) {
13713 eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
13716 eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
13720 IRTemp eaT = newTemp(Ity_I32);
13723 /* get the old Rn value */
13724 IRTemp rnT = newTemp(Ity_I32);
13725 assign(rnT, getIRegA(rN));
13727 /* decide on the transfer address */
13728 IRTemp taT = IRTemp_INVALID;
13729 switch (summary & 0x0F) {
13730 case 1: case 2: taT = eaT; break;
13731 case 3: taT = rnT; break;
13733 vassert(taT != IRTemp_INVALID);
13735 /* XXX deal with alignment constraints */
13736 /* XXX: but the A8 doesn't seem to trap for misaligned loads, so,
13737 ignore alignment issues for the time being. */
13739 /* doubleword store S 1
13740 doubleword load S 0
13742 HChar* name = NULL;
13743 /* generate the transfers */
13744 if (bS == 1) { // doubleword store
13745 storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(0)), getIRegA(rD+0) );
13746 storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(4)), getIRegA(rD+1) );
13748 } else { // doubleword load
13750 loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(0))),
13751 IRTemp_INVALID, Ijk_Boring );
13753 loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(4))),
13754 IRTemp_INVALID, Ijk_Boring );
13758 /* Update Rn if necessary. */
13759 switch (summary & 0x0F) {
13761 // should be assured by logic above:
13763 vassert(rD+0 != rN); /* since we just wrote rD+0 */
13764 vassert(rD+1 != rN); /* since we just wrote rD+1 */
13766 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
13770 switch (summary & 0x0F) {
13771 case 1: DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
13773 case 2: DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
13774 name, nCC(INSN_COND), rD, dis_buf);
13776 case 3: DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
13777 name, nCC(INSN_COND), rD, dis_buf);
13779 default: vassert(0);
13782 goto decode_success;
13785 after_load_store_doubleword:
13787 /* ------------------- {s,u}xtab ------------- */
13788 if (BITS8(0,1,1,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
13789 && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
13790 && BITS4(0,1,1,1) == INSN(7,4)) {
13791 UInt rN = INSN(19,16);
13792 UInt rD = INSN(15,12);
13793 UInt rM = INSN(3,0);
13794 UInt rot = (insn >> 10) & 3;
13795 UInt isU = INSN(22,22);
13796 if (rN == 15/*it's {S,U}XTB*/ || rD == 15 || rM == 15) {
13797 /* undecodable; fall through */
13799 IRTemp srcL = newTemp(Ity_I32);
13800 IRTemp srcR = newTemp(Ity_I32);
13801 IRTemp res = newTemp(Ity_I32);
13802 assign(srcR, getIRegA(rM));
13803 assign(srcL, getIRegA(rN));
13804 assign(res, binop(Iop_Add32,
13806 unop(isU ? Iop_8Uto32 : Iop_8Sto32,
13808 genROR32(srcR, 8 * rot)))));
13809 putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13810 DIP("%cxtab%s r%u, r%u, r%u, ror #%u\n",
13811 isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
13812 goto decode_success;
13817 /* ------------------- {s,u}xtah ------------- */
13818 if (BITS8(0,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
13819 && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
13820 && BITS4(0,1,1,1) == INSN(7,4)) {
13821 UInt rN = INSN(19,16);
13822 UInt rD = INSN(15,12);
13823 UInt rM = INSN(3,0);
13824 UInt rot = (insn >> 10) & 3;
13825 UInt isU = INSN(22,22);
13826 if (rN == 15/*it's {S,U}XTH*/ || rD == 15 || rM == 15) {
13827 /* undecodable; fall through */
13829 IRTemp srcL = newTemp(Ity_I32);
13830 IRTemp srcR = newTemp(Ity_I32);
13831 IRTemp res = newTemp(Ity_I32);
13832 assign(srcR, getIRegA(rM));
13833 assign(srcL, getIRegA(rN));
13834 assign(res, binop(Iop_Add32,
13836 unop(isU ? Iop_16Uto32 : Iop_16Sto32,
13838 genROR32(srcR, 8 * rot)))));
13839 putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13841 DIP("%cxtah%s r%u, r%u, r%u, ror #%u\n",
13842 isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
13843 goto decode_success;
13848 /* ------------------- rev16, rev ------------------ */
13849 if (INSN(27,16) == 0x6BF
13850 && (INSN(11,4) == 0xFB/*rev16*/ || INSN(11,4) == 0xF3/*rev*/)) {
13851 Bool isREV = INSN(11,4) == 0xF3;
13852 UInt rM = INSN(3,0);
13853 UInt rD = INSN(15,12);
13854 if (rM != 15 && rD != 15) {
13855 IRTemp rMt = newTemp(Ity_I32);
13856 assign(rMt, getIRegA(rM));
13857 IRTemp res = isREV ? gen_REV(rMt) : gen_REV16(rMt);
13858 putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13859 DIP("rev%s%s r%u, r%u\n", isREV ? "" : "16",
13860 nCC(INSN_COND), rD, rM);
13861 goto decode_success;
13865 /* ------------------- rbit ------------------ */
13866 if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) {
13867 UInt rD = INSN(15,12);
13868 UInt rM = INSN(3,0);
13869 if (rD != 15 && rM != 15) {
13870 IRTemp arg = newTemp(Ity_I32);
13871 assign(arg, getIRegA(rM));
13872 IRTemp res = gen_BITREV(arg);
13873 putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13874 DIP("rbit r%u, r%u\n", rD, rM);
13875 goto decode_success;
13879 /* ------------------- smmul ------------------ */
13880 if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
13881 && INSN(15,12) == BITS4(1,1,1,1)
13882 && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
13883 UInt bitR = INSN(5,5);
13884 UInt rD = INSN(19,16);
13885 UInt rM = INSN(11,8);
13886 UInt rN = INSN(3,0);
13887 if (rD != 15 && rM != 15 && rN != 15) {
13889 = unop(Iop_64HIto32,
13891 binop(Iop_MullS32, getIRegA(rN), getIRegA(rM)),
13892 mkU64(bitR ? 0x80000000ULL : 0ULL)));
13893 putIRegA(rD, res, condT, Ijk_Boring);
13894 DIP("smmul%s%s r%u, r%u, r%u\n",
13895 nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM);
13896 goto decode_success;
13900 /* ------------------- NOP ------------------ */
13901 if (0x0320F000 == (insn & 0x0FFFFFFF)) {
13902 DIP("nop%s\n", nCC(INSN_COND));
13903 goto decode_success;
13906 /* ----------------------------------------------------------- */
13907 /* -- ARMv7 instructions -- */
13908 /* ----------------------------------------------------------- */
13910 /* -------------- read CP15 TPIDRURO register ------------- */
13911 /* mrc p15, 0, r0, c13, c0, 3 up to
13912 mrc p15, 0, r14, c13, c0, 3
13914 /* I don't know whether this is really v7-only. But anyway, we
13915 have to support it since arm-linux uses TPIDRURO as a thread
13917 if (0x0E1D0F70 == (insn & 0x0FFF0FFF)) {
13918 UInt rD = INSN(15,12);
13920 /* skip r15, that's too stupid to handle */
13921 putIRegA(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32),
13922 condT, Ijk_Boring);
13923 DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND), rD);
13924 goto decode_success;
13929 /* Handle various kinds of barriers. This is rather indiscriminate
13930 in the sense that they are all turned into an IR Fence, which
13931 means we don't know which they are, so the back end has to
13932 re-emit them all when it comes acrosss an IR Fence.
13935 case 0xEE070F9A: /* v6 */
13936 /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7). Data
13937 Synch Barrier -- ensures completion of memory accesses. */
13938 stmt( IRStmt_MBE(Imbe_Fence) );
13939 DIP("mcr 15, 0, r0, c7, c10, 4 (data synch barrier)\n");
13940 goto decode_success;
13941 case 0xEE070FBA: /* v6 */
13942 /* mcr 15, 0, r0, c7, c10, 5 (v6) equiv to DMB (v7). Data
13943 Memory Barrier -- ensures ordering of memory accesses. */
13944 stmt( IRStmt_MBE(Imbe_Fence) );
13945 DIP("mcr 15, 0, r0, c7, c10, 5 (data memory barrier)\n");
13946 goto decode_success;
13947 case 0xEE070F95: /* v6 */
13948 /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7).
13949 Instruction Synchronisation Barrier (or Flush Prefetch
13950 Buffer) -- a pipe flush, I think. I suspect we could
13951 ignore those, but to be on the safe side emit a fence
13953 stmt( IRStmt_MBE(Imbe_Fence) );
13954 DIP("mcr 15, 0, r0, c7, c5, 4 (insn synch barrier)\n");
13955 goto decode_success;
13960 /* ----------------------------------------------------------- */
13961 /* -- VFP (CP 10, CP 11) instructions (in ARM mode) -- */
13962 /* ----------------------------------------------------------- */
13964 if (INSN_COND != ARMCondNV) {
13965 Bool ok_vfp = decode_CP10_CP11_instruction (
13966 &dres, INSN(27,0), condT, INSN_COND,
13970 goto decode_success;
13973 /* ----------------------------------------------------------- */
13974 /* -- NEON instructions (in ARM mode) -- */
13975 /* ----------------------------------------------------------- */
13977 /* These are all in NV space, and so are taken care of (far) above,
13978 by a call from this function to decode_NV_instruction(). */
13980 /* ----------------------------------------------------------- */
13981 /* -- v6 media instructions (in ARM mode) -- */
13982 /* ----------------------------------------------------------- */
13984 { Bool ok_v6m = decode_V6MEDIA_instruction(
13985 &dres, INSN(27,0), condT, INSN_COND,
13989 goto decode_success;
13992 /* ----------------------------------------------------------- */
13993 /* -- Undecodable -- */
13994 /* ----------------------------------------------------------- */
13996 goto decode_failure;
14000 /* All decode failures end up here. */
14001 vex_printf("disInstr(arm): unhandled instruction: "
14003 vex_printf(" cond=%d(0x%x) 27:20=%u(0x%02x) "
14006 (Int)INSN_COND, (UInt)INSN_COND,
14007 (Int)INSN(27,20), (UInt)INSN(27,20),
14009 (Int)INSN(3,0), (UInt)INSN(3,0) );
14011 /* Tell the dispatcher that this insn cannot be decoded, and so has
14012 not been executed, and (is currently) the next to be executed.
14013 R15 should be up-to-date since it made so at the start of each
14014 insn, but nevertheless be paranoid and update it again right
14016 vassert(0 == (guest_R15_curr_instr_notENC & 3));
14017 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) );
14018 irsb->next = mkU32(guest_R15_curr_instr_notENC);
14019 irsb->jumpkind = Ijk_NoDecode;
14020 dres.whatNext = Dis_StopHere;
14025 /* All decode successes end up here. */
14028 vassert(dres.len == 4 || dres.len == 20);
14030 /* Now then. Do we have an implicit jump to r15 to deal with? */
14032 /* If we get jump to deal with, we assume that there's been no
14033 other competing branch stuff previously generated for this
14034 insn. That's reasonable, in the sense that the ARM insn set
14035 appears to declare as "Unpredictable" any instruction which
14036 generates more than one possible new value for r15. Hence
14037 just assert. The decoders themselves should check against
14038 all such instructions which are thusly Unpredictable, and
14039 decline to decode them. Hence we should never get here if we
14040 have competing new values for r15, and hence it is safe to
14042 vassert(dres.whatNext == Dis_Continue);
14043 vassert(irsb->next == NULL);
14044 vassert(irsb->jumpkind == Ijk_Boring);
14045 /* If r15 is unconditionally written, terminate the block by
14046 jumping to it. If it's conditionally written, still
14047 terminate the block (a shame, but we can't do side exits to
14048 arbitrary destinations), but first jump to the next
14049 instruction if the condition doesn't hold. */
14050 /* We can't use getIReg(15) to get the destination, since that
14051 will produce r15+8, which isn't what we want. Must use
14052 llGetIReg(15) instead. */
14053 if (r15guard == IRTemp_INVALID) {
14054 /* unconditional */
14060 mkexpr(r15guard), mkU32(1))),
14062 IRConst_U32(guest_R15_curr_instr_notENC + 4)
14065 irsb->next = llGetIReg(15);
14066 irsb->jumpkind = r15kind;
14067 dres.whatNext = Dis_StopHere;
14077 /*------------------------------------------------------------*/
14078 /*--- Disassemble a single Thumb2 instruction ---*/
14079 /*------------------------------------------------------------*/
14081 /* NB: in Thumb mode we do fetches of regs with getIRegT, which
14082 automagically adds 4 to fetches of r15. However, writes to regs
14083 are done with putIRegT, which disallows writes to r15. Hence any
14084 r15 writes and associated jumps have to be done "by hand". */
14086 /* Disassemble a single Thumb instruction into IR. The instruction is
14087 located in host memory at guest_instr, and has (decoded) guest IP
14088 of guest_R15_curr_instr_notENC, which will have been set before the
14092 DisResult disInstr_THUMB_WRK (
14094 Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
14096 void* callback_opaque,
14097 UChar* guest_instr,
14098 VexArchInfo* archinfo,
14099 VexAbiInfo* abiinfo
14102 /* A macro to fish bits out of insn0. There's also INSN1, to fish
14103 bits out of insn1, but that's defined only after the end of the
14104 16-bit insn decoder, so as to stop it mistakenly being used
14106 # define INSN0(_bMax,_bMin) SLICE_UInt(((UInt)insn0), (_bMax), (_bMin))
14109 UShort insn0; /* first 16 bits of the insn */
14110 //Bool allow_VFP = False;
14111 //UInt hwcaps = archinfo->hwcaps;
14112 HChar dis_buf[128]; // big enough to hold LDMIA etc text
14114 /* Summary result of the ITxxx backwards analysis: False == safe
14116 Bool guaranteedUnconditional = False;
14118 /* What insn variants are we supporting today? */
14119 //allow_VFP = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
14122 /* Set result defaults. */
14123 dres.whatNext = Dis_Continue;
14125 dres.continueAt = 0;
14127 /* Set default actions for post-insn handling of writes to r15, if
14129 r15written = False;
14130 r15guard = IRTemp_INVALID; /* unconditional */
14131 r15kind = Ijk_Boring;
14133 /* Insns could be 2 or 4 bytes long. Just get the first 16 bits at
14134 this point. If we need the second 16, get them later. We can't
14135 get them both out immediately because it risks a fault (very
14136 unlikely, but ..) if the second 16 bits aren't actually
14138 insn0 = getUShortLittleEndianly( guest_instr );
14140 if (0) vex_printf("insn: 0x%x\n", insn0);
14142 DIP("\t(thumb) 0x%x: ", (UInt)guest_R15_curr_instr_notENC);
14144 /* We may be asked to update the guest R15 before going further. */
14145 vassert(0 == (guest_R15_curr_instr_notENC & 1));
14147 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) );
14150 /* ----------------------------------------------------------- */
14151 /* Spot "Special" instructions (see comment at top of file). */
14153 UChar* code = (UChar*)guest_instr;
14154 /* Spot the 16-byte preamble:
14156 ea4f 0cfc mov.w ip, ip, ror #3
14157 ea4f 3c7c mov.w ip, ip, ror #13
14158 ea4f 7c7c mov.w ip, ip, ror #29
14159 ea4f 4cfc mov.w ip, ip, ror #19
14161 UInt word1 = 0x0CFCEA4F;
14162 UInt word2 = 0x3C7CEA4F;
14163 UInt word3 = 0x7C7CEA4F;
14164 UInt word4 = 0x4CFCEA4F;
14165 if (getUIntLittleEndianly(code+ 0) == word1 &&
14166 getUIntLittleEndianly(code+ 4) == word2 &&
14167 getUIntLittleEndianly(code+ 8) == word3 &&
14168 getUIntLittleEndianly(code+12) == word4) {
14169 /* Got a "Special" instruction preamble. Which one is it? */
14171 if (getUIntLittleEndianly(code+16) == 0x0A0AEA4A
14172 /* orr.w r10,r10,r10 */) {
14173 /* R3 = client_request ( R4 ) */
14174 DIP("r3 = client_request ( %%r4 )\n");
14175 irsb->next = mkU32( (guest_R15_curr_instr_notENC + 20) | 1 );
14176 irsb->jumpkind = Ijk_ClientReq;
14177 dres.whatNext = Dis_StopHere;
14178 goto decode_success;
14182 if (getUIntLittleEndianly(code+16) == 0x0B0BEA4B
14183 /* orr r11,r11,r11 */) {
14184 /* R3 = guest_NRADDR */
14185 DIP("r3 = guest_NRADDR\n");
14187 llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
14188 goto decode_success;
14192 if (getUIntLittleEndianly(code+16) == 0x0C0CEA4C
14193 /* orr r12,r12,r12 */) {
14194 /* branch-and-link-to-noredir R4 */
14195 DIP("branch-and-link-to-noredir r4\n");
14196 llPutIReg(14, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 ));
14197 irsb->next = getIRegT(4);
14198 irsb->jumpkind = Ijk_NoRedir;
14199 dres.whatNext = Dis_StopHere;
14200 goto decode_success;
14202 /* We don't know what it is. Set insn0 so decode_failure
14203 can print the insn following the Special-insn preamble. */
14204 insn0 = getUShortLittleEndianly(code+16);
14205 goto decode_failure;
14211 /* ----------------------------------------------------------- */
14213 /* Main Thumb instruction decoder starts here. It's a series of
14214 switches which examine ever longer bit sequences at the MSB of
14215 the instruction word, first for 16-bit insns, then for 32-bit
14218 /* --- BEGIN ITxxx optimisation analysis --- */
14219 /* This is a crucial optimisation for the ITState boilerplate that
14220 follows. Examine the 9 halfwords preceding this instruction,
14221 and if we are absolutely sure that none of them constitute an
14222 'it' instruction, then we can be sure that this instruction is
14223 not under the control of any 'it' instruction, and so
14224 guest_ITSTATE must be zero. So write zero into ITSTATE right
14225 now, so that iropt can fold out almost all of the resulting
14228 If we aren't sure, we can always safely skip this step. So be a
14229 bit conservative about it: only poke around in the same page as
14230 this instruction, lest we get a fault from the previous page
14231 that would not otherwise have happened. The saving grace is
14232 that such skipping is pretty rare -- it only happens,
14233 statistically, 18/4096ths of the time, so is judged unlikely to
14234 be a performance problems.
14236 FIXME: do better. Take into account the number of insns covered
14237 by any IT insns we find, to rule out cases where an IT clearly
14238 cannot cover this instruction. This would improve behaviour for
14239 branch targets immediately following an IT-guarded group that is
14240 not of full length. Eg, (and completely ignoring issues of 16-
14241 vs 32-bit insn length):
14249 The 'it' only conditionalises insn1 and insn2. However, the
14250 current analysis is conservative and considers insn3 and insn4
14251 also possibly guarded. Hence if 'label:' is the start of a hot
14252 loop we will get a big performance hit.
14255 /* Summary result of this analysis: False == safe but
14257 vassert(guaranteedUnconditional == False);
14259 UInt pc = guest_R15_curr_instr_notENC;
14260 vassert(0 == (pc & 1));
14262 UInt pageoff = pc & 0xFFF;
14263 if (pageoff >= 18) {
14264 /* It's safe to poke about in the 9 halfwords preceding this
14265 insn. So, have a look at them. */
14266 guaranteedUnconditional = True; /* assume no 'it' insn found, till we do */
14268 UShort* hwp = (UShort*)(HWord)pc;
14270 for (i = -1; i >= -9; i--) {
14271 /* We're in the same page. (True, but commented out due
14274 vassert( ( ((UInt)(&hwp[i])) & 0xFFFFF000 )
14275 == ( pc & 0xFFFFF000 ) );
14277 /* All valid IT instructions must have the form 0xBFxy,
14278 where x can be anything, but y must be nonzero. */
14279 if ((hwp[i] & 0xFF00) == 0xBF00 && (hwp[i] & 0xF) != 0) {
14280 /* might be an 'it' insn. Play safe. */
14281 guaranteedUnconditional = False;
14287 /* --- END ITxxx optimisation analysis --- */
14289 /* Generate the guarding condition for this insn, by examining
14290 ITSTATE. Assign it to condT. Also, generate new
14291 values for ITSTATE ready for stuffing back into the
14292 guest state, but don't actually do the Put yet, since it will
14293 need to stuffed back in only after the instruction gets to a
14294 point where it is sure to complete. Mostly we let the code at
14295 decode_success handle this, but in cases where the insn contains
14296 a side exit, we have to update them before the exit. */
14298 /* If the ITxxx optimisation analysis above could not prove that
14299 this instruction is guaranteed unconditional, we insert a
14300 lengthy IR preamble to compute the guarding condition at
14301 runtime. If it can prove it (which obviously we hope is the
14302 normal case) then we insert a minimal preamble, which is
14303 equivalent to setting guest_ITSTATE to zero and then folding
14304 that through the full preamble (which completely disappears). */
14306 IRTemp condT = IRTemp_INVALID;
14307 IRTemp old_itstate = IRTemp_INVALID;
14308 IRTemp new_itstate = IRTemp_INVALID;
14309 IRTemp cond_AND_notInIT_T = IRTemp_INVALID;
14311 if (guaranteedUnconditional) {
14312 /* BEGIN "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
14314 // ITSTATE = 0 :: I32
14315 IRTemp z32 = newTemp(Ity_I32);
14316 assign(z32, mkU32(0));
14319 // old_itstate = 0 :: I32
14321 // old_itstate = get_ITSTATE();
14322 old_itstate = z32; /* 0 :: I32 */
14324 // new_itstate = old_itstate >> 8
14328 // new_itstate = newTemp(Ity_I32);
14329 // assign(new_itstate,
14330 // binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
14333 // ITSTATE = 0 :: I32(again)
14335 // put_ITSTATE(new_itstate);
14337 // condT1 = calc_cond_dyn( xor(and(old_istate,0xF0), 0xE0) )
14338 // = calc_cond_dyn( xor(0,0xE0) )
14339 // = calc_cond_dyn ( 0xE0 )
14341 // Not that this matters, since the computed value is not used:
14342 // see condT folding below
14344 // IRTemp condT1 = newTemp(Ity_I32);
14346 // mk_armg_calculate_condition_dyn(
14347 // binop(Iop_Xor32,
14348 // binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
14353 // condT = 32to8(and32(old_itstate,0xF0)) == 0 ? 1 : condT1
14354 // = 32to8(and32(0,0xF0)) == 0 ? 1 : condT1
14355 // = 32to8(0) == 0 ? 1 : condT1
14356 // = 0 == 0 ? 1 : condT1
14359 // condT = newTemp(Ity_I32);
14360 // assign(condT, IRExpr_Mux0X(
14361 // unop(Iop_32to8, binop(Iop_And32,
14362 // mkexpr(old_itstate),
14367 condT = newTemp(Ity_I32);
14368 assign(condT, mkU32(1));
14370 // notInITt = xor32(and32(old_itstate, 1), 1)
14371 // = xor32(and32(0, 1), 1)
14375 // IRTemp notInITt = newTemp(Ity_I32);
14376 // assign(notInITt,
14377 // binop(Iop_Xor32,
14378 // binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
14381 // cond_AND_notInIT_T = and32(notInITt, condT)
14385 // cond_AND_notInIT_T = newTemp(Ity_I32);
14386 // assign(cond_AND_notInIT_T,
14387 // binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
14388 cond_AND_notInIT_T = condT; /* 1 :: I32 */
14390 /* END "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
14392 /* BEGIN { STANDARD PREAMBLE; } */
14394 old_itstate = get_ITSTATE();
14396 new_itstate = newTemp(Ity_I32);
14397 assign(new_itstate,
14398 binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
14400 put_ITSTATE(new_itstate);
14402 /* Same strategy as for ARM insns: generate a condition
14403 temporary at this point (or IRTemp_INVALID, meaning
14404 unconditional). We leave it to lower-level instruction
14405 decoders to decide whether they can generate straight-line
14406 code, or whether they must generate a side exit before the
14407 instruction. condT :: Ity_I32 and is always either zero or
14409 IRTemp condT1 = newTemp(Ity_I32);
14411 mk_armg_calculate_condition_dyn(
14413 binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
14418 /* This is a bit complex, but needed to make Memcheck understand
14419 that, if the condition in old_itstate[7:4] denotes AL (that
14420 is, if this instruction is to be executed unconditionally),
14421 then condT does not depend on the results of calling the
14424 We test explicitly for old_itstate[7:4] == AL ^ 0xE, and in
14425 that case set condT directly to 1. Else we use the results
14426 of the helper. Since old_itstate is always defined and
14427 because Memcheck does lazy V-bit propagation through Mux0X,
14428 this will cause condT to always be a defined 1 if the
14429 condition is 'AL'. From an execution semantics point of view
14430 this is irrelevant since we're merely duplicating part of the
14431 behaviour of the helper. But it makes it clear to Memcheck,
14432 in this case, that condT does not in fact depend on the
14433 contents of the condition code thunk. Without it, we get
14434 quite a lot of false errors.
14436 So, just to clarify: from a straight semantics point of view,
14437 we can simply do "assign(condT, mkexpr(condT1))", and the
14438 simulator still runs fine. It's just that we get loads of
14439 false errors from Memcheck. */
14440 condT = newTemp(Ity_I32);
14441 assign(condT, IRExpr_Mux0X(
14442 unop(Iop_32to8, binop(Iop_And32,
14443 mkexpr(old_itstate),
14449 /* Something we don't have in ARM: generate a 0 or 1 value
14450 indicating whether or not we are in an IT block (NB: 0 = in
14451 IT block, 1 = not in IT block). This is used to gate
14452 condition code updates in 16-bit Thumb instructions. */
14453 IRTemp notInITt = newTemp(Ity_I32);
14456 binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
14459 /* Compute 'condT && notInITt' -- that is, the instruction is
14460 going to execute, and we're not in an IT block. This is the
14461 gating condition for updating condition codes in 16-bit Thumb
14462 instructions, except for CMP, CMN and TST. */
14463 cond_AND_notInIT_T = newTemp(Ity_I32);
14464 assign(cond_AND_notInIT_T,
14465 binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
14466 /* END { STANDARD PREAMBLE; } */
14471 * ITSTATE has been updated
14472 * condT holds the guarding condition for this instruction (0 or 1),
14473 * notInITt is 1 if we're in "normal" code, 0 if in an IT block
14474 * cond_AND_notInIT_T is the AND of the above two.
14476 If the instruction proper can't trap, then there's nothing else
14477 to do w.r.t. ITSTATE -- just go and and generate IR for the
14478 insn, taking into account the guarding condition.
14480 If, however, the instruction might trap, then we must back up
14481 ITSTATE to the old value, and re-update it after the potentially
14482 trapping IR section. A trap can happen either via a memory
14483 reference or because we need to throw SIGILL.
14485 If an instruction has a side exit, we need to be sure that any
14486 ITSTATE backup is re-updated before the side exit.
14489 /* ----------------------------------------------------------- */
14491 /* -- Thumb 16-bit integer instructions -- */
14493 /* -- IMPORTANT: references to insn1 or INSN1 are -- */
14494 /* -- not allowed in this section -- */
14496 /* ----------------------------------------------------------- */
14498 /* 16-bit instructions inside an IT block, apart from CMP, CMN and
14499 TST, do not set the condition codes. Hence we must dynamically
14500 test for this case for every condition code update. */
14502 IROp anOp = Iop_INVALID;
14503 HChar* anOpNm = NULL;
14505 /* ================ 16-bit 15:6 cases ================ */
14507 switch (INSN0(15,6)) {
14510 case 0x10b: { // CMN
14511 /* ---------------- CMP Rn, Rm ---------------- */
14512 Bool isCMN = INSN0(15,6) == 0x10b;
14513 UInt rN = INSN0(2,0);
14514 UInt rM = INSN0(5,3);
14515 IRTemp argL = newTemp(Ity_I32);
14516 IRTemp argR = newTemp(Ity_I32);
14517 assign( argL, getIRegT(rN) );
14518 assign( argR, getIRegT(rM) );
14519 /* Update flags regardless of whether in an IT block or not. */
14520 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
14521 argL, argR, condT );
14522 DIP("%s r%u, r%u\n", isCMN ? "cmn" : "cmp", rN, rM);
14523 goto decode_success;
14527 /* ---------------- TST Rn, Rm ---------------- */
14528 UInt rN = INSN0(2,0);
14529 UInt rM = INSN0(5,3);
14530 IRTemp oldC = newTemp(Ity_I32);
14531 IRTemp oldV = newTemp(Ity_I32);
14532 IRTemp res = newTemp(Ity_I32);
14533 assign( oldC, mk_armg_calculate_flag_c() );
14534 assign( oldV, mk_armg_calculate_flag_v() );
14535 assign( res, binop(Iop_And32, getIRegT(rN), getIRegT(rM)) );
14536 /* Update flags regardless of whether in an IT block or not. */
14537 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
14538 DIP("tst r%u, r%u\n", rN, rM);
14539 goto decode_success;
14543 /* ---------------- NEGS Rd, Rm ---------------- */
14545 UInt rM = INSN0(5,3);
14546 UInt rD = INSN0(2,0);
14547 IRTemp arg = newTemp(Ity_I32);
14548 IRTemp zero = newTemp(Ity_I32);
14549 assign(arg, getIRegT(rM));
14550 assign(zero, mkU32(0));
14551 // rD can never be r15
14552 putIRegT(rD, binop(Iop_Sub32, mkexpr(zero), mkexpr(arg)), condT);
14553 setFlags_D1_D2( ARMG_CC_OP_SUB, zero, arg, cond_AND_notInIT_T);
14554 DIP("negs r%u, r%u\n", rD, rM);
14555 goto decode_success;
14559 /* ---------------- MVNS Rd, Rm ---------------- */
14561 UInt rM = INSN0(5,3);
14562 UInt rD = INSN0(2,0);
14563 IRTemp oldV = newTemp(Ity_I32);
14564 IRTemp oldC = newTemp(Ity_I32);
14565 IRTemp res = newTemp(Ity_I32);
14566 assign( oldV, mk_armg_calculate_flag_v() );
14567 assign( oldC, mk_armg_calculate_flag_c() );
14568 assign(res, unop(Iop_Not32, getIRegT(rM)));
14569 // rD can never be r15
14570 putIRegT(rD, mkexpr(res), condT);
14571 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
14572 cond_AND_notInIT_T );
14573 DIP("mvns r%u, r%u\n", rD, rM);
14574 goto decode_success;
14578 /* ---------------- ORRS Rd, Rm ---------------- */
14579 anOp = Iop_Or32; anOpNm = "orr"; goto and_orr_eor_mul;
14581 /* ---------------- ANDS Rd, Rm ---------------- */
14582 anOp = Iop_And32; anOpNm = "and"; goto and_orr_eor_mul;
14584 /* ---------------- EORS Rd, Rm ---------------- */
14585 anOp = Iop_Xor32; anOpNm = "eor"; goto and_orr_eor_mul;
14587 /* ---------------- MULS Rd, Rm ---------------- */
14588 anOp = Iop_Mul32; anOpNm = "mul"; goto and_orr_eor_mul;
14590 /* Rd = Rd `op` Rm */
14591 UInt rM = INSN0(5,3);
14592 UInt rD = INSN0(2,0);
14593 IRTemp res = newTemp(Ity_I32);
14594 IRTemp oldV = newTemp(Ity_I32);
14595 IRTemp oldC = newTemp(Ity_I32);
14596 assign( oldV, mk_armg_calculate_flag_v() );
14597 assign( oldC, mk_armg_calculate_flag_c() );
14598 assign( res, binop(anOp, getIRegT(rD), getIRegT(rM) ));
14599 // not safe to read guest state after here
14600 // rD can never be r15
14601 putIRegT(rD, mkexpr(res), condT);
14602 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
14603 cond_AND_notInIT_T );
14604 DIP("%s r%u, r%u\n", anOpNm, rD, rM);
14605 goto decode_success;
14609 /* ---------------- BICS Rd, Rm ---------------- */
14610 /* Rd = Rd & ~Rm */
14611 UInt rM = INSN0(5,3);
14612 UInt rD = INSN0(2,0);
14613 IRTemp res = newTemp(Ity_I32);
14614 IRTemp oldV = newTemp(Ity_I32);
14615 IRTemp oldC = newTemp(Ity_I32);
14616 assign( oldV, mk_armg_calculate_flag_v() );
14617 assign( oldC, mk_armg_calculate_flag_c() );
14618 assign( res, binop(Iop_And32, getIRegT(rD),
14619 unop(Iop_Not32, getIRegT(rM) )));
14620 // not safe to read guest state after here
14621 // rD can never be r15
14622 putIRegT(rD, mkexpr(res), condT);
14623 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
14624 cond_AND_notInIT_T );
14625 DIP("bics r%u, r%u\n", rD, rM);
14626 goto decode_success;
14630 /* ---------------- ADCS Rd, Rm ---------------- */
14631 /* Rd = Rd + Rm + oldC */
14632 UInt rM = INSN0(5,3);
14633 UInt rD = INSN0(2,0);
14634 IRTemp argL = newTemp(Ity_I32);
14635 IRTemp argR = newTemp(Ity_I32);
14636 IRTemp oldC = newTemp(Ity_I32);
14637 IRTemp res = newTemp(Ity_I32);
14638 assign(argL, getIRegT(rD));
14639 assign(argR, getIRegT(rM));
14640 assign(oldC, mk_armg_calculate_flag_c());
14641 assign(res, binop(Iop_Add32,
14642 binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
14644 // rD can never be r15
14645 putIRegT(rD, mkexpr(res), condT);
14646 setFlags_D1_D2_ND( ARMG_CC_OP_ADC, argL, argR, oldC,
14647 cond_AND_notInIT_T );
14648 DIP("adcs r%u, r%u\n", rD, rM);
14649 goto decode_success;
14653 /* ---------------- SBCS Rd, Rm ---------------- */
14654 /* Rd = Rd - Rm - (oldC ^ 1) */
14655 UInt rM = INSN0(5,3);
14656 UInt rD = INSN0(2,0);
14657 IRTemp argL = newTemp(Ity_I32);
14658 IRTemp argR = newTemp(Ity_I32);
14659 IRTemp oldC = newTemp(Ity_I32);
14660 IRTemp res = newTemp(Ity_I32);
14661 assign(argL, getIRegT(rD));
14662 assign(argR, getIRegT(rM));
14663 assign(oldC, mk_armg_calculate_flag_c());
14664 assign(res, binop(Iop_Sub32,
14665 binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
14666 binop(Iop_Xor32, mkexpr(oldC), mkU32(1))));
14667 // rD can never be r15
14668 putIRegT(rD, mkexpr(res), condT);
14669 setFlags_D1_D2_ND( ARMG_CC_OP_SBB, argL, argR, oldC,
14670 cond_AND_notInIT_T );
14671 DIP("sbcs r%u, r%u\n", rD, rM);
14672 goto decode_success;
14676 /* ---------------- UXTB Rd, Rm ---------------- */
14677 /* Rd = 8Uto32(Rm) */
14678 UInt rM = INSN0(5,3);
14679 UInt rD = INSN0(2,0);
14680 putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFF)),
14682 DIP("uxtb r%u, r%u\n", rD, rM);
14683 goto decode_success;
14687 /* ---------------- SXTB Rd, Rm ---------------- */
14688 /* Rd = 8Sto32(Rm) */
14689 UInt rM = INSN0(5,3);
14690 UInt rD = INSN0(2,0);
14691 putIRegT(rD, binop(Iop_Sar32,
14692 binop(Iop_Shl32, getIRegT(rM), mkU8(24)),
14695 DIP("sxtb r%u, r%u\n", rD, rM);
14696 goto decode_success;
14700 /* ---------------- UXTH Rd, Rm ---------------- */
14701 /* Rd = 16Uto32(Rm) */
14702 UInt rM = INSN0(5,3);
14703 UInt rD = INSN0(2,0);
14704 putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFFFF)),
14706 DIP("uxth r%u, r%u\n", rD, rM);
14707 goto decode_success;
14711 /* ---------------- SXTH Rd, Rm ---------------- */
14712 /* Rd = 16Sto32(Rm) */
14713 UInt rM = INSN0(5,3);
14714 UInt rD = INSN0(2,0);
14715 putIRegT(rD, binop(Iop_Sar32,
14716 binop(Iop_Shl32, getIRegT(rM), mkU8(16)),
14719 DIP("sxth r%u, r%u\n", rD, rM);
14720 goto decode_success;
14723 case 0x102: // LSLS
14724 case 0x103: // LSRS
14725 case 0x104: // ASRS
14726 case 0x107: { // RORS
14727 /* ---------------- LSLS Rs, Rd ---------------- */
14728 /* ---------------- LSRS Rs, Rd ---------------- */
14729 /* ---------------- ASRS Rs, Rd ---------------- */
14730 /* ---------------- RORS Rs, Rd ---------------- */
14731 /* Rd = Rd `op` Rs, and set flags */
14732 UInt rS = INSN0(5,3);
14733 UInt rD = INSN0(2,0);
14734 IRTemp oldV = newTemp(Ity_I32);
14735 IRTemp rDt = newTemp(Ity_I32);
14736 IRTemp rSt = newTemp(Ity_I32);
14737 IRTemp res = newTemp(Ity_I32);
14738 IRTemp resC = newTemp(Ity_I32);
14739 HChar* wot = "???";
14740 assign(rSt, getIRegT(rS));
14741 assign(rDt, getIRegT(rD));
14742 assign(oldV, mk_armg_calculate_flag_v());
14743 /* Does not appear to be the standard 'how' encoding. */
14744 switch (INSN0(15,6)) {
14746 compute_result_and_C_after_LSL_by_reg(
14747 dis_buf, &res, &resC, rDt, rSt, rD, rS
14752 compute_result_and_C_after_LSR_by_reg(
14753 dis_buf, &res, &resC, rDt, rSt, rD, rS
14758 compute_result_and_C_after_ASR_by_reg(
14759 dis_buf, &res, &resC, rDt, rSt, rD, rS
14764 compute_result_and_C_after_ROR_by_reg(
14765 dis_buf, &res, &resC, rDt, rSt, rD, rS
14770 /*NOTREACHED*/vassert(0);
14772 // not safe to read guest state after this point
14773 putIRegT(rD, mkexpr(res), condT);
14774 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
14775 cond_AND_notInIT_T );
14776 DIP("%ss r%u, r%u\n", wot, rS, rD);
14777 goto decode_success;
14781 case 0x2E9: { // REV16
14782 /* ---------------- REV Rd, Rm ---------------- */
14783 /* ---------------- REV16 Rd, Rm ---------------- */
14784 UInt rM = INSN0(5,3);
14785 UInt rD = INSN0(2,0);
14786 Bool isREV = INSN0(15,6) == 0x2E8;
14787 IRTemp arg = newTemp(Ity_I32);
14788 assign(arg, getIRegT(rM));
14789 IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
14790 putIRegT(rD, mkexpr(res), condT);
14791 DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM);
14792 goto decode_success;
14796 break; /* examine the next shortest prefix */
14801 /* ================ 16-bit 15:7 cases ================ */
14803 switch (INSN0(15,7)) {
14805 case BITS9(1,0,1,1,0,0,0,0,0): {
14806 /* ------------ ADD SP, #imm7 * 4 ------------ */
14807 UInt uimm7 = INSN0(6,0);
14808 putIRegT(13, binop(Iop_Add32, getIRegT(13), mkU32(uimm7 * 4)),
14810 DIP("add sp, #%u\n", uimm7 * 4);
14811 goto decode_success;
14814 case BITS9(1,0,1,1,0,0,0,0,1): {
14815 /* ------------ SUB SP, #imm7 * 4 ------------ */
14816 UInt uimm7 = INSN0(6,0);
14817 putIRegT(13, binop(Iop_Sub32, getIRegT(13), mkU32(uimm7 * 4)),
14819 DIP("sub sp, #%u\n", uimm7 * 4);
14820 goto decode_success;
14823 case BITS9(0,1,0,0,0,1,1,1,0): {
14824 /* ---------------- BX rM ---------------- */
14825 /* Branch to reg, and optionally switch modes. Reg contains a
14826 suitably encoded address therefore (w CPSR.T at the bottom).
14827 Have to special-case r15, as usual. */
14828 UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
14829 if (BITS3(0,0,0) == INSN0(2,0)) {
14830 IRTemp dst = newTemp(Ity_I32);
14831 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
14832 mk_skip_over_T16_if_cond_is_false(condT);
14833 condT = IRTemp_INVALID;
14836 assign( dst, getIRegT(rM) );
14839 assign( dst, mkU32(guest_R15_curr_instr_notENC + 4) );
14841 irsb->next = mkexpr(dst);
14842 irsb->jumpkind = Ijk_Boring;
14843 dres.whatNext = Dis_StopHere;
14844 DIP("bx r%u (possibly switch to ARM mode)\n", rM);
14845 goto decode_success;
14850 /* ---------------- BLX rM ---------------- */
14851 /* Branch and link to interworking address in rM. */
14852 case BITS9(0,1,0,0,0,1,1,1,1): {
14853 if (BITS3(0,0,0) == INSN0(2,0)) {
14854 UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
14855 IRTemp dst = newTemp(Ity_I32);
14857 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
14858 mk_skip_over_T16_if_cond_is_false(condT);
14859 condT = IRTemp_INVALID;
14861 /* We're returning to Thumb code, hence "| 1" */
14862 assign( dst, getIRegT(rM) );
14863 putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ),
14865 irsb->next = mkexpr(dst);
14866 irsb->jumpkind = Ijk_Call;
14867 dres.whatNext = Dis_StopHere;
14868 DIP("blx r%u (possibly switch to ARM mode)\n", rM);
14869 goto decode_success;
14871 /* else unpredictable, fall through */
14877 break; /* examine the next shortest prefix */
14882 /* ================ 16-bit 15:8 cases ================ */
14884 switch (INSN0(15,8)) {
14886 case BITS8(1,1,0,1,1,1,1,1): {
14887 /* ---------------- SVC ---------------- */
14888 UInt imm8 = INSN0(7,0);
14890 /* A syscall. We can't do this conditionally, hence: */
14891 mk_skip_over_T16_if_cond_is_false( condT );
14892 // FIXME: what if we have to back up and restart this insn?
14893 // then ITSTATE will be wrong (we'll have it as "used")
14894 // when it isn't. Correct is to save ITSTATE in a
14895 // stash pseudo-reg, and back up from that if we have to
14897 // uncond after here
14898 irsb->next = mkU32( (guest_R15_curr_instr_notENC + 2) | 1 );
14899 irsb->jumpkind = Ijk_Sys_syscall;
14900 dres.whatNext = Dis_StopHere;
14901 DIP("svc #0x%08x\n", imm8);
14902 goto decode_success;
14904 /* else fall through */
14908 case BITS8(0,1,0,0,0,1,0,0): {
14909 /* ---------------- ADD(HI) Rd, Rm ---------------- */
14910 UInt h1 = INSN0(7,7);
14911 UInt h2 = INSN0(6,6);
14912 UInt rM = (h2 << 3) | INSN0(5,3);
14913 UInt rD = (h1 << 3) | INSN0(2,0);
14914 //if (h1 == 0 && h2 == 0) { // Original T1 was more restrictive
14915 if (rD == 15 && rM == 15) {
14916 // then it's invalid
14918 IRTemp res = newTemp(Ity_I32);
14919 assign( res, binop(Iop_Add32, getIRegT(rD), getIRegT(rM) ));
14921 putIRegT( rD, mkexpr(res), condT );
14923 /* Only allowed outside or last-in IT block; SIGILL if not so. */
14924 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
14925 /* jump over insn if not selected */
14926 mk_skip_over_T16_if_cond_is_false(condT);
14927 condT = IRTemp_INVALID;
14929 /* non-interworking branch */
14930 irsb->next = binop(Iop_Or32, mkexpr(res), mkU32(1));
14931 irsb->jumpkind = Ijk_Boring;
14932 dres.whatNext = Dis_StopHere;
14934 DIP("add(hi) r%u, r%u\n", rD, rM);
14935 goto decode_success;
14940 case BITS8(0,1,0,0,0,1,0,1): {
14941 /* ---------------- CMP(HI) Rd, Rm ---------------- */
14942 UInt h1 = INSN0(7,7);
14943 UInt h2 = INSN0(6,6);
14944 UInt rM = (h2 << 3) | INSN0(5,3);
14945 UInt rN = (h1 << 3) | INSN0(2,0);
14946 if (h1 != 0 || h2 != 0) {
14947 IRTemp argL = newTemp(Ity_I32);
14948 IRTemp argR = newTemp(Ity_I32);
14949 assign( argL, getIRegT(rN) );
14950 assign( argR, getIRegT(rM) );
14951 /* Update flags regardless of whether in an IT block or not. */
14952 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
14953 DIP("cmphi r%u, r%u\n", rN, rM);
14954 goto decode_success;
14959 case BITS8(0,1,0,0,0,1,1,0): {
14960 /* ---------------- MOV(HI) Rd, Rm ---------------- */
14961 UInt h1 = INSN0(7,7);
14962 UInt h2 = INSN0(6,6);
14963 UInt rM = (h2 << 3) | INSN0(5,3);
14964 UInt rD = (h1 << 3) | INSN0(2,0);
14965 /* The old ARM ARM seems to disallow the case where both Rd and
14966 Rm are "low" registers, but newer versions allow it. */
14967 if (1 /*h1 != 0 || h2 != 0*/) {
14968 IRTemp val = newTemp(Ity_I32);
14969 assign( val, getIRegT(rM) );
14971 putIRegT( rD, mkexpr(val), condT );
14973 /* Only allowed outside or last-in IT block; SIGILL if not so. */
14974 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
14975 /* jump over insn if not selected */
14976 mk_skip_over_T16_if_cond_is_false(condT);
14977 condT = IRTemp_INVALID;
14979 /* non-interworking branch */
14980 irsb->next = binop(Iop_Or32, mkexpr(val), mkU32(1));
14981 irsb->jumpkind = Ijk_Boring;
14982 dres.whatNext = Dis_StopHere;
14984 DIP("mov r%u, r%u\n", rD, rM);
14985 goto decode_success;
14990 case BITS8(1,0,1,1,1,1,1,1): {
14991 /* ---------------- IT (if-then) ---------------- */
14992 UInt firstcond = INSN0(7,4);
14993 UInt mask = INSN0(3,0);
14994 UInt newITSTATE = 0;
14995 /* This is the ITSTATE represented as described in
14996 libvex_guest_arm.h. It is not the ARM ARM representation. */
15000 Bool valid = compute_ITSTATE( &newITSTATE, &c1, &c2, &c3,
15002 if (valid && firstcond != 0xF/*NV*/) {
15003 /* Not allowed in an IT block; SIGILL if so. */
15004 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
15006 IRTemp t = newTemp(Ity_I32);
15007 assign(t, mkU32(newITSTATE));
15010 DIP("it%c%c%c %s\n", c1, c2, c3, nCC(firstcond));
15011 goto decode_success;
15016 case BITS8(1,0,1,1,0,0,0,1):
15017 case BITS8(1,0,1,1,0,0,1,1):
15018 case BITS8(1,0,1,1,1,0,0,1):
15019 case BITS8(1,0,1,1,1,0,1,1): {
15020 /* ---------------- CB{N}Z ---------------- */
15021 UInt rN = INSN0(2,0);
15022 UInt bOP = INSN0(11,11);
15023 UInt imm32 = (INSN0(9,9) << 6) | (INSN0(7,3) << 1);
15024 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
15025 /* It's a conditional branch forward. */
15026 IRTemp kond = newTemp(Ity_I1);
15027 assign( kond, binop(bOP ? Iop_CmpNE32 : Iop_CmpEQ32,
15028 getIRegT(rN), mkU32(0)) );
15030 vassert(0 == (guest_R15_curr_instr_notENC & 1));
15031 /* Looks like the nearest insn we can branch to is the one after
15032 next. That makes sense, as there's no point in being able to
15033 encode a conditional branch to the next instruction. */
15034 UInt dst = (guest_R15_curr_instr_notENC + 4 + imm32) | 1;
15035 stmt(IRStmt_Exit( mkexpr(kond),
15037 IRConst_U32(toUInt(dst)) ));
15038 DIP("cb%s r%u, 0x%x\n", bOP ? "nz" : "z", rN, dst - 1);
15039 goto decode_success;
15043 break; /* examine the next shortest prefix */
15048 /* ================ 16-bit 15:9 cases ================ */
15050 switch (INSN0(15,9)) {
15052 case BITS7(1,0,1,1,0,1,0): {
15053 /* ---------------- PUSH ---------------- */
15054 /* This is a bit like STMxx, but way simpler. Complications we
15055 don't have to deal with:
15056 * SP being one of the transferred registers
15057 * direction (increment vs decrement)
15058 * before-vs-after-ness
15061 UInt bitR = INSN0(8,8);
15062 UInt regList = INSN0(7,0);
15063 if (bitR) regList |= (1 << 14);
15065 if (regList != 0) {
15066 /* Since we can't generate a guaranteed non-trapping IR
15067 sequence, (1) jump over the insn if it is gated false, and
15068 (2) back out the ITSTATE update. */
15069 mk_skip_over_T16_if_cond_is_false(condT);
15070 condT = IRTemp_INVALID;
15071 put_ITSTATE(old_itstate);
15075 for (i = 0; i < 16; i++) {
15076 if ((regList & (1 << i)) != 0)
15079 vassert(nRegs >= 1 && nRegs <= 8);
15081 /* Move SP down first of all, so we're "covered". And don't
15082 mess with its alignment. */
15083 IRTemp newSP = newTemp(Ity_I32);
15084 assign(newSP, binop(Iop_Sub32, getIRegT(13), mkU32(4 * nRegs)));
15085 putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
15087 /* Generate a transfer base address as a forced-aligned
15088 version of the final SP value. */
15089 IRTemp base = newTemp(Ity_I32);
15090 assign(base, binop(Iop_And32, mkexpr(newSP), mkU32(~3)));
15092 /* Now the transfers */
15094 for (i = 0; i < 16; i++) {
15095 if ((regList & (1 << i)) != 0) {
15096 storeLE( binop(Iop_Add32, mkexpr(base), mkU32(4 * nRegs)),
15102 /* Reinstate the ITSTATE update. */
15103 put_ITSTATE(new_itstate);
15105 DIP("push {%s0x%04x}\n", bitR ? "lr," : "", regList & 0xFF);
15106 goto decode_success;
15111 case BITS7(1,0,1,1,1,1,0): {
15112 /* ---------------- POP ---------------- */
15114 UInt bitR = INSN0(8,8);
15115 UInt regList = INSN0(7,0);
15117 if (regList != 0 || bitR) {
15118 /* Since we can't generate a guaranteed non-trapping IR
15119 sequence, (1) jump over the insn if it is gated false, and
15120 (2) back out the ITSTATE update. */
15121 mk_skip_over_T16_if_cond_is_false(condT);
15122 condT = IRTemp_INVALID;
15123 put_ITSTATE(old_itstate);
15127 for (i = 0; i < 8; i++) {
15128 if ((regList & (1 << i)) != 0)
15131 vassert(nRegs >= 0 && nRegs <= 7);
15132 vassert(bitR == 0 || bitR == 1);
15134 IRTemp oldSP = newTemp(Ity_I32);
15135 assign(oldSP, getIRegT(13));
15137 /* Generate a transfer base address as a forced-aligned
15138 version of the original SP value. */
15139 IRTemp base = newTemp(Ity_I32);
15140 assign(base, binop(Iop_And32, mkexpr(oldSP), mkU32(~3)));
15142 /* Compute a new value for SP, but don't install it yet, so
15143 that we're "covered" until all the transfers are done.
15144 And don't mess with its alignment. */
15145 IRTemp newSP = newTemp(Ity_I32);
15146 assign(newSP, binop(Iop_Add32, mkexpr(oldSP),
15147 mkU32(4 * (nRegs + bitR))));
15149 /* Now the transfers, not including PC */
15151 for (i = 0; i < 8; i++) {
15152 if ((regList & (1 << i)) != 0) {
15153 putIRegT(i, loadLE( Ity_I32,
15154 binop(Iop_Add32, mkexpr(base),
15155 mkU32(4 * nRegs))),
15161 IRTemp newPC = IRTemp_INVALID;
15163 newPC = newTemp(Ity_I32);
15164 assign( newPC, loadLE( Ity_I32,
15165 binop(Iop_Add32, mkexpr(base),
15166 mkU32(4 * nRegs))));
15169 /* Now we can safely install the new SP value */
15170 putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
15172 /* Reinstate the ITSTATE update. */
15173 put_ITSTATE(new_itstate);
15175 /* now, do we also have to do a branch? If so, it turns out
15176 that the new PC value is encoded exactly as we need it to
15177 be -- with CPSR.T in the bottom bit. So we can simply use
15178 it as is, no need to mess with it. Note, therefore, this
15179 is an interworking return. */
15181 irsb->next = mkexpr(newPC);
15182 irsb->jumpkind = Ijk_Ret;
15183 dres.whatNext = Dis_StopHere;
15186 DIP("pop {%s0x%04x}\n", bitR ? "pc," : "", regList & 0xFF);
15187 goto decode_success;
15192 case BITS7(0,0,0,1,1,1,0): /* ADDS */
15193 case BITS7(0,0,0,1,1,1,1): { /* SUBS */
15194 /* ---------------- ADDS Rd, Rn, #uimm3 ---------------- */
15195 /* ---------------- SUBS Rd, Rn, #uimm3 ---------------- */
15196 UInt uimm3 = INSN0(8,6);
15197 UInt rN = INSN0(5,3);
15198 UInt rD = INSN0(2,0);
15199 UInt isSub = INSN0(9,9);
15200 IRTemp argL = newTemp(Ity_I32);
15201 IRTemp argR = newTemp(Ity_I32);
15202 assign( argL, getIRegT(rN) );
15203 assign( argR, mkU32(uimm3) );
15204 putIRegT(rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
15205 mkexpr(argL), mkexpr(argR)),
15207 setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
15208 argL, argR, cond_AND_notInIT_T );
15209 DIP("%s r%u, r%u, #%u\n", isSub ? "subs" : "adds", rD, rN, uimm3);
15210 goto decode_success;
15213 case BITS7(0,0,0,1,1,0,0): /* ADDS */
15214 case BITS7(0,0,0,1,1,0,1): { /* SUBS */
15215 /* ---------------- ADDS Rd, Rn, Rm ---------------- */
15216 /* ---------------- SUBS Rd, Rn, Rm ---------------- */
15217 UInt rM = INSN0(8,6);
15218 UInt rN = INSN0(5,3);
15219 UInt rD = INSN0(2,0);
15220 UInt isSub = INSN0(9,9);
15221 IRTemp argL = newTemp(Ity_I32);
15222 IRTemp argR = newTemp(Ity_I32);
15223 assign( argL, getIRegT(rN) );
15224 assign( argR, getIRegT(rM) );
15225 putIRegT( rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
15226 mkexpr(argL), mkexpr(argR)),
15228 setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
15229 argL, argR, cond_AND_notInIT_T );
15230 DIP("%s r%u, r%u, r%u\n", isSub ? "subs" : "adds", rD, rN, rM);
15231 goto decode_success;
15234 case BITS7(0,1,0,1,0,0,0): /* STR */
15235 case BITS7(0,1,0,1,1,0,0): { /* LDR */
15236 /* ------------- LDR Rd, [Rn, Rm] ------------- */
15237 /* ------------- STR Rd, [Rn, Rm] ------------- */
15238 /* LDR/STR Rd, [Rn + Rm] */
15239 UInt rD = INSN0(2,0);
15240 UInt rN = INSN0(5,3);
15241 UInt rM = INSN0(8,6);
15242 UInt isLD = INSN0(11,11);
15244 mk_skip_over_T16_if_cond_is_false(condT);
15245 condT = IRTemp_INVALID;
15248 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
15249 put_ITSTATE(old_itstate); // backout
15251 putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
15253 storeLE(ea, getIRegT(rD));
15255 put_ITSTATE(new_itstate); // restore
15257 DIP("%s r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
15258 goto decode_success;
15261 case BITS7(0,1,0,1,0,0,1):
15262 case BITS7(0,1,0,1,1,0,1): {
15263 /* ------------- LDRH Rd, [Rn, Rm] ------------- */
15264 /* ------------- STRH Rd, [Rn, Rm] ------------- */
15265 /* LDRH/STRH Rd, [Rn + Rm] */
15266 UInt rD = INSN0(2,0);
15267 UInt rN = INSN0(5,3);
15268 UInt rM = INSN0(8,6);
15269 UInt isLD = INSN0(11,11);
15271 mk_skip_over_T16_if_cond_is_false(condT);
15272 condT = IRTemp_INVALID;
15275 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
15276 put_ITSTATE(old_itstate); // backout
15278 putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
15281 storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
15283 put_ITSTATE(new_itstate); // restore
15285 DIP("%sh r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
15286 goto decode_success;
15289 case BITS7(0,1,0,1,1,1,1): {
15290 /* ------------- LDRSH Rd, [Rn, Rm] ------------- */
15291 /* LDRSH Rd, [Rn + Rm] */
15292 UInt rD = INSN0(2,0);
15293 UInt rN = INSN0(5,3);
15294 UInt rM = INSN0(8,6);
15296 mk_skip_over_T16_if_cond_is_false(condT);
15297 condT = IRTemp_INVALID;
15300 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
15301 put_ITSTATE(old_itstate); // backout
15302 putIRegT(rD, unop(Iop_16Sto32, loadLE(Ity_I16, ea)),
15304 put_ITSTATE(new_itstate); // restore
15306 DIP("ldrsh r%u, [r%u, r%u]\n", rD, rN, rM);
15307 goto decode_success;
15310 case BITS7(0,1,0,1,0,1,1): {
15311 /* ------------- LDRSB Rd, [Rn, Rm] ------------- */
15312 /* LDRSB Rd, [Rn + Rm] */
15313 UInt rD = INSN0(2,0);
15314 UInt rN = INSN0(5,3);
15315 UInt rM = INSN0(8,6);
15317 mk_skip_over_T16_if_cond_is_false(condT);
15318 condT = IRTemp_INVALID;
15321 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
15322 put_ITSTATE(old_itstate); // backout
15323 putIRegT(rD, unop(Iop_8Sto32, loadLE(Ity_I8, ea)),
15325 put_ITSTATE(new_itstate); // restore
15327 DIP("ldrsb r%u, [r%u, r%u]\n", rD, rN, rM);
15328 goto decode_success;
15331 case BITS7(0,1,0,1,0,1,0):
15332 case BITS7(0,1,0,1,1,1,0): {
15333 /* ------------- LDRB Rd, [Rn, Rm] ------------- */
15334 /* ------------- STRB Rd, [Rn, Rm] ------------- */
15335 /* LDRB/STRB Rd, [Rn + Rm] */
15336 UInt rD = INSN0(2,0);
15337 UInt rN = INSN0(5,3);
15338 UInt rM = INSN0(8,6);
15339 UInt isLD = INSN0(11,11);
15341 mk_skip_over_T16_if_cond_is_false(condT);
15342 condT = IRTemp_INVALID;
15345 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
15346 put_ITSTATE(old_itstate); // backout
15348 putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
15351 storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
15353 put_ITSTATE(new_itstate); // restore
15355 DIP("%sb r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
15356 goto decode_success;
15360 break; /* examine the next shortest prefix */
15365 /* ================ 16-bit 15:11 cases ================ */
15367 switch (INSN0(15,11)) {
15369 case BITS5(0,0,1,1,0):
15370 case BITS5(0,0,1,1,1): {
15371 /* ---------------- ADDS Rn, #uimm8 ---------------- */
15372 /* ---------------- SUBS Rn, #uimm8 ---------------- */
15373 UInt isSub = INSN0(11,11);
15374 UInt rN = INSN0(10,8);
15375 UInt uimm8 = INSN0(7,0);
15376 IRTemp argL = newTemp(Ity_I32);
15377 IRTemp argR = newTemp(Ity_I32);
15378 assign( argL, getIRegT(rN) );
15379 assign( argR, mkU32(uimm8) );
15380 putIRegT( rN, binop(isSub ? Iop_Sub32 : Iop_Add32,
15381 mkexpr(argL), mkexpr(argR)), condT );
15382 setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
15383 argL, argR, cond_AND_notInIT_T );
15384 DIP("%s r%u, #%u\n", isSub ? "subs" : "adds", rN, uimm8);
15385 goto decode_success;
15388 case BITS5(1,0,1,0,0): {
15389 /* ---------------- ADD rD, PC, #imm8 * 4 ---------------- */
15391 /* rD = align4(PC) + imm8 * 4 */
15392 UInt rD = INSN0(10,8);
15393 UInt imm8 = INSN0(7,0);
15394 putIRegT(rD, binop(Iop_Add32,
15395 binop(Iop_And32, getIRegT(15), mkU32(~3U)),
15398 DIP("add r%u, pc, #%u\n", rD, imm8 * 4);
15399 goto decode_success;
15402 case BITS5(1,0,1,0,1): {
15403 /* ---------------- ADD rD, SP, #imm8 * 4 ---------------- */
15404 UInt rD = INSN0(10,8);
15405 UInt imm8 = INSN0(7,0);
15406 putIRegT(rD, binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4)),
15408 DIP("add r%u, r13, #%u\n", rD, imm8 * 4);
15409 goto decode_success;
15412 case BITS5(0,0,1,0,1): {
15413 /* ---------------- CMP Rn, #uimm8 ---------------- */
15414 UInt rN = INSN0(10,8);
15415 UInt uimm8 = INSN0(7,0);
15416 IRTemp argL = newTemp(Ity_I32);
15417 IRTemp argR = newTemp(Ity_I32);
15418 assign( argL, getIRegT(rN) );
15419 assign( argR, mkU32(uimm8) );
15420 /* Update flags regardless of whether in an IT block or not. */
15421 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
15422 DIP("cmp r%u, #%u\n", rN, uimm8);
15423 goto decode_success;
15426 case BITS5(0,0,1,0,0): {
15427 /* -------------- (T1) MOVS Rn, #uimm8 -------------- */
15428 UInt rD = INSN0(10,8);
15429 UInt uimm8 = INSN0(7,0);
15430 IRTemp oldV = newTemp(Ity_I32);
15431 IRTemp oldC = newTemp(Ity_I32);
15432 IRTemp res = newTemp(Ity_I32);
15433 assign( oldV, mk_armg_calculate_flag_v() );
15434 assign( oldC, mk_armg_calculate_flag_c() );
15435 assign( res, mkU32(uimm8) );
15436 putIRegT(rD, mkexpr(res), condT);
15437 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
15438 cond_AND_notInIT_T );
15439 DIP("movs r%u, #%u\n", rD, uimm8);
15440 goto decode_success;
15443 case BITS5(0,1,0,0,1): {
15444 /* ------------- LDR Rd, [PC, #imm8 * 4] ------------- */
15445 /* LDR Rd, [align4(PC) + imm8 * 4] */
15446 UInt rD = INSN0(10,8);
15447 UInt imm8 = INSN0(7,0);
15448 IRTemp ea = newTemp(Ity_I32);
15450 mk_skip_over_T16_if_cond_is_false(condT);
15451 condT = IRTemp_INVALID;
15454 assign(ea, binop(Iop_Add32,
15455 binop(Iop_And32, getIRegT(15), mkU32(~3U)),
15457 put_ITSTATE(old_itstate); // backout
15458 putIRegT(rD, loadLE(Ity_I32, mkexpr(ea)),
15460 put_ITSTATE(new_itstate); // restore
15462 DIP("ldr r%u, [pc, #%u]\n", rD, imm8 * 4);
15463 goto decode_success;
15466 case BITS5(0,1,1,0,0): /* STR */
15467 case BITS5(0,1,1,0,1): { /* LDR */
15468 /* ------------- LDR Rd, [Rn, #imm5 * 4] ------------- */
15469 /* ------------- STR Rd, [Rn, #imm5 * 4] ------------- */
15470 /* LDR/STR Rd, [Rn + imm5 * 4] */
15471 UInt rD = INSN0(2,0);
15472 UInt rN = INSN0(5,3);
15473 UInt imm5 = INSN0(10,6);
15474 UInt isLD = INSN0(11,11);
15476 mk_skip_over_T16_if_cond_is_false(condT);
15477 condT = IRTemp_INVALID;
15480 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 4));
15481 put_ITSTATE(old_itstate); // backout
15483 putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
15485 storeLE( ea, getIRegT(rD) );
15487 put_ITSTATE(new_itstate); // restore
15489 DIP("%s r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 4);
15490 goto decode_success;
15493 case BITS5(1,0,0,0,0): /* STRH */
15494 case BITS5(1,0,0,0,1): { /* LDRH */
15495 /* ------------- LDRH Rd, [Rn, #imm5 * 2] ------------- */
15496 /* ------------- STRH Rd, [Rn, #imm5 * 2] ------------- */
15497 /* LDRH/STRH Rd, [Rn + imm5 * 2] */
15498 UInt rD = INSN0(2,0);
15499 UInt rN = INSN0(5,3);
15500 UInt imm5 = INSN0(10,6);
15501 UInt isLD = INSN0(11,11);
15503 mk_skip_over_T16_if_cond_is_false(condT);
15504 condT = IRTemp_INVALID;
15507 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 2));
15508 put_ITSTATE(old_itstate); // backout
15510 putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
15513 storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
15515 put_ITSTATE(new_itstate); // restore
15517 DIP("%sh r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 2);
15518 goto decode_success;
15521 case BITS5(0,1,1,1,0): /* STRB */
15522 case BITS5(0,1,1,1,1): { /* LDRB */
15523 /* ------------- LDRB Rd, [Rn, #imm5] ------------- */
15524 /* ------------- STRB Rd, [Rn, #imm5] ------------- */
15525 /* LDRB/STRB Rd, [Rn + imm5] */
15526 UInt rD = INSN0(2,0);
15527 UInt rN = INSN0(5,3);
15528 UInt imm5 = INSN0(10,6);
15529 UInt isLD = INSN0(11,11);
15531 mk_skip_over_T16_if_cond_is_false(condT);
15532 condT = IRTemp_INVALID;
15535 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5));
15536 put_ITSTATE(old_itstate); // backout
15538 putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
15541 storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
15543 put_ITSTATE(new_itstate); // restore
15545 DIP("%sb r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5);
15546 goto decode_success;
15549 case BITS5(1,0,0,1,0): /* STR */
15550 case BITS5(1,0,0,1,1): { /* LDR */
15551 /* ------------- LDR Rd, [SP, #imm8 * 4] ------------- */
15552 /* ------------- STR Rd, [SP, #imm8 * 4] ------------- */
15553 /* LDR/STR Rd, [SP + imm8 * 4] */
15554 UInt rD = INSN0(10,8);
15555 UInt imm8 = INSN0(7,0);
15556 UInt isLD = INSN0(11,11);
15558 mk_skip_over_T16_if_cond_is_false(condT);
15559 condT = IRTemp_INVALID;
15562 IRExpr* ea = binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4));
15563 put_ITSTATE(old_itstate); // backout
15565 putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
15567 storeLE(ea, getIRegT(rD));
15569 put_ITSTATE(new_itstate); // restore
15571 DIP("%s r%u, [sp, #%u]\n", isLD ? "ldr" : "str", rD, imm8 * 4);
15572 goto decode_success;
15575 case BITS5(1,1,0,0,1): {
15576 /* ------------- LDMIA Rn!, {reglist} ------------- */
15578 UInt rN = INSN0(10,8);
15579 UInt list = INSN0(7,0);
15580 /* Empty lists aren't allowed. */
15582 mk_skip_over_T16_if_cond_is_false(condT);
15583 condT = IRTemp_INVALID;
15584 put_ITSTATE(old_itstate);
15587 IRTemp oldRn = newTemp(Ity_I32);
15588 IRTemp base = newTemp(Ity_I32);
15589 assign(oldRn, getIRegT(rN));
15590 assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
15591 for (i = 0; i < 8; i++) {
15592 if (0 == (list & (1 << i)))
15597 binop(Iop_Add32, mkexpr(base),
15598 mkU32(nRegs * 4 - 4))),
15602 /* Only do the writeback for rN if it isn't in the list of
15603 registers to be transferred. */
15604 if (0 == (list & (1 << rN))) {
15606 binop(Iop_Add32, mkexpr(oldRn),
15612 /* Reinstate the ITSTATE update. */
15613 put_ITSTATE(new_itstate);
15615 DIP("ldmia r%u!, {0x%04x}\n", rN, list);
15616 goto decode_success;
15621 case BITS5(1,1,0,0,0): {
15622 /* ------------- STMIA Rn!, {reglist} ------------- */
15624 UInt rN = INSN0(10,8);
15625 UInt list = INSN0(7,0);
15626 /* Empty lists aren't allowed. Also, if rN is in the list then
15627 it must be the lowest numbered register in the list. */
15628 Bool valid = list != 0;
15629 if (valid && 0 != (list & (1 << rN))) {
15630 for (i = 0; i < rN; i++) {
15631 if (0 != (list & (1 << i)))
15636 mk_skip_over_T16_if_cond_is_false(condT);
15637 condT = IRTemp_INVALID;
15638 put_ITSTATE(old_itstate);
15641 IRTemp oldRn = newTemp(Ity_I32);
15642 IRTemp base = newTemp(Ity_I32);
15643 assign(oldRn, getIRegT(rN));
15644 assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
15645 for (i = 0; i < 8; i++) {
15646 if (0 == (list & (1 << i)))
15649 storeLE( binop(Iop_Add32, mkexpr(base), mkU32(nRegs * 4 - 4)),
15652 /* Always do the writeback. */
15654 binop(Iop_Add32, mkexpr(oldRn),
15658 /* Reinstate the ITSTATE update. */
15659 put_ITSTATE(new_itstate);
15661 DIP("stmia r%u!, {0x%04x}\n", rN, list);
15662 goto decode_success;
15667 case BITS5(0,0,0,0,0): /* LSLS */
15668 case BITS5(0,0,0,0,1): /* LSRS */
15669 case BITS5(0,0,0,1,0): { /* ASRS */
15670 /* ---------------- LSLS Rd, Rm, #imm5 ---------------- */
15671 /* ---------------- LSRS Rd, Rm, #imm5 ---------------- */
15672 /* ---------------- ASRS Rd, Rm, #imm5 ---------------- */
15673 UInt rD = INSN0(2,0);
15674 UInt rM = INSN0(5,3);
15675 UInt imm5 = INSN0(10,6);
15676 IRTemp res = newTemp(Ity_I32);
15677 IRTemp resC = newTemp(Ity_I32);
15678 IRTemp rMt = newTemp(Ity_I32);
15679 IRTemp oldV = newTemp(Ity_I32);
15680 HChar* wot = "???";
15681 assign(rMt, getIRegT(rM));
15682 assign(oldV, mk_armg_calculate_flag_v());
15683 /* Looks like INSN0(12,11) are the standard 'how' encoding.
15684 Could compactify if the ROR case later appears. */
15685 switch (INSN0(15,11)) {
15686 case BITS5(0,0,0,0,0):
15687 compute_result_and_C_after_LSL_by_imm5(
15688 dis_buf, &res, &resC, rMt, imm5, rM
15692 case BITS5(0,0,0,0,1):
15693 compute_result_and_C_after_LSR_by_imm5(
15694 dis_buf, &res, &resC, rMt, imm5, rM
15698 case BITS5(0,0,0,1,0):
15699 compute_result_and_C_after_ASR_by_imm5(
15700 dis_buf, &res, &resC, rMt, imm5, rM
15705 /*NOTREACHED*/vassert(0);
15707 // not safe to read guest state after this point
15708 putIRegT(rD, mkexpr(res), condT);
15709 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
15710 cond_AND_notInIT_T );
15711 /* ignore buf and roll our own output */
15712 DIP("%ss r%u, r%u, #%u\n", wot, rD, rM, imm5);
15713 goto decode_success;
15716 case BITS5(1,1,1,0,0): {
15717 /* ---------------- B #simm11 ---------------- */
15718 Int simm11 = INSN0(10,0);
15719 simm11 = (simm11 << 21) >> 20;
15720 UInt dst = simm11 + guest_R15_curr_instr_notENC + 4;
15721 /* Only allowed outside or last-in IT block; SIGILL if not so. */
15722 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15723 // and skip this insn if not selected; being cleverer is too
15725 mk_skip_over_T16_if_cond_is_false(condT);
15726 condT = IRTemp_INVALID;
15728 irsb->next = mkU32( dst | 1 /*CPSR.T*/ );
15729 irsb->jumpkind = Ijk_Boring;
15730 dres.whatNext = Dis_StopHere;
15731 DIP("b 0x%x\n", dst);
15732 goto decode_success;
15736 break; /* examine the next shortest prefix */
15741 /* ================ 16-bit 15:12 cases ================ */
15743 switch (INSN0(15,12)) {
15745 case BITS4(1,1,0,1): {
15746 /* ---------------- Bcond #simm8 ---------------- */
15747 UInt cond = INSN0(11,8);
15748 Int simm8 = INSN0(7,0);
15749 simm8 = (simm8 << 24) >> 23;
15750 UInt dst = simm8 + guest_R15_curr_instr_notENC + 4;
15751 if (cond != ARMCondAL && cond != ARMCondNV) {
15752 /* Not allowed in an IT block; SIGILL if so. */
15753 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
15755 IRTemp kondT = newTemp(Ity_I32);
15756 assign( kondT, mk_armg_calculate_condition(cond) );
15757 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
15759 IRConst_U32(dst | 1/*CPSR.T*/) ));
15760 irsb->next = mkU32( (guest_R15_curr_instr_notENC + 2)
15762 irsb->jumpkind = Ijk_Boring;
15763 dres.whatNext = Dis_StopHere;
15764 DIP("b%s 0x%x\n", nCC(cond), dst);
15765 goto decode_success;
15771 break; /* hmm, nothing matched */
15775 /* ================ 16-bit misc cases ================ */
15777 /* ------ NOP ------ */
15778 if (INSN0(15,0) == 0xBF00) {
15780 goto decode_success;
15783 /* ----------------------------------------------------------- */
15785 /* -- Thumb 32-bit integer instructions -- */
15787 /* ----------------------------------------------------------- */
15789 # define INSN1(_bMax,_bMin) SLICE_UInt(((UInt)insn1), (_bMax), (_bMin))
15791 /* second 16 bits of the instruction, if any */
15792 UShort insn1 = getUShortLittleEndianly( guest_instr+2 );
15794 anOp = Iop_INVALID; /* paranoia */
15795 anOpNm = NULL; /* paranoia */
15797 /* Change result defaults to suit 32-bit insns. */
15798 vassert(dres.whatNext == Dis_Continue);
15799 vassert(dres.len == 2);
15800 vassert(dres.continueAt == 0);
15803 /* ---------------- BL/BLX simm26 ---------------- */
15804 if (BITS5(1,1,1,1,0) == INSN0(15,11) && BITS2(1,1) == INSN1(15,14)) {
15805 UInt isBL = INSN1(12,12);
15806 UInt bS = INSN0(10,10);
15807 UInt bJ1 = INSN1(13,13);
15808 UInt bJ2 = INSN1(11,11);
15809 UInt bI1 = 1 ^ (bJ1 ^ bS);
15810 UInt bI2 = 1 ^ (bJ2 ^ bS);
15812 = (bS << (1 + 1 + 10 + 11 + 1))
15813 | (bI1 << (1 + 10 + 11 + 1))
15814 | (bI2 << (10 + 11 + 1))
15815 | (INSN0(9,0) << (11 + 1))
15816 | (INSN1(10,0) << 1);
15817 simm25 = (simm25 << 7) >> 7;
15819 vassert(0 == (guest_R15_curr_instr_notENC & 1));
15820 UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
15822 /* One further validity case to check: in the case of BLX
15823 (not-BL), that insn1[0] must be zero. */
15825 if (isBL == 0 && INSN1(0,0) == 1) valid = False;
15827 /* Only allowed outside or last-in IT block; SIGILL if not so. */
15828 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15829 // and skip this insn if not selected; being cleverer is too
15831 mk_skip_over_T32_if_cond_is_false(condT);
15832 condT = IRTemp_INVALID;
15835 /* We're returning to Thumb code, hence "| 1" */
15836 putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 4) | 1 ),
15839 /* BL: unconditional T -> T call */
15840 /* we're calling Thumb code, hence "| 1" */
15841 irsb->next = mkU32( dst | 1 );
15842 DIP("bl 0x%x (stay in Thumb mode)\n", dst);
15844 /* BLX: unconditional T -> A call */
15845 /* we're calling ARM code, hence "& 3" to align to a
15846 valid ARM insn address */
15847 irsb->next = mkU32( dst & ~3 );
15848 DIP("blx 0x%x (switch to ARM mode)\n", dst & ~3);
15850 irsb->jumpkind = Ijk_Call;
15851 dres.whatNext = Dis_StopHere;
15852 goto decode_success;
15856 /* ---------------- {LD,ST}M{IA,DB} ---------------- */
15857 if (0x3a2 == INSN0(15,6) // {LD,ST}MIA
15858 || 0x3a4 == INSN0(15,6)) { // {LD,ST}MDB
15859 UInt bW = INSN0(5,5); /* writeback Rn ? */
15860 UInt bL = INSN0(4,4);
15861 UInt rN = INSN0(3,0);
15862 UInt bP = INSN1(15,15); /* reglist entry for r15 */
15863 UInt bM = INSN1(14,14); /* reglist entry for r14 */
15864 UInt rLmost = INSN1(12,0); /* reglist entry for r0 .. 12 */
15865 UInt rL13 = INSN1(13,13); /* must be zero */
15871 if (INSN0(15,6) == 0x3a4) {
15876 /* detect statically invalid cases, and construct the final
15882 regList = (bP << 15) | (bM << 14) | rLmost;
15883 if (rN == 15) valid = False;
15884 if (popcount32(regList) < 2) valid = False;
15885 if (bP == 1 && bM == 1) valid = False;
15886 if (bW == 1 && (regList & (1<<rN))) valid = False;
15888 regList = (bM << 14) | rLmost;
15889 if (bP == 1) valid = False;
15890 if (rN == 15) valid = False;
15891 if (popcount32(regList) < 2) valid = False;
15892 if (bW == 1 && (regList & (1<<rN))) valid = False;
15893 if (regList & (1<<rN)) {
15895 /* if Rn is in the list, then it must be the
15896 lowest numbered entry */
15897 for (i = 0; i < rN; i++) {
15898 if (regList & (1<<i))
15905 if (bL == 1 && bP == 1) {
15906 // We'll be writing the PC. Hence:
15907 /* Only allowed outside or last-in IT block; SIGILL if not so. */
15908 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15912 mk_skip_over_T32_if_cond_is_false(condT);
15913 condT = IRTemp_INVALID;
15916 /* Generate the IR. This might generate a write to R15, */
15917 mk_ldm_stm(False/*!arm*/, rN, bINC, bBEFORE, bW, bL, regList);
15919 if (bL == 1 && (regList & (1<<15))) {
15920 // If we wrote to R15, we have an interworking return to
15922 irsb->next = llGetIReg(15);
15923 irsb->jumpkind = Ijk_Ret;
15924 dres.whatNext = Dis_StopHere;
15927 DIP("%sm%c%c r%u%s, {0x%04x}\n",
15928 bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
15929 rN, bW ? "!" : "", regList);
15931 goto decode_success;
15935 /* -------------- (T3) ADD{S}.W Rd, Rn, #constT -------------- */
15936 if (INSN0(15,11) == BITS5(1,1,1,1,0)
15937 && INSN0(9,5) == BITS5(0,1,0,0,0)
15938 && INSN1(15,15) == 0) {
15939 UInt bS = INSN0(4,4);
15940 UInt rN = INSN0(3,0);
15941 UInt rD = INSN1(11,8);
15942 Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
15943 /* but allow "add.w reg, sp, #constT" */
15944 if (!valid && rN == 13)
15947 IRTemp argL = newTemp(Ity_I32);
15948 IRTemp argR = newTemp(Ity_I32);
15949 IRTemp res = newTemp(Ity_I32);
15950 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
15951 assign(argL, getIRegT(rN));
15952 assign(argR, mkU32(imm32));
15953 assign(res, binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
15954 putIRegT(rD, mkexpr(res), condT);
15956 setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
15957 DIP("add%s.w r%u, r%u, #%u\n",
15958 bS == 1 ? "s" : "", rD, rN, imm32);
15959 goto decode_success;
15963 /* ---------------- (T2) CMP.W Rn, #constT ---------------- */
15964 /* ---------------- (T2) CMN.W Rn, #constT ---------------- */
15965 if (INSN0(15,11) == BITS5(1,1,1,1,0)
15966 && ( INSN0(9,4) == BITS6(0,1,1,0,1,1) // CMP
15967 || INSN0(9,4) == BITS6(0,1,0,0,0,1)) // CMN
15968 && INSN1(15,15) == 0
15969 && INSN1(11,8) == BITS4(1,1,1,1)) {
15970 UInt rN = INSN0(3,0);
15972 IRTemp argL = newTemp(Ity_I32);
15973 IRTemp argR = newTemp(Ity_I32);
15974 Bool isCMN = INSN0(9,4) == BITS6(0,1,0,0,0,1);
15975 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
15976 assign(argL, getIRegT(rN));
15977 assign(argR, mkU32(imm32));
15978 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
15979 argL, argR, condT );
15980 DIP("%s.w r%u, #%u\n", isCMN ? "cmn" : "cmp", rN, imm32);
15981 goto decode_success;
15985 /* -------------- (T1) TST.W Rn, #constT -------------- */
15986 /* -------------- (T1) TEQ.W Rn, #constT -------------- */
15987 if (INSN0(15,11) == BITS5(1,1,1,1,0)
15988 && ( INSN0(9,4) == BITS6(0,0,0,0,0,1) // TST
15989 || INSN0(9,4) == BITS6(0,0,1,0,0,1)) // TEQ
15990 && INSN1(15,15) == 0
15991 && INSN1(11,8) == BITS4(1,1,1,1)) {
15992 UInt rN = INSN0(3,0);
15993 if (!isBadRegT(rN)) { // yes, really, it's inconsistent with CMP.W
15994 Bool isTST = INSN0(9,4) == BITS6(0,0,0,0,0,1);
15995 IRTemp argL = newTemp(Ity_I32);
15996 IRTemp argR = newTemp(Ity_I32);
15997 IRTemp res = newTemp(Ity_I32);
15998 IRTemp oldV = newTemp(Ity_I32);
15999 IRTemp oldC = newTemp(Ity_I32);
16001 UInt imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
16002 assign(argL, getIRegT(rN));
16003 assign(argR, mkU32(imm32));
16004 assign(res, binop(isTST ? Iop_And32 : Iop_Xor32,
16005 mkexpr(argL), mkexpr(argR)));
16006 assign( oldV, mk_armg_calculate_flag_v() );
16008 ? mkU32((imm32 >> 31) & 1)
16009 : mk_armg_calculate_flag_c() );
16010 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
16011 DIP("%s.w r%u, #%u\n", isTST ? "tst" : "teq", rN, imm32);
16012 goto decode_success;
16016 /* -------------- (T3) SUB{S}.W Rd, Rn, #constT -------------- */
16017 /* -------------- (T3) RSB{S}.W Rd, Rn, #constT -------------- */
16018 if (INSN0(15,11) == BITS5(1,1,1,1,0)
16019 && (INSN0(9,5) == BITS5(0,1,1,0,1) // SUB
16020 || INSN0(9,5) == BITS5(0,1,1,1,0)) // RSB
16021 && INSN1(15,15) == 0) {
16022 Bool isRSB = INSN0(9,5) == BITS5(0,1,1,1,0);
16023 UInt bS = INSN0(4,4);
16024 UInt rN = INSN0(3,0);
16025 UInt rD = INSN1(11,8);
16026 Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
16027 /* but allow "sub{s}.w reg, sp, #constT
16028 this is (T2) of "SUB (SP minus immediate)" */
16029 if (!valid && !isRSB && rN == 13 && rD != 15)
16032 IRTemp argL = newTemp(Ity_I32);
16033 IRTemp argR = newTemp(Ity_I32);
16034 IRTemp res = newTemp(Ity_I32);
16035 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16036 assign(argL, getIRegT(rN));
16037 assign(argR, mkU32(imm32));
16039 ? binop(Iop_Sub32, mkexpr(argR), mkexpr(argL))
16040 : binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
16041 putIRegT(rD, mkexpr(res), condT);
16044 setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
16046 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
16048 DIP("%s%s.w r%u, r%u, #%u\n",
16049 isRSB ? "rsb" : "sub", bS == 1 ? "s" : "", rD, rN, imm32);
16050 goto decode_success;
16054 /* -------------- (T1) ADC{S}.W Rd, Rn, #constT -------------- */
16055 /* -------------- (T1) SBC{S}.W Rd, Rn, #constT -------------- */
16056 if (INSN0(15,11) == BITS5(1,1,1,1,0)
16057 && ( INSN0(9,5) == BITS5(0,1,0,1,0) // ADC
16058 || INSN0(9,5) == BITS5(0,1,0,1,1)) // SBC
16059 && INSN1(15,15) == 0) {
16060 /* ADC: Rd = Rn + constT + oldC */
16061 /* SBC: Rd = Rn - constT - (oldC ^ 1) */
16062 UInt bS = INSN0(4,4);
16063 UInt rN = INSN0(3,0);
16064 UInt rD = INSN1(11,8);
16065 if (!isBadRegT(rN) && !isBadRegT(rD)) {
16066 IRTemp argL = newTemp(Ity_I32);
16067 IRTemp argR = newTemp(Ity_I32);
16068 IRTemp res = newTemp(Ity_I32);
16069 IRTemp oldC = newTemp(Ity_I32);
16070 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16071 assign(argL, getIRegT(rN));
16072 assign(argR, mkU32(imm32));
16073 assign(oldC, mk_armg_calculate_flag_c() );
16075 switch (INSN0(9,5)) {
16076 case BITS5(0,1,0,1,0): // ADC
16080 binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
16082 putIRegT(rD, mkexpr(res), condT);
16084 setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
16085 argL, argR, oldC, condT );
16087 case BITS5(0,1,0,1,1): // SBC
16091 binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
16092 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
16093 putIRegT(rD, mkexpr(res), condT);
16095 setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
16096 argL, argR, oldC, condT );
16101 DIP("%s%s.w r%u, r%u, #%u\n",
16102 nm, bS == 1 ? "s" : "", rD, rN, imm32);
16103 goto decode_success;
16107 /* -------------- (T1) ORR{S}.W Rd, Rn, #constT -------------- */
16108 /* -------------- (T1) AND{S}.W Rd, Rn, #constT -------------- */
16109 /* -------------- (T1) BIC{S}.W Rd, Rn, #constT -------------- */
16110 /* -------------- (T1) EOR{S}.W Rd, Rn, #constT -------------- */
16111 if (INSN0(15,11) == BITS5(1,1,1,1,0)
16112 && ( INSN0(9,5) == BITS5(0,0,0,1,0) // ORR
16113 || INSN0(9,5) == BITS5(0,0,0,0,0) // AND
16114 || INSN0(9,5) == BITS5(0,0,0,0,1) // BIC
16115 || INSN0(9,5) == BITS5(0,0,1,0,0) // EOR
16116 || INSN0(9,5) == BITS5(0,0,0,1,1)) // ORN
16117 && INSN1(15,15) == 0) {
16118 UInt bS = INSN0(4,4);
16119 UInt rN = INSN0(3,0);
16120 UInt rD = INSN1(11,8);
16121 if (!isBadRegT(rN) && !isBadRegT(rD)) {
16122 Bool notArgR = False;
16123 IROp op = Iop_INVALID;
16125 switch (INSN0(9,5)) {
16126 case BITS5(0,0,0,1,0): op = Iop_Or32; nm = "orr"; break;
16127 case BITS5(0,0,0,0,0): op = Iop_And32; nm = "and"; break;
16128 case BITS5(0,0,0,0,1): op = Iop_And32; nm = "bic";
16129 notArgR = True; break;
16130 case BITS5(0,0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
16131 case BITS5(0,0,0,1,1): op = Iop_Or32; nm = "orn";
16132 notArgR = True; break;
16133 default: vassert(0);
16135 IRTemp argL = newTemp(Ity_I32);
16136 IRTemp argR = newTemp(Ity_I32);
16137 IRTemp res = newTemp(Ity_I32);
16139 UInt imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
16140 assign(argL, getIRegT(rN));
16141 assign(argR, mkU32(notArgR ? ~imm32 : imm32));
16142 assign(res, binop(op, mkexpr(argL), mkexpr(argR)));
16143 putIRegT(rD, mkexpr(res), condT);
16145 IRTemp oldV = newTemp(Ity_I32);
16146 IRTemp oldC = newTemp(Ity_I32);
16147 assign( oldV, mk_armg_calculate_flag_v() );
16149 ? mkU32((imm32 >> 31) & 1)
16150 : mk_armg_calculate_flag_c() );
16151 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16154 DIP("%s%s.w r%u, r%u, #%u\n",
16155 nm, bS == 1 ? "s" : "", rD, rN, imm32);
16156 goto decode_success;
16160 /* ---------- (T3) ADD{S}.W Rd, Rn, Rm, {shift} ---------- */
16161 /* ---------- (T3) SUB{S}.W Rd, Rn, Rm, {shift} ---------- */
16162 /* ---------- (T3) RSB{S}.W Rd, Rn, Rm, {shift} ---------- */
16163 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16164 && ( INSN0(8,5) == BITS4(1,0,0,0) // add subopc
16165 || INSN0(8,5) == BITS4(1,1,0,1) // sub subopc
16166 || INSN0(8,5) == BITS4(1,1,1,0)) // rsb subopc
16167 && INSN1(15,15) == 0) {
16168 UInt rN = INSN0(3,0);
16169 UInt rD = INSN1(11,8);
16170 UInt rM = INSN1(3,0);
16171 UInt bS = INSN0(4,4);
16172 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16173 UInt how = INSN1(5,4);
16175 Bool valid = !isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM);
16176 /* but allow "add.w reg, sp, reg w/ no shift
16177 (T3) "ADD (SP plus register) */
16178 if (!valid && INSN0(8,5) == BITS4(1,0,0,0) // add
16179 && rD != 15 && rN == 13 && imm5 == 0 && how == 0) {
16182 /* also allow "sub.w reg, sp, reg w/ no shift
16183 (T1) "SUB (SP minus register) */
16184 if (!valid && INSN0(8,5) == BITS4(1,1,0,1) // sub
16185 && rD != 15 && rN == 13 && imm5 == 0 && how == 0) {
16190 IROp op = Iop_INVALID;
16192 switch (INSN0(8,5)) {
16193 case BITS4(1,0,0,0): op = Iop_Add32; nm = "add"; break;
16194 case BITS4(1,1,0,1): op = Iop_Sub32; nm = "sub"; break;
16195 case BITS4(1,1,1,0): op = Iop_Sub32; nm = "rsb";
16196 swap = True; break;
16197 default: vassert(0);
16200 IRTemp argL = newTemp(Ity_I32);
16201 assign(argL, getIRegT(rN));
16203 IRTemp rMt = newTemp(Ity_I32);
16204 assign(rMt, getIRegT(rM));
16206 IRTemp argR = newTemp(Ity_I32);
16207 compute_result_and_C_after_shift_by_imm5(
16208 dis_buf, &argR, NULL, rMt, how, imm5, rM
16211 IRTemp res = newTemp(Ity_I32);
16213 ? binop(op, mkexpr(argR), mkexpr(argL))
16214 : binop(op, mkexpr(argL), mkexpr(argR)));
16216 putIRegT(rD, mkexpr(res), condT);
16220 setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
16224 setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
16226 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
16233 DIP("%s%s.w r%u, r%u, %s\n",
16234 nm, bS ? "s" : "", rD, rN, dis_buf);
16235 goto decode_success;
16239 /* ---------- (T3) ADC{S}.W Rd, Rn, Rm, {shift} ---------- */
16240 /* ---------- (T2) SBC{S}.W Rd, Rn, Rm, {shift} ---------- */
16241 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16242 && ( INSN0(8,5) == BITS4(1,0,1,0) // adc subopc
16243 || INSN0(8,5) == BITS4(1,0,1,1)) // sbc subopc
16244 && INSN1(15,15) == 0) {
16245 /* ADC: Rd = Rn + shifter_operand + oldC */
16246 /* SBC: Rd = Rn - shifter_operand - (oldC ^ 1) */
16247 UInt rN = INSN0(3,0);
16248 UInt rD = INSN1(11,8);
16249 UInt rM = INSN1(3,0);
16250 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
16251 UInt bS = INSN0(4,4);
16252 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16253 UInt how = INSN1(5,4);
16255 IRTemp argL = newTemp(Ity_I32);
16256 assign(argL, getIRegT(rN));
16258 IRTemp rMt = newTemp(Ity_I32);
16259 assign(rMt, getIRegT(rM));
16261 IRTemp oldC = newTemp(Ity_I32);
16262 assign(oldC, mk_armg_calculate_flag_c());
16264 IRTemp argR = newTemp(Ity_I32);
16265 compute_result_and_C_after_shift_by_imm5(
16266 dis_buf, &argR, NULL, rMt, how, imm5, rM
16270 IRTemp res = newTemp(Ity_I32);
16271 switch (INSN0(8,5)) {
16272 case BITS4(1,0,1,0): // ADC
16276 binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
16278 putIRegT(rD, mkexpr(res), condT);
16280 setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
16281 argL, argR, oldC, condT );
16283 case BITS4(1,0,1,1): // SBC
16287 binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
16288 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
16289 putIRegT(rD, mkexpr(res), condT);
16291 setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
16292 argL, argR, oldC, condT );
16298 DIP("%s%s.w r%u, r%u, %s\n",
16299 nm, bS ? "s" : "", rD, rN, dis_buf);
16300 goto decode_success;
16304 /* ---------- (T3) AND{S}.W Rd, Rn, Rm, {shift} ---------- */
16305 /* ---------- (T3) ORR{S}.W Rd, Rn, Rm, {shift} ---------- */
16306 /* ---------- (T3) EOR{S}.W Rd, Rn, Rm, {shift} ---------- */
16307 /* ---------- (T3) BIC{S}.W Rd, Rn, Rm, {shift} ---------- */
16308 /* ---------- (T1) ORN{S}.W Rd, Rn, Rm, {shift} ---------- */
16309 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16310 && ( INSN0(8,5) == BITS4(0,0,0,0) // and subopc
16311 || INSN0(8,5) == BITS4(0,0,1,0) // orr subopc
16312 || INSN0(8,5) == BITS4(0,1,0,0) // eor subopc
16313 || INSN0(8,5) == BITS4(0,0,0,1) // bic subopc
16314 || INSN0(8,5) == BITS4(0,0,1,1)) // orn subopc
16315 && INSN1(15,15) == 0) {
16316 UInt rN = INSN0(3,0);
16317 UInt rD = INSN1(11,8);
16318 UInt rM = INSN1(3,0);
16319 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
16320 Bool notArgR = False;
16321 IROp op = Iop_INVALID;
16323 switch (INSN0(8,5)) {
16324 case BITS4(0,0,0,0): op = Iop_And32; nm = "and"; break;
16325 case BITS4(0,0,1,0): op = Iop_Or32; nm = "orr"; break;
16326 case BITS4(0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
16327 case BITS4(0,0,0,1): op = Iop_And32; nm = "bic";
16328 notArgR = True; break;
16329 case BITS4(0,0,1,1): op = Iop_Or32; nm = "orn";
16330 notArgR = True; break;
16331 default: vassert(0);
16333 UInt bS = INSN0(4,4);
16334 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16335 UInt how = INSN1(5,4);
16337 IRTemp rNt = newTemp(Ity_I32);
16338 assign(rNt, getIRegT(rN));
16340 IRTemp rMt = newTemp(Ity_I32);
16341 assign(rMt, getIRegT(rM));
16343 IRTemp argR = newTemp(Ity_I32);
16344 IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
16346 compute_result_and_C_after_shift_by_imm5(
16347 dis_buf, &argR, bS ? &oldC : NULL, rMt, how, imm5, rM
16350 IRTemp res = newTemp(Ity_I32);
16352 vassert(op == Iop_And32 || op == Iop_Or32);
16353 assign(res, binop(op, mkexpr(rNt),
16354 unop(Iop_Not32, mkexpr(argR))));
16356 assign(res, binop(op, mkexpr(rNt), mkexpr(argR)));
16359 putIRegT(rD, mkexpr(res), condT);
16361 IRTemp oldV = newTemp(Ity_I32);
16362 assign( oldV, mk_armg_calculate_flag_v() );
16363 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16367 DIP("%s%s.w r%u, r%u, %s\n",
16368 nm, bS ? "s" : "", rD, rN, dis_buf);
16369 goto decode_success;
16373 /* -------------- (T?) LSL{S}.W Rd, Rn, Rm -------------- */
16374 /* -------------- (T?) LSR{S}.W Rd, Rn, Rm -------------- */
16375 /* -------------- (T?) ASR{S}.W Rd, Rn, Rm -------------- */
16376 /* -------------- (T?) ROR{S}.W Rd, Rn, Rm -------------- */
16377 if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,0,0)
16378 && INSN1(15,12) == BITS4(1,1,1,1)
16379 && INSN1(7,4) == BITS4(0,0,0,0)) {
16380 UInt how = INSN0(6,5); // standard encoding
16381 UInt rN = INSN0(3,0);
16382 UInt rD = INSN1(11,8);
16383 UInt rM = INSN1(3,0);
16384 UInt bS = INSN0(4,4);
16385 Bool valid = !isBadRegT(rN) && !isBadRegT(rM) && !isBadRegT(rD);
16386 if (how == 3) valid = False; //ATC
16388 IRTemp rNt = newTemp(Ity_I32);
16389 IRTemp rMt = newTemp(Ity_I32);
16390 IRTemp res = newTemp(Ity_I32);
16391 IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
16392 IRTemp oldV = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
16393 HChar* nms[4] = { "lsl", "lsr", "asr", "ror" };
16394 HChar* nm = nms[how];
16395 assign(rNt, getIRegT(rN));
16396 assign(rMt, getIRegT(rM));
16397 compute_result_and_C_after_shift_by_reg(
16398 dis_buf, &res, bS ? &oldC : NULL,
16399 rNt, how, rMt, rN, rM
16402 assign(oldV, mk_armg_calculate_flag_v());
16403 putIRegT(rD, mkexpr(res), condT);
16405 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16408 DIP("%s%s.w r%u, r%u, r%u\n",
16409 nm, bS ? "s" : "", rD, rN, rM);
16410 goto decode_success;
16414 /* ------------ (T?) MOV{S}.W Rd, Rn, {shift} ------------ */
16415 /* ------------ (T?) MVN{S}.W Rd, Rn, {shift} ------------ */
16416 if ((INSN0(15,0) & 0xFFCF) == 0xEA4F
16417 && INSN1(15,15) == 0) {
16418 UInt rD = INSN1(11,8);
16419 UInt rN = INSN1(3,0);
16420 if (!isBadRegT(rD) && !isBadRegT(rN)) {
16421 UInt bS = INSN0(4,4);
16422 UInt isMVN = INSN0(5,5);
16423 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16424 UInt how = INSN1(5,4);
16426 IRTemp rNt = newTemp(Ity_I32);
16427 assign(rNt, getIRegT(rN));
16429 IRTemp oldRn = newTemp(Ity_I32);
16430 IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
16431 compute_result_and_C_after_shift_by_imm5(
16432 dis_buf, &oldRn, bS ? &oldC : NULL, rNt, how, imm5, rN
16435 IRTemp res = newTemp(Ity_I32);
16436 assign(res, isMVN ? unop(Iop_Not32, mkexpr(oldRn))
16439 putIRegT(rD, mkexpr(res), condT);
16441 IRTemp oldV = newTemp(Ity_I32);
16442 assign( oldV, mk_armg_calculate_flag_v() );
16443 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT);
16445 DIP("%s%s.w r%u, %s\n",
16446 isMVN ? "mvn" : "mov", bS ? "s" : "", rD, dis_buf);
16447 goto decode_success;
16451 /* -------------- (T?) TST.W Rn, Rm, {shift} -------------- */
16452 /* -------------- (T?) TEQ.W Rn, Rm, {shift} -------------- */
16453 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16454 && ( INSN0(8,4) == BITS5(0,0,0,0,1) // TST
16455 || INSN0(8,4) == BITS5(0,1,0,0,1)) // TEQ
16456 && INSN1(15,15) == 0
16457 && INSN1(11,8) == BITS4(1,1,1,1)) {
16458 UInt rN = INSN0(3,0);
16459 UInt rM = INSN1(3,0);
16460 if (!isBadRegT(rN) && !isBadRegT(rM)) {
16461 Bool isTST = INSN0(8,4) == BITS5(0,0,0,0,1);
16463 UInt how = INSN1(5,4);
16464 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16466 IRTemp argL = newTemp(Ity_I32);
16467 assign(argL, getIRegT(rN));
16469 IRTemp rMt = newTemp(Ity_I32);
16470 assign(rMt, getIRegT(rM));
16472 IRTemp argR = newTemp(Ity_I32);
16473 IRTemp oldC = newTemp(Ity_I32);
16474 compute_result_and_C_after_shift_by_imm5(
16475 dis_buf, &argR, &oldC, rMt, how, imm5, rM
16478 IRTemp oldV = newTemp(Ity_I32);
16479 assign( oldV, mk_armg_calculate_flag_v() );
16481 IRTemp res = newTemp(Ity_I32);
16482 assign(res, binop(isTST ? Iop_And32 : Iop_Xor32,
16483 mkexpr(argL), mkexpr(argR)));
16485 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16487 DIP("%s.w r%u, %s\n", isTST ? "tst" : "teq", rN, dis_buf);
16488 goto decode_success;
16492 /* -------------- (T3) CMP.W Rn, Rm, {shift} -------------- */
16493 /* -------------- (T2) CMN.W Rn, Rm, {shift} -------------- */
16494 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16495 && ( INSN0(8,4) == BITS5(1,1,0,1,1) // CMP
16496 || INSN0(8,4) == BITS5(1,0,0,0,1)) // CMN
16497 && INSN1(15,15) == 0
16498 && INSN1(11,8) == BITS4(1,1,1,1)) {
16499 UInt rN = INSN0(3,0);
16500 UInt rM = INSN1(3,0);
16501 if (!isBadRegT(rN) && !isBadRegT(rM)) {
16502 Bool isCMN = INSN0(8,4) == BITS5(1,0,0,0,1);
16503 UInt how = INSN1(5,4);
16504 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16506 IRTemp argL = newTemp(Ity_I32);
16507 assign(argL, getIRegT(rN));
16509 IRTemp rMt = newTemp(Ity_I32);
16510 assign(rMt, getIRegT(rM));
16512 IRTemp argR = newTemp(Ity_I32);
16513 compute_result_and_C_after_shift_by_imm5(
16514 dis_buf, &argR, NULL, rMt, how, imm5, rM
16517 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
16518 argL, argR, condT );
16520 DIP("%s.w r%u, %s\n", isCMN ? "cmn" : "cmp", rN, dis_buf);
16521 goto decode_success;
16525 /* -------------- (T2) MOV{S}.W Rd, #constT -------------- */
16526 /* -------------- (T2) MVN{S}.W Rd, #constT -------------- */
16527 if (INSN0(15,11) == BITS5(1,1,1,1,0)
16528 && ( INSN0(9,5) == BITS5(0,0,0,1,0) // MOV
16529 || INSN0(9,5) == BITS5(0,0,0,1,1)) // MVN
16530 && INSN0(3,0) == BITS4(1,1,1,1)
16531 && INSN1(15,15) == 0) {
16532 UInt rD = INSN1(11,8);
16533 if (!isBadRegT(rD)) {
16535 UInt bS = INSN0(4,4);
16536 Bool isMVN = INSN0(5,5) == 1;
16537 UInt imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
16538 IRTemp res = newTemp(Ity_I32);
16539 assign(res, mkU32(isMVN ? ~imm32 : imm32));
16540 putIRegT(rD, mkexpr(res), condT);
16542 IRTemp oldV = newTemp(Ity_I32);
16543 IRTemp oldC = newTemp(Ity_I32);
16544 assign( oldV, mk_armg_calculate_flag_v() );
16546 ? mkU32((imm32 >> 31) & 1)
16547 : mk_armg_calculate_flag_c() );
16548 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16551 DIP("%s%s.w r%u, #%u\n",
16552 isMVN ? "mvn" : "mov", bS ? "s" : "", rD, imm32);
16553 goto decode_success;
16557 /* -------------- (T3) MOVW Rd, #imm16 -------------- */
16558 if (INSN0(15,11) == BITS5(1,1,1,1,0)
16559 && INSN0(9,4) == BITS6(1,0,0,1,0,0)
16560 && INSN1(15,15) == 0) {
16561 UInt rD = INSN1(11,8);
16562 if (!isBadRegT(rD)) {
16563 UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
16564 | (INSN1(14,12) << 8) | INSN1(7,0);
16565 putIRegT(rD, mkU32(imm16), condT);
16566 DIP("movw r%u, #%u\n", rD, imm16);
16567 goto decode_success;
16571 /* ---------------- MOVT Rd, #imm16 ---------------- */
16572 if (INSN0(15,11) == BITS5(1,1,1,1,0)
16573 && INSN0(9,4) == BITS6(1,0,1,1,0,0)
16574 && INSN1(15,15) == 0) {
16575 UInt rD = INSN1(11,8);
16576 if (!isBadRegT(rD)) {
16577 UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
16578 | (INSN1(14,12) << 8) | INSN1(7,0);
16579 IRTemp res = newTemp(Ity_I32);
16582 binop(Iop_And32, getIRegT(rD), mkU32(0xFFFF)),
16583 mkU32(imm16 << 16)));
16584 putIRegT(rD, mkexpr(res), condT);
16585 DIP("movt r%u, #%u\n", rD, imm16);
16586 goto decode_success;
16590 /* ---------------- LD/ST reg+/-#imm8 ---------------- */
16591 /* Loads and stores of the form:
16592 op Rt, [Rn, #-imm8] or
16593 op Rt, [Rn], #+/-imm8 or
16594 op Rt, [Rn, #+/-imm8]!
16596 ldrb ldrh ldr ldrsb ldrsh
16599 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) && INSN1(11,11) == 1) {
16601 Bool syned = False;
16603 IRType ty = Ity_I8;
16606 switch (INSN0(8,4)) {
16607 case BITS5(0,0,0,0,0): // strb
16608 nm = "strb"; isST = True; break;
16609 case BITS5(0,0,0,0,1): // ldrb
16610 nm = "ldrb"; break;
16611 case BITS5(1,0,0,0,1): // ldrsb
16612 nm = "ldrsb"; syned = True; break;
16613 case BITS5(0,0,0,1,0): // strh
16614 nm = "strh"; ty = Ity_I16; isST = True; break;
16615 case BITS5(0,0,0,1,1): // ldrh
16616 nm = "ldrh"; ty = Ity_I16; break;
16617 case BITS5(1,0,0,1,1): // ldrsh
16618 nm = "ldrsh"; ty = Ity_I16; syned = True; break;
16619 case BITS5(0,0,1,0,0): // str
16620 nm = "str"; ty = Ity_I32; isST = True; break;
16621 case BITS5(0,0,1,0,1):
16622 nm = "ldr"; ty = Ity_I32; break; // ldr
16624 valid = False; break;
16627 UInt rN = INSN0(3,0);
16628 UInt rT = INSN1(15,12);
16629 UInt bP = INSN1(10,10);
16630 UInt bU = INSN1(9,9);
16631 UInt bW = INSN1(8,8);
16632 UInt imm8 = INSN1(7,0);
16633 Bool loadsPC = False;
16636 if (bP == 1 && bU == 1 && bW == 0)
16638 if (bP == 0 && bW == 0)
16642 if (bW == 1 && rN == rT)
16644 if (ty == Ity_I8 || ty == Ity_I16) {
16648 /* ty == Ity_I32 */
16649 if (isST && rT == 15)
16651 if (!isST && rT == 15)
16657 // if it's a branch, it can't happen in the middle of an IT block
16659 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16661 mk_skip_over_T32_if_cond_is_false(condT);
16662 condT = IRTemp_INVALID;
16665 IRTemp preAddr = newTemp(Ity_I32);
16666 assign(preAddr, getIRegT(rN));
16668 IRTemp postAddr = newTemp(Ity_I32);
16669 assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
16670 mkexpr(preAddr), mkU32(imm8)));
16672 IRTemp transAddr = bP == 1 ? postAddr : preAddr;
16676 /* Store. If necessary, update the base register before
16677 the store itself, so that the common idiom of "str rX,
16678 [sp, #-4]!" (store rX at sp-4, then do new sp = sp-4,
16679 a.k.a "push rX") doesn't cause Memcheck to complain
16680 that the access is below the stack pointer. Also, not
16681 updating sp before the store confuses Valgrind's
16682 dynamic stack-extending logic. So do it before the
16683 store. Hence we need to snarf the store data before
16684 doing the basereg update. */
16686 /* get hold of the data to be stored */
16687 IRTemp oldRt = newTemp(Ity_I32);
16688 assign(oldRt, getIRegT(rT));
16690 /* Update Rn if necessary. */
16692 vassert(rN != rT); // assured by validity check above
16693 putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
16696 /* generate the transfer */
16699 storeLE(mkexpr(transAddr),
16700 unop(Iop_32to8, mkexpr(oldRt)));
16703 storeLE(mkexpr(transAddr),
16704 unop(Iop_32to16, mkexpr(oldRt)));
16707 storeLE(mkexpr(transAddr), mkexpr(oldRt));
16717 /* generate the transfer */
16718 IRTemp newRt = newTemp(Ity_I32);
16719 IROp widen = Iop_INVALID;
16722 widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
16724 widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
16730 if (widen == Iop_INVALID) {
16731 assign(newRt, loadLE(ty, mkexpr(transAddr)));
16733 assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
16737 llPutIReg(rT, mkexpr(newRt));
16739 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
16743 /* Presumably this is an interworking branch. */
16744 irsb->next = mkexpr(newRt);
16745 irsb->jumpkind = Ijk_Boring; /* or _Ret ? */
16746 dres.whatNext = Dis_StopHere;
16749 /* Update Rn if necessary. */
16751 vassert(rN != rT); // assured by validity check above
16752 putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
16756 if (bP == 1 && bW == 0) {
16757 DIP("%s.w r%u, [r%u, #%c%u]\n",
16758 nm, rT, rN, bU ? '+' : '-', imm8);
16760 else if (bP == 1 && bW == 1) {
16761 DIP("%s.w r%u, [r%u, #%c%u]!\n",
16762 nm, rT, rN, bU ? '+' : '-', imm8);
16765 vassert(bP == 0 && bW == 1);
16766 DIP("%s.w r%u, [r%u], #%c%u\n",
16767 nm, rT, rN, bU ? '+' : '-', imm8);
16770 goto decode_success;
16774 /* ------------- LD/ST reg+(reg<<imm2) ------------- */
16775 /* Loads and stores of the form:
16776 op Rt, [Rn, Rm, LSL #imm8]
16778 ldrb ldrh ldr ldrsb ldrsh
16781 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)
16782 && INSN1(11,6) == BITS6(0,0,0,0,0,0)) {
16784 Bool syned = False;
16786 IRType ty = Ity_I8;
16789 switch (INSN0(8,4)) {
16790 case BITS5(0,0,0,0,0): // strb
16791 nm = "strb"; isST = True; break;
16792 case BITS5(0,0,0,0,1): // ldrb
16793 nm = "ldrb"; break;
16794 case BITS5(1,0,0,0,1): // ldrsb
16795 nm = "ldrsb"; syned = True; break;
16796 case BITS5(0,0,0,1,0): // strh
16797 nm = "strh"; ty = Ity_I16; isST = True; break;
16798 case BITS5(0,0,0,1,1): // ldrh
16799 nm = "ldrh"; ty = Ity_I16; break;
16800 case BITS5(1,0,0,1,1): // ldrsh
16801 nm = "ldrsh"; ty = Ity_I16; syned = True; break;
16802 case BITS5(0,0,1,0,0): // str
16803 nm = "str"; ty = Ity_I32; isST = True; break;
16804 case BITS5(0,0,1,0,1):
16805 nm = "ldr"; ty = Ity_I32; break; // ldr
16807 valid = False; break;
16810 UInt rN = INSN0(3,0);
16811 UInt rM = INSN1(3,0);
16812 UInt rT = INSN1(15,12);
16813 UInt imm2 = INSN1(5,4);
16814 Bool loadsPC = False;
16816 if (ty == Ity_I8 || ty == Ity_I16) {
16817 /* all 8- and 16-bit load and store cases have the
16818 same exclusion set. */
16819 if (rN == 15 || isBadRegT(rT) || isBadRegT(rM))
16822 vassert(ty == Ity_I32);
16823 if (rN == 15 || isBadRegT(rM))
16825 if (isST && rT == 15)
16827 /* If it is a load and rT is 15, that's only allowable if we
16828 not in an IT block, or are the last in it. Need to insert
16829 a dynamic check for that. */
16830 if (!isST && rT == 15)
16835 // if it's a branch, it can't happen in the middle of an IT block
16837 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16839 mk_skip_over_T32_if_cond_is_false(condT);
16840 condT = IRTemp_INVALID;
16843 IRTemp transAddr = newTemp(Ity_I32);
16847 binop(Iop_Shl32, getIRegT(rM), mkU8(imm2)) ));
16850 IRTemp oldRt = newTemp(Ity_I32);
16851 assign(oldRt, getIRegT(rT));
16854 storeLE(mkexpr(transAddr),
16855 unop(Iop_32to8, mkexpr(oldRt)));
16858 storeLE(mkexpr(transAddr),
16859 unop(Iop_32to16, mkexpr(oldRt)));
16862 storeLE(mkexpr(transAddr), mkexpr(oldRt));
16868 IRTemp newRt = newTemp(Ity_I32);
16869 IROp widen = Iop_INVALID;
16872 widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
16874 widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
16880 if (widen == Iop_INVALID) {
16881 assign(newRt, loadLE(ty, mkexpr(transAddr)));
16883 assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
16886 /* If we're loading the PC, putIRegT will assert. So go
16887 direct via llPutIReg. In all other cases use putIRegT
16888 as it is safer (although could simply use llPutIReg for
16889 _all_ cases here.) */
16892 llPutIReg(rT, mkexpr(newRt));
16894 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
16898 /* Presumably this is an interworking branch. */
16899 irsb->next = mkexpr(newRt);
16900 irsb->jumpkind = Ijk_Boring; /* or _Ret ? */
16901 dres.whatNext = Dis_StopHere;
16905 DIP("%s.w r%u, [r%u, r%u, LSL #%u]\n",
16906 nm, rT, rN, rM, imm2);
16908 goto decode_success;
16912 /* --------------- LD/ST reg+imm12 --------------- */
16913 /* Loads and stores of the form:
16914 op Rt, [Rn, +#imm12]
16916 ldrb ldrh ldr ldrsb ldrsh
16919 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)) {
16921 Bool syned = False;
16923 IRType ty = Ity_I8;
16926 switch (INSN0(8,4)) {
16927 case BITS5(0,1,0,0,0): // strb
16928 nm = "strb"; isST = True; break;
16929 case BITS5(0,1,0,0,1): // ldrb
16930 nm = "ldrb"; break;
16931 case BITS5(1,1,0,0,1): // ldrsb
16932 nm = "ldrsb"; syned = True; break;
16933 case BITS5(0,1,0,1,0): // strh
16934 nm = "strh"; ty = Ity_I16; isST = True; break;
16935 case BITS5(0,1,0,1,1): // ldrh
16936 nm = "ldrh"; ty = Ity_I16; break;
16937 case BITS5(1,1,0,1,1): // ldrsh
16938 nm = "ldrsh"; ty = Ity_I16; syned = True; break;
16939 case BITS5(0,1,1,0,0): // str
16940 nm = "str"; ty = Ity_I32; isST = True; break;
16941 case BITS5(0,1,1,0,1):
16942 nm = "ldr"; ty = Ity_I32; break; // ldr
16944 valid = False; break;
16947 UInt rN = INSN0(3,0);
16948 UInt rT = INSN1(15,12);
16949 UInt imm12 = INSN1(11,0);
16950 Bool loadsPC = False;
16952 if (ty == Ity_I8 || ty == Ity_I16) {
16953 /* all 8- and 16-bit load and store cases have the
16954 same exclusion set. */
16955 if (rN == 15 || isBadRegT(rT))
16958 vassert(ty == Ity_I32);
16960 if (rN == 15 || rT == 15)
16963 /* For a 32-bit load, rT == 15 is only allowable if we not
16964 in an IT block, or are the last in it. Need to insert
16965 a dynamic check for that. Also, in this particular
16966 case, rN == 15 is allowable. In this case however, the
16967 value obtained for rN is (apparently)
16968 "word-align(address of current insn + 4)". */
16975 // if it's a branch, it can't happen in the middle of an IT block
16977 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16979 mk_skip_over_T32_if_cond_is_false(condT);
16980 condT = IRTemp_INVALID;
16983 IRTemp rNt = newTemp(Ity_I32);
16985 vassert(ty == Ity_I32 && !isST);
16986 assign(rNt, binop(Iop_And32, getIRegT(rN), mkU32(~3)));
16988 assign(rNt, getIRegT(rN));
16991 IRTemp transAddr = newTemp(Ity_I32);
16993 binop( Iop_Add32, mkexpr(rNt), mkU32(imm12) ));
16996 IRTemp oldRt = newTemp(Ity_I32);
16997 assign(oldRt, getIRegT(rT));
17000 storeLE(mkexpr(transAddr),
17001 unop(Iop_32to8, mkexpr(oldRt)));
17004 storeLE(mkexpr(transAddr),
17005 unop(Iop_32to16, mkexpr(oldRt)));
17008 storeLE(mkexpr(transAddr), mkexpr(oldRt));
17014 IRTemp newRt = newTemp(Ity_I32);
17015 IROp widen = Iop_INVALID;
17018 widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
17020 widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
17026 if (widen == Iop_INVALID) {
17027 assign(newRt, loadLE(ty, mkexpr(transAddr)));
17029 assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
17031 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
17034 /* Presumably this is an interworking branch. */
17035 irsb->next = mkexpr(newRt);
17036 irsb->jumpkind = Ijk_Boring; /* or _Ret ? */
17037 dres.whatNext = Dis_StopHere;
17041 DIP("%s.w r%u, [r%u, +#%u]\n", nm, rT, rN, imm12);
17043 goto decode_success;
17047 /* -------------- LDRD/STRD reg+/-#imm8 -------------- */
17048 /* Doubleword loads and stores of the form:
17049 ldrd/strd Rt, Rt2, [Rn, #-imm8] or
17050 ldrd/strd Rt, Rt2, [Rn], #+/-imm8 or
17051 ldrd/strd Rt, Rt2, [Rn, #+/-imm8]!
17053 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,0) && INSN0(6,6) == 1) {
17054 UInt bP = INSN0(8,8);
17055 UInt bU = INSN0(7,7);
17056 UInt bW = INSN0(5,5);
17057 UInt bL = INSN0(4,4); // 1: load 0: store
17058 UInt rN = INSN0(3,0);
17059 UInt rT = INSN1(15,12);
17060 UInt rT2 = INSN1(11,8);
17061 UInt imm8 = INSN1(7,0);
17064 if (bP == 0 && bW == 0) valid = False;
17065 if (bW == 1 && (rN == rT || rN == rT2)) valid = False;
17066 if (isBadRegT(rT) || isBadRegT(rT2)) valid = False;
17067 if (rN == 15) valid = False;
17068 if (bL == 1 && rT == rT2) valid = False;
17072 mk_skip_over_T32_if_cond_is_false(condT);
17073 condT = IRTemp_INVALID;
17076 IRTemp preAddr = newTemp(Ity_I32);
17077 assign(preAddr, getIRegT(rN));
17079 IRTemp postAddr = newTemp(Ity_I32);
17080 assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
17081 mkexpr(preAddr), mkU32(imm8 << 2)));
17083 IRTemp transAddr = bP == 1 ? postAddr : preAddr;
17086 IRTemp oldRt = newTemp(Ity_I32);
17087 IRTemp oldRt2 = newTemp(Ity_I32);
17088 assign(oldRt, getIRegT(rT));
17089 assign(oldRt2, getIRegT(rT2));
17090 storeLE(mkexpr(transAddr),
17092 storeLE(binop(Iop_Add32, mkexpr(transAddr), mkU32(4)),
17095 IRTemp newRt = newTemp(Ity_I32);
17096 IRTemp newRt2 = newTemp(Ity_I32);
17099 mkexpr(transAddr)));
17102 binop(Iop_Add32, mkexpr(transAddr), mkU32(4))));
17103 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
17104 putIRegT(rT2, mkexpr(newRt2), IRTemp_INVALID);
17108 putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
17111 HChar* nm = bL ? "ldrd" : "strd";
17113 if (bP == 1 && bW == 0) {
17114 DIP("%s.w r%u, r%u, [r%u, #%c%u]\n",
17115 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17117 else if (bP == 1 && bW == 1) {
17118 DIP("%s.w r%u, r%u, [r%u, #%c%u]!\n",
17119 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17122 vassert(bP == 0 && bW == 1);
17123 DIP("%s.w r%u, r%u, [r%u], #%c%u\n",
17124 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17127 goto decode_success;
17131 /* -------------- (T3) Bcond.W label -------------- */
17132 /* This variant carries its own condition, so can't be part of an
17134 if (INSN0(15,11) == BITS5(1,1,1,1,0)
17135 && INSN1(15,14) == BITS2(1,0)
17136 && INSN1(12,12) == 0) {
17137 UInt cond = INSN0(9,6);
17138 if (cond != ARMCondAL && cond != ARMCondNV) {
17140 = (INSN0(10,10) << (1 + 1 + 6 + 11 + 1))
17141 | (INSN1(11,11) << (1 + 6 + 11 + 1))
17142 | (INSN1(13,13) << (6 + 11 + 1))
17143 | (INSN0(5,0) << (11 + 1))
17144 | (INSN1(10,0) << 1);
17145 simm21 = (simm21 << 11) >> 11;
17147 vassert(0 == (guest_R15_curr_instr_notENC & 1));
17148 UInt dst = simm21 + guest_R15_curr_instr_notENC + 4;
17150 /* Not allowed in an IT block; SIGILL if so. */
17151 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
17153 IRTemp kondT = newTemp(Ity_I32);
17154 assign( kondT, mk_armg_calculate_condition(cond) );
17155 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
17157 IRConst_U32(dst | 1/*CPSR.T*/) ));
17158 irsb->next = mkU32( (guest_R15_curr_instr_notENC + 4)
17160 irsb->jumpkind = Ijk_Boring;
17161 dres.whatNext = Dis_StopHere;
17162 DIP("b%s.w 0x%x\n", nCC(cond), dst);
17163 goto decode_success;
17167 /* ---------------- (T4) B.W label ---------------- */
17168 /* ... whereas this variant doesn't carry its own condition, so it
17169 has to be either unconditional or the conditional by virtue of
17170 being the last in an IT block. The upside is that there's 4
17171 more bits available for the jump offset, so it has a 16-times
17172 greater branch range than the T3 variant. */
17173 if (INSN0(15,11) == BITS5(1,1,1,1,0)
17174 && INSN1(15,14) == BITS2(1,0)
17175 && INSN1(12,12) == 1) {
17177 UInt bS = INSN0(10,10);
17178 UInt bJ1 = INSN1(13,13);
17179 UInt bJ2 = INSN1(11,11);
17180 UInt bI1 = 1 ^ (bJ1 ^ bS);
17181 UInt bI2 = 1 ^ (bJ2 ^ bS);
17183 = (bS << (1 + 1 + 10 + 11 + 1))
17184 | (bI1 << (1 + 10 + 11 + 1))
17185 | (bI2 << (10 + 11 + 1))
17186 | (INSN0(9,0) << (11 + 1))
17187 | (INSN1(10,0) << 1);
17188 simm25 = (simm25 << 7) >> 7;
17190 vassert(0 == (guest_R15_curr_instr_notENC & 1));
17191 UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
17193 /* If in an IT block, must be the last insn. */
17194 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
17197 mk_skip_over_T32_if_cond_is_false(condT);
17198 condT = IRTemp_INVALID;
17202 irsb->next = mkU32( dst | 1 /*CPSR.T*/ );
17203 irsb->jumpkind = Ijk_Boring;
17204 dres.whatNext = Dis_StopHere;
17205 DIP("b.w 0x%x\n", dst);
17206 goto decode_success;
17210 /* ------------------ TBB, TBH ------------------ */
17211 if (INSN0(15,4) == 0xE8D && INSN1(15,5) == 0x780) {
17212 UInt rN = INSN0(3,0);
17213 UInt rM = INSN1(3,0);
17214 UInt bH = INSN1(4,4);
17215 if (bH/*ATC*/ || (rN != 13 && !isBadRegT(rM))) {
17216 /* Must be last or not-in IT block */
17217 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
17219 mk_skip_over_T32_if_cond_is_false(condT);
17220 condT = IRTemp_INVALID;
17225 bH ? binop(Iop_Shl32, getIRegT(rM), mkU8(1))
17228 IRTemp delta = newTemp(Ity_I32);
17230 assign(delta, unop(Iop_16Uto32, loadLE(Ity_I16, ea)));
17232 assign(delta, unop(Iop_8Uto32, loadLE(Ity_I8, ea)));
17239 binop(Iop_Shl32, mkexpr(delta), mkU8(1))
17243 irsb->jumpkind = Ijk_Boring;
17244 dres.whatNext = Dis_StopHere;
17245 DIP("tb%c [r%u, r%u%s]\n",
17246 bH ? 'h' : 'b', rN, rM, bH ? ", LSL #1" : "");
17247 goto decode_success;
17251 /* ------------------ UBFX ------------------ */
17252 /* ------------------ SBFX ------------------ */
17253 /* There's also ARM versions of same, but it doesn't seem worth the
17254 hassle to common up the handling (it's only a couple of C
17256 if ((INSN0(15,4) == 0xF3C // UBFX
17257 || INSN0(15,4) == 0xF34) // SBFX
17258 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
17259 UInt rN = INSN0(3,0);
17260 UInt rD = INSN1(11,8);
17261 UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
17262 UInt wm1 = INSN1(4,0);
17263 UInt msb = lsb + wm1;
17264 if (!isBadRegT(rD) && !isBadRegT(rN) && msb <= 31) {
17265 Bool isU = INSN0(15,4) == 0xF3C;
17266 IRTemp src = newTemp(Ity_I32);
17267 IRTemp tmp = newTemp(Ity_I32);
17268 IRTemp res = newTemp(Ity_I32);
17269 UInt mask = ((1 << wm1) - 1) + (1 << wm1);
17270 vassert(msb >= 0 && msb <= 31);
17271 vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
17273 assign(src, getIRegT(rN));
17274 assign(tmp, binop(Iop_And32,
17275 binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
17277 assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
17278 binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
17281 putIRegT(rD, mkexpr(res), condT);
17283 DIP("%s r%u, r%u, #%u, #%u\n",
17284 isU ? "ubfx" : "sbfx", rD, rN, lsb, wm1 + 1);
17285 goto decode_success;
17289 /* ------------------ UXTB ------------------ */
17290 /* ------------------ UXTH ------------------ */
17291 /* ------------------ SXTB ------------------ */
17292 /* ------------------ SXTH ------------------ */
17293 /* ----------------- UXTB16 ----------------- */
17294 /* ----------------- SXTB16 ----------------- */
17295 /* FIXME: this is an exact duplicate of the ARM version. They
17296 should be commoned up. */
17297 if ((INSN0(15,0) == 0xFA5F // UXTB
17298 || INSN0(15,0) == 0xFA1F // UXTH
17299 || INSN0(15,0) == 0xFA4F // SXTB
17300 || INSN0(15,0) == 0xFA0F // SXTH
17301 || INSN0(15,0) == 0xFA3F // UXTB16
17302 || INSN0(15,0) == 0xFA2F) // SXTB16
17303 && INSN1(15,12) == BITS4(1,1,1,1)
17304 && INSN1(7,6) == BITS2(1,0)) {
17305 UInt rD = INSN1(11,8);
17306 UInt rM = INSN1(3,0);
17307 UInt rot = INSN1(5,4);
17308 if (!isBadRegT(rD) && !isBadRegT(rM)) {
17310 IRTemp srcT = newTemp(Ity_I32);
17311 IRTemp rotT = newTemp(Ity_I32);
17312 IRTemp dstT = newTemp(Ity_I32);
17313 assign(srcT, getIRegT(rM));
17314 assign(rotT, genROR32(srcT, 8 * rot));
17315 switch (INSN0(15,0)) {
17316 case 0xFA5F: // UXTB
17318 assign(dstT, unop(Iop_8Uto32,
17319 unop(Iop_32to8, mkexpr(rotT))));
17321 case 0xFA1F: // UXTH
17323 assign(dstT, unop(Iop_16Uto32,
17324 unop(Iop_32to16, mkexpr(rotT))));
17326 case 0xFA4F: // SXTB
17328 assign(dstT, unop(Iop_8Sto32,
17329 unop(Iop_32to8, mkexpr(rotT))));
17331 case 0xFA0F: // SXTH
17333 assign(dstT, unop(Iop_16Sto32,
17334 unop(Iop_32to16, mkexpr(rotT))));
17336 case 0xFA3F: // UXTB16
17338 assign(dstT, binop(Iop_And32, mkexpr(rotT),
17339 mkU32(0x00FF00FF)));
17341 case 0xFA2F: { // SXTB16
17343 IRTemp lo32 = newTemp(Ity_I32);
17344 IRTemp hi32 = newTemp(Ity_I32);
17345 assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
17346 assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
17352 unop(Iop_32to8, mkexpr(lo32))),
17356 unop(Iop_32to8, mkexpr(hi32))),
17364 putIRegT(rD, mkexpr(dstT), condT);
17365 DIP("%s r%u, r%u, ror #%u\n", nm, rD, rM, 8 * rot);
17366 goto decode_success;
17370 /* -------------- MUL.W Rd, Rn, Rm -------------- */
17371 if (INSN0(15,4) == 0xFB0
17372 && (INSN1(15,0) & 0xF0F0) == 0xF000) {
17373 UInt rN = INSN0(3,0);
17374 UInt rD = INSN1(11,8);
17375 UInt rM = INSN1(3,0);
17376 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
17377 IRTemp res = newTemp(Ity_I32);
17378 assign(res, binop(Iop_Mul32, getIRegT(rN), getIRegT(rM)));
17379 putIRegT(rD, mkexpr(res), condT);
17380 DIP("mul.w r%u, r%u, r%u\n", rD, rN, rM);
17381 goto decode_success;
17385 /* ------------------ {U,S}MULL ------------------ */
17386 if ((INSN0(15,4) == 0xFB8 || INSN0(15,4) == 0xFBA)
17387 && INSN1(7,4) == BITS4(0,0,0,0)) {
17388 UInt isU = INSN0(5,5);
17389 UInt rN = INSN0(3,0);
17390 UInt rDlo = INSN1(15,12);
17391 UInt rDhi = INSN1(11,8);
17392 UInt rM = INSN1(3,0);
17393 if (!isBadRegT(rDhi) && !isBadRegT(rDlo)
17394 && !isBadRegT(rN) && !isBadRegT(rM) && rDlo != rDhi) {
17395 IRTemp res = newTemp(Ity_I64);
17396 assign(res, binop(isU ? Iop_MullU32 : Iop_MullS32,
17397 getIRegT(rN), getIRegT(rM)));
17398 putIRegT( rDhi, unop(Iop_64HIto32, mkexpr(res)), condT );
17399 putIRegT( rDlo, unop(Iop_64to32, mkexpr(res)), condT );
17400 DIP("%cmull r%u, r%u, r%u, r%u\n",
17401 isU ? 'u' : 's', rDlo, rDhi, rN, rM);
17402 goto decode_success;
17406 /* ------------------ ML{A,S} ------------------ */
17407 if (INSN0(15,4) == 0xFB0
17408 && ( INSN1(7,4) == BITS4(0,0,0,0) // MLA
17409 || INSN1(7,4) == BITS4(0,0,0,1))) { // MLS
17410 UInt rN = INSN0(3,0);
17411 UInt rA = INSN1(15,12);
17412 UInt rD = INSN1(11,8);
17413 UInt rM = INSN1(3,0);
17414 if (!isBadRegT(rD) && !isBadRegT(rN)
17415 && !isBadRegT(rM) && !isBadRegT(rA)) {
17416 Bool isMLA = INSN1(7,4) == BITS4(0,0,0,0);
17417 IRTemp res = newTemp(Ity_I32);
17419 binop(isMLA ? Iop_Add32 : Iop_Sub32,
17421 binop(Iop_Mul32, getIRegT(rN), getIRegT(rM))));
17422 putIRegT(rD, mkexpr(res), condT);
17423 DIP("%s r%u, r%u, r%u, r%u\n",
17424 isMLA ? "mla" : "mls", rD, rN, rM, rA);
17425 goto decode_success;
17429 /* ------------------ (T3) ADR ------------------ */
17430 if ((INSN0(15,0) == 0xF20F || INSN0(15,0) == 0xF60F)
17431 && INSN1(15,15) == 0) {
17432 /* rD = align4(PC) + imm32 */
17433 UInt rD = INSN1(11,8);
17434 if (!isBadRegT(rD)) {
17435 UInt imm32 = (INSN0(10,10) << 11)
17436 | (INSN1(14,12) << 8) | INSN1(7,0);
17437 putIRegT(rD, binop(Iop_Add32,
17438 binop(Iop_And32, getIRegT(15), mkU32(~3U)),
17441 DIP("add r%u, pc, #%u\n", rD, imm32);
17442 goto decode_success;
17446 /* ----------------- (T1) UMLAL ----------------- */
17447 /* ----------------- (T1) SMLAL ----------------- */
17448 if ((INSN0(15,4) == 0xFBE // UMLAL
17449 || INSN0(15,4) == 0xFBC) // SMLAL
17450 && INSN1(7,4) == BITS4(0,0,0,0)) {
17451 UInt rN = INSN0(3,0);
17452 UInt rDlo = INSN1(15,12);
17453 UInt rDhi = INSN1(11,8);
17454 UInt rM = INSN1(3,0);
17455 if (!isBadRegT(rDlo) && !isBadRegT(rDhi) && !isBadRegT(rN)
17456 && !isBadRegT(rM) && rDhi != rDlo) {
17457 Bool isS = INSN0(15,4) == 0xFBC;
17458 IRTemp argL = newTemp(Ity_I32);
17459 IRTemp argR = newTemp(Ity_I32);
17460 IRTemp old = newTemp(Ity_I64);
17461 IRTemp res = newTemp(Ity_I64);
17462 IRTemp resHi = newTemp(Ity_I32);
17463 IRTemp resLo = newTemp(Ity_I32);
17464 IROp mulOp = isS ? Iop_MullS32 : Iop_MullU32;
17465 assign( argL, getIRegT(rM));
17466 assign( argR, getIRegT(rN));
17467 assign( old, binop(Iop_32HLto64, getIRegT(rDhi), getIRegT(rDlo)) );
17468 assign( res, binop(Iop_Add64,
17470 binop(mulOp, mkexpr(argL), mkexpr(argR))) );
17471 assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
17472 assign( resLo, unop(Iop_64to32, mkexpr(res)) );
17473 putIRegT( rDhi, mkexpr(resHi), condT );
17474 putIRegT( rDlo, mkexpr(resLo), condT );
17475 DIP("%cmlal r%u, r%u, r%u, r%u\n",
17476 isS ? 's' : 'u', rDlo, rDhi, rN, rM);
17477 goto decode_success;
17481 /* ------------------ (T2) ADR ------------------ */
17482 if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF)
17483 && INSN1(15,15) == 0) {
17484 /* rD = align4(PC) - imm32 */
17485 UInt rD = INSN1(11,8);
17486 if (!isBadRegT(rD)) {
17487 UInt imm32 = (INSN0(10,10) << 11)
17488 | (INSN1(14,12) << 8) | INSN1(7,0);
17489 putIRegT(rD, binop(Iop_Sub32,
17490 binop(Iop_And32, getIRegT(15), mkU32(~3U)),
17493 DIP("sub r%u, pc, #%u\n", rD, imm32);
17494 goto decode_success;
17498 /* ------------------- (T1) BFI ------------------- */
17499 /* ------------------- (T1) BFC ------------------- */
17500 if (INSN0(15,4) == 0xF36 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
17501 UInt rD = INSN1(11,8);
17502 UInt rN = INSN0(3,0);
17503 UInt msb = INSN1(4,0);
17504 UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
17505 if (isBadRegT(rD) || rN == 13 || msb < lsb) {
17506 /* undecodable; fall through */
17508 IRTemp src = newTemp(Ity_I32);
17509 IRTemp olddst = newTemp(Ity_I32);
17510 IRTemp newdst = newTemp(Ity_I32);
17511 UInt mask = 1 << (msb - lsb);
17512 mask = (mask - 1) + mask;
17513 vassert(mask != 0); // guaranteed by "msb < lsb" check above
17516 assign(src, rN == 15 ? mkU32(0) : getIRegT(rN));
17517 assign(olddst, getIRegT(rD));
17521 binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
17528 putIRegT(rD, mkexpr(newdst), condT);
17531 DIP("bfc r%u, #%u, #%u\n",
17532 rD, lsb, msb-lsb+1);
17534 DIP("bfi r%u, r%u, #%u, #%u\n",
17535 rD, rN, lsb, msb-lsb+1);
17537 goto decode_success;
17541 /* ------------------- (T1) SXTAH ------------------- */
17542 /* ------------------- (T1) UXTAH ------------------- */
17543 if ((INSN0(15,4) == 0xFA1 // UXTAH
17544 || INSN0(15,4) == 0xFA0) // SXTAH
17545 && INSN1(15,12) == BITS4(1,1,1,1)
17546 && INSN1(7,6) == BITS2(1,0)) {
17547 Bool isU = INSN0(15,4) == 0xFA1;
17548 UInt rN = INSN0(3,0);
17549 UInt rD = INSN1(11,8);
17550 UInt rM = INSN1(3,0);
17551 UInt rot = INSN1(5,4);
17552 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
17553 IRTemp srcL = newTemp(Ity_I32);
17554 IRTemp srcR = newTemp(Ity_I32);
17555 IRTemp res = newTemp(Ity_I32);
17556 assign(srcR, getIRegT(rM));
17557 assign(srcL, getIRegT(rN));
17558 assign(res, binop(Iop_Add32,
17560 unop(isU ? Iop_16Uto32 : Iop_16Sto32,
17562 genROR32(srcR, 8 * rot)))));
17563 putIRegT(rD, mkexpr(res), condT);
17564 DIP("%cxtah r%u, r%u, r%u, ror #%u\n",
17565 isU ? 'u' : 's', rD, rN, rM, rot);
17566 goto decode_success;
17570 /* ------------------- (T1) SXTAB ------------------- */
17571 /* ------------------- (T1) UXTAB ------------------- */
17572 if ((INSN0(15,4) == 0xFA5 // UXTAB
17573 || INSN0(15,4) == 0xFA4) // SXTAB
17574 && INSN1(15,12) == BITS4(1,1,1,1)
17575 && INSN1(7,6) == BITS2(1,0)) {
17576 Bool isU = INSN0(15,4) == 0xFA5;
17577 UInt rN = INSN0(3,0);
17578 UInt rD = INSN1(11,8);
17579 UInt rM = INSN1(3,0);
17580 UInt rot = INSN1(5,4);
17581 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
17582 IRTemp srcL = newTemp(Ity_I32);
17583 IRTemp srcR = newTemp(Ity_I32);
17584 IRTemp res = newTemp(Ity_I32);
17585 assign(srcR, getIRegT(rM));
17586 assign(srcL, getIRegT(rN));
17587 assign(res, binop(Iop_Add32,
17589 unop(isU ? Iop_8Uto32 : Iop_8Sto32,
17591 genROR32(srcR, 8 * rot)))));
17592 putIRegT(rD, mkexpr(res), condT);
17593 DIP("%cxtab r%u, r%u, r%u, ror #%u\n",
17594 isU ? 'u' : 's', rD, rN, rM, rot);
17595 goto decode_success;
17599 /* ------------------- (T1) CLZ ------------------- */
17600 if (INSN0(15,4) == 0xFAB
17601 && INSN1(15,12) == BITS4(1,1,1,1)
17602 && INSN1(7,4) == BITS4(1,0,0,0)) {
17603 UInt rM1 = INSN0(3,0);
17604 UInt rD = INSN1(11,8);
17605 UInt rM2 = INSN1(3,0);
17606 if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
17607 IRTemp arg = newTemp(Ity_I32);
17608 IRTemp res = newTemp(Ity_I32);
17609 assign(arg, getIRegT(rM1));
17610 assign(res, IRExpr_Mux0X(
17611 unop(Iop_1Uto8,binop(Iop_CmpEQ32,
17614 unop(Iop_Clz32, mkexpr(arg)),
17617 putIRegT(rD, mkexpr(res), condT);
17618 DIP("clz r%u, r%u\n", rD, rM1);
17619 goto decode_success;
17623 /* ------------------- (T1) RBIT ------------------- */
17624 if (INSN0(15,4) == 0xFA9
17625 && INSN1(15,12) == BITS4(1,1,1,1)
17626 && INSN1(7,4) == BITS4(1,0,1,0)) {
17627 UInt rM1 = INSN0(3,0);
17628 UInt rD = INSN1(11,8);
17629 UInt rM2 = INSN1(3,0);
17630 if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
17631 IRTemp arg = newTemp(Ity_I32);
17632 assign(arg, getIRegT(rM1));
17633 IRTemp res = gen_BITREV(arg);
17634 putIRegT(rD, mkexpr(res), condT);
17635 DIP("rbit r%u, r%u\n", rD, rM1);
17636 goto decode_success;
17640 /* ------------------- (T2) REV ------------------- */
17641 /* ------------------- (T2) REV16 ------------------- */
17642 if (INSN0(15,4) == 0xFA9
17643 && INSN1(15,12) == BITS4(1,1,1,1)
17644 && ( INSN1(7,4) == BITS4(1,0,0,0) // REV
17645 || INSN1(7,4) == BITS4(1,0,0,1))) { // REV16
17646 UInt rM1 = INSN0(3,0);
17647 UInt rD = INSN1(11,8);
17648 UInt rM2 = INSN1(3,0);
17649 Bool isREV = INSN1(7,4) == BITS4(1,0,0,0);
17650 if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
17651 IRTemp arg = newTemp(Ity_I32);
17652 assign(arg, getIRegT(rM1));
17653 IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
17654 putIRegT(rD, mkexpr(res), condT);
17655 DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM1);
17656 goto decode_success;
17660 /* -------------- (T1) MSR apsr, reg -------------- */
17661 if (INSN0(15,4) == 0xF38
17662 && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) {
17663 UInt rN = INSN0(3,0);
17664 UInt write_ge = INSN1(10,10);
17665 UInt write_nzcvq = INSN1(11,11);
17666 if (!isBadRegT(rN) && (write_nzcvq || write_ge)) {
17667 IRTemp rNt = newTemp(Ity_I32);
17668 assign(rNt, getIRegT(rN));
17669 desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
17670 DIP("msr cpsr_%s%s, r%u\n",
17671 write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
17672 goto decode_success;
17676 /* -------------- (T1) MRS reg, apsr -------------- */
17677 if (INSN0(15,0) == 0xF3EF
17678 && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(7,0) == 0x00) {
17679 UInt rD = INSN1(11,8);
17680 if (!isBadRegT(rD)) {
17681 IRTemp apsr = synthesise_APSR();
17682 putIRegT( rD, mkexpr(apsr), condT );
17683 DIP("mrs r%u, cpsr\n", rD);
17684 goto decode_success;
17688 /* ----------------- (T1) LDREX ----------------- */
17689 if (INSN0(15,4) == 0xE85 && INSN1(11,8) == BITS4(1,1,1,1)) {
17690 UInt rN = INSN0(3,0);
17691 UInt rT = INSN1(15,12);
17692 UInt imm8 = INSN1(7,0);
17693 if (!isBadRegT(rT) && rN != 15) {
17696 mk_skip_over_T32_if_cond_is_false( condT );
17698 res = newTemp(Ity_I32);
17699 stmt( IRStmt_LLSC(Iend_LE,
17701 binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
17702 NULL/*this is a load*/ ));
17703 putIRegT(rT, mkexpr(res), IRTemp_INVALID);
17704 DIP("ldrex r%u, [r%u, #+%u]\n", rT, rN, imm8 * 4);
17705 goto decode_success;
17709 /* ----------------- (T1) STREX ----------------- */
17710 if (INSN0(15,4) == 0xE84) {
17711 UInt rN = INSN0(3,0);
17712 UInt rT = INSN1(15,12);
17713 UInt rD = INSN1(11,8);
17714 UInt imm8 = INSN1(7,0);
17715 if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15
17716 && rD != rN && rD != rT) {
17717 IRTemp resSC1, resSC32;
17720 mk_skip_over_T32_if_cond_is_false( condT );
17723 /* Ok, now we're unconditional. Do the store. */
17724 resSC1 = newTemp(Ity_I1);
17725 stmt( IRStmt_LLSC(Iend_LE,
17727 binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
17730 /* Set rD to 1 on failure, 0 on success. Currently we have
17731 resSC1 == 0 on failure, 1 on success. */
17732 resSC32 = newTemp(Ity_I32);
17734 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
17736 putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
17737 DIP("strex r%u, r%u, [r%u, #+%u]\n", rD, rT, rN, imm8 * 4);
17738 goto decode_success;
17742 /* -------------- v7 barrier insns -------------- */
17743 if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) {
17744 /* XXX this isn't really right, is it? The generated IR does
17745 them unconditionally. I guess it doesn't matter since it
17746 doesn't do any harm to do them even when the guarding
17747 condition is false -- it's just a performance loss. */
17748 switch (INSN1(7,0)) {
17749 case 0x4F: /* DSB sy */
17750 case 0x4E: /* DSB st */
17751 case 0x4B: /* DSB ish */
17752 case 0x4A: /* DSB ishst */
17753 case 0x47: /* DSB nsh */
17754 case 0x46: /* DSB nshst */
17755 case 0x43: /* DSB osh */
17756 case 0x42: /* DSB oshst */
17757 stmt( IRStmt_MBE(Imbe_Fence) );
17759 goto decode_success;
17760 case 0x5F: /* DMB sy */
17761 case 0x5E: /* DMB st */
17762 case 0x5B: /* DMB ish */
17763 case 0x5A: /* DMB ishst */
17764 case 0x57: /* DMB nsh */
17765 case 0x56: /* DMB nshst */
17766 case 0x53: /* DMB osh */
17767 case 0x52: /* DMB oshst */
17768 stmt( IRStmt_MBE(Imbe_Fence) );
17770 goto decode_success;
17771 case 0x6F: /* ISB */
17772 stmt( IRStmt_MBE(Imbe_Fence) );
17774 goto decode_success;
17780 /* -------------- read CP15 TPIDRURO register ------------- */
17781 /* mrc p15, 0, r0, c13, c0, 3 up to
17782 mrc p15, 0, r14, c13, c0, 3
17784 /* I don't know whether this is really v7-only. But anyway, we
17785 have to support it since arm-linux uses TPIDRURO as a thread
17788 if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) {
17789 UInt rD = INSN1(15,12);
17790 if (!isBadRegT(rD)) {
17791 putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), IRTemp_INVALID);
17792 DIP("mrc p15,0, r%u, c13, c0, 3\n", rD);
17793 goto decode_success;
17798 /* ------------------- NOP ------------------ */
17799 if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) {
17801 goto decode_success;
17804 /* ----------------------------------------------------------- */
17805 /* -- VFP (CP 10, CP 11) instructions (in Thumb mode) -- */
17806 /* ----------------------------------------------------------- */
17808 if (INSN0(15,12) == BITS4(1,1,1,0)) {
17809 UInt insn28 = (INSN0(11,0) << 16) | INSN1(15,0);
17810 Bool ok_vfp = decode_CP10_CP11_instruction (
17811 &dres, insn28, condT, ARMCondAL/*bogus*/,
17815 goto decode_success;
17818 /* ----------------------------------------------------------- */
17819 /* -- NEON instructions (in Thumb mode) -- */
17820 /* ----------------------------------------------------------- */
17822 if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
17823 UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
17824 Bool ok_neon = decode_NEON_instruction(
17825 &dres, insn32, condT, True/*isT*/
17828 goto decode_success;
17831 /* ----------------------------------------------------------- */
17832 /* -- v6 media instructions (in Thumb mode) -- */
17833 /* ----------------------------------------------------------- */
17835 { UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
17836 Bool ok_v6m = decode_V6MEDIA_instruction(
17837 &dres, insn32, condT, ARMCondAL/*bogus*/,
17841 goto decode_success;
17844 /* ----------------------------------------------------------- */
17845 /* -- Undecodable -- */
17846 /* ----------------------------------------------------------- */
17848 goto decode_failure;
17852 /* All decode failures end up here. */
17853 vex_printf("disInstr(thumb): unhandled instruction: "
17854 "0x%04x 0x%04x\n", (UInt)insn0, (UInt)insn1);
17856 /* Back up ITSTATE to the initial value for this instruction.
17857 If we don't do that, any subsequent restart of the instruction
17858 will restart with the wrong value. */
17859 put_ITSTATE(old_itstate);
17860 /* Tell the dispatcher that this insn cannot be decoded, and so has
17861 not been executed, and (is currently) the next to be executed.
17862 R15 should be up-to-date since it made so at the start of each
17863 insn, but nevertheless be paranoid and update it again right
17865 vassert(0 == (guest_R15_curr_instr_notENC & 1));
17866 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) );
17867 irsb->next = mkU32(guest_R15_curr_instr_notENC | 1 /* CPSR.T */);
17868 irsb->jumpkind = Ijk_NoDecode;
17869 dres.whatNext = Dis_StopHere;
17874 /* All decode successes end up here. */
17877 vassert(dres.len == 2 || dres.len == 4 || dres.len == 20);
17880 // XXX is this necessary on Thumb?
17881 /* Now then. Do we have an implicit jump to r15 to deal with? */
17883 /* If we get jump to deal with, we assume that there's been no
17884 other competing branch stuff previously generated for this
17885 insn. That's reasonable, in the sense that the ARM insn set
17886 appears to declare as "Unpredictable" any instruction which
17887 generates more than one possible new value for r15. Hence
17888 just assert. The decoders themselves should check against
17889 all such instructions which are thusly Unpredictable, and
17890 decline to decode them. Hence we should never get here if we
17891 have competing new values for r15, and hence it is safe to
17893 vassert(dres.whatNext == Dis_Continue);
17894 vassert(irsb->next == NULL);
17895 vassert(irsb->jumpkind == Ijk_Boring);
17896 /* If r15 is unconditionally written, terminate the block by
17897 jumping to it. If it's conditionally written, still
17898 terminate the block (a shame, but we can't do side exits to
17899 arbitrary destinations), but first jump to the next
17900 instruction if the condition doesn't hold. */
17901 /* We can't use getIRegT(15) to get the destination, since that
17902 will produce r15+4, which isn't what we want. Must use
17903 llGetIReg(15) instead. */
17904 if (r15guard == IRTemp_INVALID) {
17905 /* unconditional */
17911 mkexpr(r15guard), mkU32(1))),
17913 IRConst_U32(guest_R15_curr_instr_notENC + 4)
17916 irsb->next = llGetIReg(15);
17917 irsb->jumpkind = r15kind;
17918 dres.whatNext = Dis_StopHere;
17932 /*------------------------------------------------------------*/
17933 /*--- Top-level fn ---*/
17934 /*------------------------------------------------------------*/
17936 /* Disassemble a single instruction into IR. The instruction
17937 is located in host memory at &guest_code[delta]. */
17939 DisResult disInstr_ARM ( IRSB* irsb_IN,
17941 Bool (*resteerOkFn) ( void*, Addr64 ),
17943 void* callback_opaque,
17944 UChar* guest_code_IN,
17945 Long delta_ENCODED,
17946 Addr64 guest_IP_ENCODED,
17947 VexArch guest_arch,
17948 VexArchInfo* archinfo,
17949 VexAbiInfo* abiinfo,
17950 Bool host_bigendian_IN )
17953 Bool isThumb = (Bool)(guest_IP_ENCODED & 1);
17955 /* Set globals (see top of this file) */
17956 vassert(guest_arch == VexArchARM);
17959 host_is_bigendian = host_bigendian_IN;
17960 __curr_is_Thumb = isThumb;
17963 guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED - 1;
17965 guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED;
17969 dres = disInstr_THUMB_WRK ( put_IP, resteerOkFn,
17970 resteerCisOk, callback_opaque,
17971 &guest_code_IN[delta_ENCODED - 1],
17972 archinfo, abiinfo );
17974 dres = disInstr_ARM_WRK ( put_IP, resteerOkFn,
17975 resteerCisOk, callback_opaque,
17976 &guest_code_IN[delta_ENCODED],
17977 archinfo, abiinfo );
17983 /* Test program for the conversion of IRCmpF64Result values to VFP
17984 nzcv values. See handling of FCMPD et al above. */
17986 UInt foo ( UInt x )
17988 UInt ix = ((x >> 5) & 3) | (x & 1);
17989 UInt termL = (((((ix ^ 1) << 30) - 1) >> 29) + 1);
17990 UInt termR = (ix & (ix >> 1) & 1);
17991 return termL - termR;
17994 void try ( char* s, UInt ir, UInt req )
17996 UInt act = foo(ir);
17997 printf("%s 0x%02x -> req %d%d%d%d act %d%d%d%d (0x%x)\n",
17998 s, ir, (req >> 3) & 1, (req >> 2) & 1,
17999 (req >> 1) & 1, (req >> 0) & 1,
18000 (act >> 3) & 1, (act >> 2) & 1,
18001 (act >> 1) & 1, (act >> 0) & 1, act);
18008 try("UN", 0x45, 0b0011);
18009 try("LT", 0x01, 0b1000);
18010 try("GT", 0x00, 0b0010);
18011 try("EQ", 0x40, 0b0110);
18017 /*--------------------------------------------------------------------*/
18018 /*--- end guest_arm_toIR.c ---*/
18019 /*--------------------------------------------------------------------*/