1 2 /*--------------------------------------------------------------------*/ 3 /*--- begin guest_arm_toIR.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2004-2012 OpenWorks LLP 11 info (at) open-works.net 12 13 NEON support is 14 Copyright (C) 2010-2012 Samsung Electronics 15 contributed by Dmitry Zhurikhin <zhur (at) ispras.ru> 16 and Kirill Batuzov <batuzovk (at) ispras.ru> 17 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. 22 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. 27 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 31 02110-1301, USA. 32 33 The GNU General Public License is contained in the file COPYING. 34 */ 35 36 /* XXXX thumb to check: 37 that all cases where putIRegT writes r15, we generate a jump. 38 39 All uses of newTemp assign to an IRTemp and not a UInt 40 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). 45 46 VFP on thumb: check that we exclude all r13/r15 cases that we 47 should. 48 49 XXXX thumb to do: improve the ITSTATE-zeroing optimisation by 50 taking into account the number of insns guarded by an IT. 51 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. 55 56 add specialisations for armg_calculate_flag_c and _v, as they 57 are moderately often needed in Thumb code. 58 59 Correctness: ITSTATE handling in Thumb SVCs is wrong. 60 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. 66 */ 67 68 /* Limitations, etc 69 70 - pretty dodgy exception semantics for {LD,ST}Mxx, no doubt 71 72 - SWP: the restart jump back is Ijk_Boring; it should be 73 Ijk_NoRedir but that's expensive. See comments on casLE() in 74 guest_x86_toIR.c. 75 */ 76 77 /* "Special" instructions. 78 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: 83 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) 87 88 Following that, one of the following 3 are allowed 89 (standard interpretation in parentheses): 90 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 94 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. 99 */ 100 101 /* Translates ARM(v5) code to IR. */ 102 103 #include "libvex_basictypes.h" 104 #include "libvex_ir.h" 105 #include "libvex.h" 106 #include "libvex_guest_arm.h" 107 108 #include "main_util.h" 109 #include "main_globals.h" 110 #include "guest_generic_bb_to_IR.h" 111 #include "guest_arm_defs.h" 112 113 114 /*------------------------------------------------------------*/ 115 /*--- Globals ---*/ 116 /*------------------------------------------------------------*/ 117 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. 121 */ 122 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 125 out. */ 126 static Bool host_is_bigendian; 127 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; 132 133 /* CONST, FOR ASSERTIONS ONLY. Indicates whether currently processed 134 insn is Thumb (True) or ARM (False). */ 135 static Bool __curr_is_Thumb; 136 137 /* MOD: The IRSB* into which we're generating code. */ 138 static IRSB* irsb; 139 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. */ 148 149 /* MOD. Initially False; set to True iff abovementioned handling is 150 required. */ 151 static Bool r15written; 152 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 156 IRTemp_INVALID. */ 157 static IRTemp r15guard; /* :: Ity_I32, 0 or 1 */ 158 159 /* MOD. Initially Ijk_Boring. If an r15 branch is to be generated, 160 this holds the jump kind. */ 161 static IRTemp r15kind; 162 163 164 /*------------------------------------------------------------*/ 165 /*--- Debugging output ---*/ 166 /*------------------------------------------------------------*/ 167 168 #define DIP(format, args...) \ 169 if (vex_traceflags & VEX_TRACE_FE) \ 170 vex_printf(format, ## args) 171 172 #define DIS(buf, format, args...) \ 173 if (vex_traceflags & VEX_TRACE_FE) \ 174 vex_sprintf(buf, format, ## args) 175 176 #define ASSERT_IS_THUMB \ 177 do { vassert(__curr_is_Thumb); } while (0) 178 179 #define ASSERT_IS_ARM \ 180 do { vassert(! __curr_is_Thumb); } while (0) 181 182 183 /*------------------------------------------------------------*/ 184 /*--- Helper bits and pieces for deconstructing the ---*/ 185 /*--- arm insn stream. ---*/ 186 /*------------------------------------------------------------*/ 187 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 ) 191 { 192 UInt w = 0; 193 w = (w << 8) | p[3]; 194 w = (w << 8) | p[2]; 195 w = (w << 8) | p[1]; 196 w = (w << 8) | p[0]; 197 return w; 198 } 199 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 ) 203 { 204 UShort w = 0; 205 w = (w << 8) | p[1]; 206 w = (w << 8) | p[0]; 207 return w; 208 } 209 210 static UInt ROR32 ( UInt x, UInt sh ) { 211 vassert(sh >= 0 && sh < 32); 212 if (sh == 0) 213 return x; 214 else 215 return (x << (32-sh)) | (x >> sh); 216 } 217 218 static Int popcount32 ( UInt x ) 219 { 220 Int res = 0, i; 221 for (i = 0; i < 32; i++) { 222 res += (x & 1); 223 x >>= 1; 224 } 225 return res; 226 } 227 228 static UInt setbit32 ( UInt x, Int ix, UInt b ) 229 { 230 UInt mask = 1 << ix; 231 x &= ~mask; 232 x |= ((b << ix) & mask); 233 return x; 234 } 235 236 #define BITS2(_b1,_b0) \ 237 (((_b1) << 1) | (_b0)) 238 239 #define BITS3(_b2,_b1,_b0) \ 240 (((_b2) << 2) | ((_b1) << 1) | (_b0)) 241 242 #define BITS4(_b3,_b2,_b1,_b0) \ 243 (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0)) 244 245 #define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \ 246 ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \ 247 | BITS4((_b3),(_b2),(_b1),(_b0))) 248 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))) 255 256 #define BITS9(_b8,_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \ 257 (((_b8) << 8) \ 258 | BITS8((_b7),(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0))) 259 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))) 263 264 /* produces _uint[_bMax:_bMin] */ 265 #define SLICE_UInt(_uint,_bMax,_bMin) \ 266 (( ((UInt)(_uint)) >> (_bMin)) \ 267 & (UInt)((1ULL << ((_bMax) - (_bMin) + 1)) - 1ULL)) 268 269 270 /*------------------------------------------------------------*/ 271 /*--- Helper bits and pieces for creating IR fragments. ---*/ 272 /*------------------------------------------------------------*/ 273 274 static IRExpr* mkU64 ( ULong i ) 275 { 276 return IRExpr_Const(IRConst_U64(i)); 277 } 278 279 static IRExpr* mkU32 ( UInt i ) 280 { 281 return IRExpr_Const(IRConst_U32(i)); 282 } 283 284 static IRExpr* mkU8 ( UInt i ) 285 { 286 vassert(i < 256); 287 return IRExpr_Const(IRConst_U8( (UChar)i )); 288 } 289 290 static IRExpr* mkexpr ( IRTemp tmp ) 291 { 292 return IRExpr_RdTmp(tmp); 293 } 294 295 static IRExpr* unop ( IROp op, IRExpr* a ) 296 { 297 return IRExpr_Unop(op, a); 298 } 299 300 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 301 { 302 return IRExpr_Binop(op, a1, a2); 303 } 304 305 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 306 { 307 return IRExpr_Triop(op, a1, a2, a3); 308 } 309 310 static IRExpr* loadLE ( IRType ty, IRExpr* addr ) 311 { 312 return IRExpr_Load(Iend_LE, ty, addr); 313 } 314 315 /* Add a statement to the list held by "irbb". */ 316 static void stmt ( IRStmt* st ) 317 { 318 addStmtToIRSB( irsb, st ); 319 } 320 321 static void assign ( IRTemp dst, IRExpr* e ) 322 { 323 stmt( IRStmt_WrTmp(dst, e) ); 324 } 325 326 static void storeLE ( IRExpr* addr, IRExpr* data ) 327 { 328 stmt( IRStmt_Store(Iend_LE, addr, data) ); 329 } 330 331 /* Generate a new temporary of the given type. */ 332 static IRTemp newTemp ( IRType ty ) 333 { 334 vassert(isPlausibleIRType(ty)); 335 return newIRTemp( irsb->tyenv, ty ); 336 } 337 338 /* Produces a value in 0 .. 3, which is encoded as per the type 339 IRRoundingMode. */ 340 static IRExpr* /* :: Ity_I32 */ get_FAKE_roundingmode ( void ) 341 { 342 return mkU32(Irrm_NEAREST); 343 } 344 345 /* Generate an expression for SRC rotated right by ROT. */ 346 static IRExpr* genROR32( IRTemp src, Int rot ) 347 { 348 vassert(rot >= 0 && rot < 32); 349 if (rot == 0) 350 return mkexpr(src); 351 return 352 binop(Iop_Or32, 353 binop(Iop_Shl32, mkexpr(src), mkU8(32 - rot)), 354 binop(Iop_Shr32, mkexpr(src), mkU8(rot))); 355 } 356 357 static IRExpr* mkU128 ( ULong i ) 358 { 359 return binop(Iop_64HLtoV128, mkU64(i), mkU64(i)); 360 } 361 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 ) 365 { 366 if (b) 367 return binop(Iop_And32, e, mkU32(~3)); 368 else 369 return e; 370 } 371 372 373 /*------------------------------------------------------------*/ 374 /*--- Helpers for accessing guest registers. ---*/ 375 /*------------------------------------------------------------*/ 376 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) 393 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) 399 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) 432 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) 441 442 443 /* ---------------- Integer registers ---------------- */ 444 445 static Int integerGuestRegOffset ( UInt iregNo ) 446 { 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 449 ARM. */ 450 switch (iregNo) { 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; 467 default: vassert(0); 468 } 469 } 470 471 /* Plain ("low level") read from a reg; no +8 offset magic for r15. */ 472 static IRExpr* llGetIReg ( UInt iregNo ) 473 { 474 vassert(iregNo < 16); 475 return IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 ); 476 } 477 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 ) 481 { 482 IRExpr* e; 483 ASSERT_IS_ARM; 484 vassert(iregNo < 16); 485 if (iregNo == 15) { 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); 494 } else { 495 e = IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 ); 496 } 497 return e; 498 } 499 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 ) 503 { 504 IRExpr* e; 505 ASSERT_IS_THUMB; 506 vassert(iregNo < 16); 507 if (iregNo == 15) { 508 /* Ditto comment in getIReg. */ 509 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 510 e = mkU32(guest_R15_curr_instr_notENC + 4); 511 } else { 512 e = IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 ); 513 } 514 return e; 515 } 516 517 /* Plain ("low level") write to a reg; no jump or alignment magic for 518 r15. */ 519 static void llPutIReg ( UInt iregNo, IRExpr* e ) 520 { 521 vassert(iregNo < 16); 522 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32); 523 stmt( IRStmt_Put(integerGuestRegOffset(iregNo), e) ); 524 } 525 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, 532 IRExpr* e, 533 IRTemp guardT /* :: Ity_I32, 0 or 1 */, 534 IRJumpKind jk /* if a jump is generated */ ) 535 { 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? 540 //if (iregNo == 15) 541 // e = binop(Iop_And32, e, mkU32(~3)); 542 ASSERT_IS_ARM; 543 /* So, generate either an unconditional or a conditional write to 544 the reg. */ 545 if (guardT == IRTemp_INVALID) { 546 /* unconditional write */ 547 llPutIReg( iregNo, e ); 548 } else { 549 llPutIReg( iregNo, 550 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)), 551 llGetIReg(iregNo), 552 e )); 553 } 554 if (iregNo == 15) { 555 // assert against competing r15 updates. Shouldn't 556 // happen; should be ruled out by the instr matching 557 // logic. 558 vassert(r15written == False); 559 vassert(r15guard == IRTemp_INVALID); 560 vassert(r15kind == Ijk_Boring); 561 r15written = True; 562 r15guard = guardT; 563 r15kind = jk; 564 } 565 } 566 567 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, 572 IRExpr* e, 573 IRTemp guardT /* :: Ity_I32, 0 or 1 */ ) 574 { 575 /* So, generate either an unconditional or a conditional write to 576 the reg. */ 577 ASSERT_IS_THUMB; 578 vassert(iregNo >= 0 && iregNo <= 14); 579 if (guardT == IRTemp_INVALID) { 580 /* unconditional write */ 581 llPutIReg( iregNo, e ); 582 } else { 583 llPutIReg( iregNo, 584 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)), 585 llGetIReg(iregNo), 586 e )); 587 } 588 } 589 590 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 ) 595 { 596 vassert(r <= 15); 597 ASSERT_IS_THUMB; 598 return r == 13 || r == 15; 599 } 600 601 602 /* ---------------- Double registers ---------------- */ 603 604 static Int doubleGuestRegOffset ( UInt dregNo ) 605 { 606 /* Do we care about endianness here? Probably do if we ever get 607 into the situation of dealing with the single-precision VFP 608 registers. */ 609 switch (dregNo) { 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; 642 default: vassert(0); 643 } 644 } 645 646 /* Plain ("low level") read from a VFP Dreg. */ 647 static IRExpr* llGetDReg ( UInt dregNo ) 648 { 649 vassert(dregNo < 32); 650 return IRExpr_Get( doubleGuestRegOffset(dregNo), Ity_F64 ); 651 } 652 653 /* Architected read from a VFP Dreg. */ 654 static IRExpr* getDReg ( UInt dregNo ) { 655 return llGetDReg( dregNo ); 656 } 657 658 /* Plain ("low level") write to a VFP Dreg. */ 659 static void llPutDReg ( UInt dregNo, IRExpr* e ) 660 { 661 vassert(dregNo < 32); 662 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 663 stmt( IRStmt_Put(doubleGuestRegOffset(dregNo), e) ); 664 } 665 666 /* Architected write to a VFP Dreg. Handles conditional writes to the 667 register: if guardT == IRTemp_INVALID then the write is 668 unconditional. */ 669 static void putDReg ( UInt dregNo, 670 IRExpr* e, 671 IRTemp guardT /* :: Ity_I32, 0 or 1 */) 672 { 673 /* So, generate either an unconditional or a conditional write to 674 the reg. */ 675 if (guardT == IRTemp_INVALID) { 676 /* unconditional write */ 677 llPutDReg( dregNo, e ); 678 } else { 679 llPutDReg( dregNo, 680 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)), 681 llGetDReg(dregNo), 682 e )); 683 } 684 } 685 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 688 ops. */ 689 690 /* Plain ("low level") read from a Neon Integer Dreg. */ 691 static IRExpr* llGetDRegI64 ( UInt dregNo ) 692 { 693 vassert(dregNo < 32); 694 return IRExpr_Get( doubleGuestRegOffset(dregNo), Ity_I64 ); 695 } 696 697 /* Architected read from a Neon Integer Dreg. */ 698 static IRExpr* getDRegI64 ( UInt dregNo ) { 699 return llGetDRegI64( dregNo ); 700 } 701 702 /* Plain ("low level") write to a Neon Integer Dreg. */ 703 static void llPutDRegI64 ( UInt dregNo, IRExpr* e ) 704 { 705 vassert(dregNo < 32); 706 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64); 707 stmt( IRStmt_Put(doubleGuestRegOffset(dregNo), e) ); 708 } 709 710 /* Architected write to a Neon Integer Dreg. Handles conditional 711 writes to the register: if guardT == IRTemp_INVALID then the write 712 is unconditional. */ 713 static void putDRegI64 ( UInt dregNo, 714 IRExpr* e, 715 IRTemp guardT /* :: Ity_I32, 0 or 1 */) 716 { 717 /* So, generate either an unconditional or a conditional write to 718 the reg. */ 719 if (guardT == IRTemp_INVALID) { 720 /* unconditional write */ 721 llPutDRegI64( dregNo, e ); 722 } else { 723 llPutDRegI64( dregNo, 724 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)), 725 llGetDRegI64(dregNo), 726 e )); 727 } 728 } 729 730 /* ---------------- Quad registers ---------------- */ 731 732 static Int quadGuestRegOffset ( UInt qregNo ) 733 { 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. */ 736 switch (qregNo) { 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; 753 default: vassert(0); 754 } 755 } 756 757 /* Plain ("low level") read from a Neon Qreg. */ 758 static IRExpr* llGetQReg ( UInt qregNo ) 759 { 760 vassert(qregNo < 16); 761 return IRExpr_Get( quadGuestRegOffset(qregNo), Ity_V128 ); 762 } 763 764 /* Architected read from a Neon Qreg. */ 765 static IRExpr* getQReg ( UInt qregNo ) { 766 return llGetQReg( qregNo ); 767 } 768 769 /* Plain ("low level") write to a Neon Qreg. */ 770 static void llPutQReg ( UInt qregNo, IRExpr* e ) 771 { 772 vassert(qregNo < 16); 773 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 774 stmt( IRStmt_Put(quadGuestRegOffset(qregNo), e) ); 775 } 776 777 /* Architected write to a Neon Qreg. Handles conditional writes to the 778 register: if guardT == IRTemp_INVALID then the write is 779 unconditional. */ 780 static void putQReg ( UInt qregNo, 781 IRExpr* e, 782 IRTemp guardT /* :: Ity_I32, 0 or 1 */) 783 { 784 /* So, generate either an unconditional or a conditional write to 785 the reg. */ 786 if (guardT == IRTemp_INVALID) { 787 /* unconditional write */ 788 llPutQReg( qregNo, e ); 789 } else { 790 llPutQReg( qregNo, 791 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)), 792 llGetQReg(qregNo), 793 e )); 794 } 795 } 796 797 798 /* ---------------- Float registers ---------------- */ 799 800 static Int floatGuestRegOffset ( UInt fregNo ) 801 { 802 /* Start with the offset of the containing double, and then correct 803 for endianness. Actually this is completely bogus and needs 804 careful thought. */ 805 Int off; 806 vassert(fregNo < 32); 807 off = doubleGuestRegOffset(fregNo >> 1); 808 if (host_is_bigendian) { 809 vassert(0); 810 } else { 811 if (fregNo & 1) 812 off += 4; 813 } 814 return off; 815 } 816 817 /* Plain ("low level") read from a VFP Freg. */ 818 static IRExpr* llGetFReg ( UInt fregNo ) 819 { 820 vassert(fregNo < 32); 821 return IRExpr_Get( floatGuestRegOffset(fregNo), Ity_F32 ); 822 } 823 824 /* Architected read from a VFP Freg. */ 825 static IRExpr* getFReg ( UInt fregNo ) { 826 return llGetFReg( fregNo ); 827 } 828 829 /* Plain ("low level") write to a VFP Freg. */ 830 static void llPutFReg ( UInt fregNo, IRExpr* e ) 831 { 832 vassert(fregNo < 32); 833 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F32); 834 stmt( IRStmt_Put(floatGuestRegOffset(fregNo), e) ); 835 } 836 837 /* Architected write to a VFP Freg. Handles conditional writes to the 838 register: if guardT == IRTemp_INVALID then the write is 839 unconditional. */ 840 static void putFReg ( UInt fregNo, 841 IRExpr* e, 842 IRTemp guardT /* :: Ity_I32, 0 or 1 */) 843 { 844 /* So, generate either an unconditional or a conditional write to 845 the reg. */ 846 if (guardT == IRTemp_INVALID) { 847 /* unconditional write */ 848 llPutFReg( fregNo, e ); 849 } else { 850 llPutFReg( fregNo, 851 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)), 852 llGetFReg(fregNo), 853 e )); 854 } 855 } 856 857 858 /* ---------------- Misc registers ---------------- */ 859 860 static void putMiscReg32 ( UInt gsoffset, 861 IRExpr* e, /* :: Ity_I32 */ 862 IRTemp guardT /* :: Ity_I32, 0 or 1 */) 863 { 864 switch (gsoffset) { 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 */ 872 } 873 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32); 874 875 if (guardT == IRTemp_INVALID) { 876 /* unconditional write */ 877 stmt(IRStmt_Put(gsoffset, e)); 878 } else { 879 stmt(IRStmt_Put( 880 gsoffset, 881 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)), 882 IRExpr_Get(gsoffset, Ity_I32), 883 e 884 ) 885 )); 886 } 887 } 888 889 static IRTemp get_ITSTATE ( void ) 890 { 891 ASSERT_IS_THUMB; 892 IRTemp t = newTemp(Ity_I32); 893 assign(t, IRExpr_Get( OFFB_ITSTATE, Ity_I32)); 894 return t; 895 } 896 897 static void put_ITSTATE ( IRTemp t ) 898 { 899 ASSERT_IS_THUMB; 900 stmt( IRStmt_Put( OFFB_ITSTATE, mkexpr(t)) ); 901 } 902 903 static IRTemp get_QFLAG32 ( void ) 904 { 905 IRTemp t = newTemp(Ity_I32); 906 assign(t, IRExpr_Get( OFFB_QFLAG32, Ity_I32)); 907 return t; 908 } 909 910 static void put_QFLAG32 ( IRTemp t, IRTemp condT ) 911 { 912 putMiscReg32( OFFB_QFLAG32, mkexpr(t), condT ); 913 } 914 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 ) 920 { 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); 925 } 926 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 */ 940 IRTemp condT ) 941 { 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))); 949 950 switch (flagNo) { 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; 955 default: vassert(0); 956 } 957 } 958 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 */ ) 962 { 963 switch (flagNo) { 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 ); 968 default: vassert(0); 969 } 970 } 971 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 ) 976 { 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 ); 985 } 986 987 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 ) 992 { 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 ); 1005 } 1006 1007 1008 /* ---------------- FPSCR stuff ---------------- */ 1009 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 1012 returned temp. */ 1013 static IRTemp /* :: Ity_I32 */ mk_get_IR_rounding_mode ( void ) 1014 { 1015 /* The ARMvfp encoding for rounding mode bits is: 1016 00 to nearest 1017 01 to +infinity 1018 10 to -infinity 1019 11 to zero 1020 We need to convert that to the IR encoding: 1021 00 to nearest (the default) 1022 10 to +infinity 1023 01 to -infinity 1024 11 to zero 1025 Which can be done by swapping bits 0 and 1. 1026 The rmode bits are at 23:22 in FPSCR. 1027 */ 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. */ 1033 assign(armEncd, 1034 binop(Iop_Shr32, IRExpr_Get(OFFB_FPSCR, Ity_I32), mkU8(22))); 1035 /* Now swap them. */ 1036 assign(swapped, 1037 binop(Iop_Or32, 1038 binop(Iop_And32, 1039 binop(Iop_Shl32, mkexpr(armEncd), mkU8(1)), 1040 mkU32(2)), 1041 binop(Iop_And32, 1042 binop(Iop_Shr32, mkexpr(armEncd), mkU8(1)), 1043 mkU32(1)) 1044 )); 1045 return swapped; 1046 } 1047 1048 1049 /*------------------------------------------------------------*/ 1050 /*--- Helpers for flag handling and conditional insns ---*/ 1051 /*------------------------------------------------------------*/ 1052 1053 static HChar* name_ARMCondcode ( ARMCondcode cond ) 1054 { 1055 switch (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"); 1073 } 1074 } 1075 /* and a handy shorthand for it */ 1076 static HChar* nCC ( ARMCondcode cond ) { 1077 return name_ARMCondcode(cond); 1078 } 1079 1080 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. 1087 */ 1088 static IRExpr* mk_armg_calculate_condition_dyn ( IRExpr* cond ) 1089 { 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. */ 1093 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. 1098 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. */ 1102 IRExpr** args 1103 = mkIRExprVec_4( 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) 1108 ); 1109 IRExpr* call 1110 = mkIRExprCCall( 1111 Ity_I32, 1112 0/*regparm*/, 1113 "armg_calculate_condition", &armg_calculate_condition, 1114 args 1115 ); 1116 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); 1120 return call; 1121 } 1122 1123 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. 1128 */ 1129 static IRExpr* mk_armg_calculate_condition ( ARMCondcode cond ) 1130 { 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) ); 1136 } 1137 1138 1139 /* Build IR to calculate just the carry flag from stored 1140 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression :: 1141 Ity_I32. */ 1142 static IRExpr* mk_armg_calculate_flag_c ( void ) 1143 { 1144 IRExpr** args 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) ); 1149 IRExpr* call 1150 = mkIRExprCCall( 1151 Ity_I32, 1152 0/*regparm*/, 1153 "armg_calculate_flag_c", &armg_calculate_flag_c, 1154 args 1155 ); 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); 1159 return call; 1160 } 1161 1162 1163 /* Build IR to calculate just the overflow flag from stored 1164 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression :: 1165 Ity_I32. */ 1166 static IRExpr* mk_armg_calculate_flag_v ( void ) 1167 { 1168 IRExpr** args 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) ); 1173 IRExpr* call 1174 = mkIRExprCCall( 1175 Ity_I32, 1176 0/*regparm*/, 1177 "armg_calculate_flag_v", &armg_calculate_flag_v, 1178 args 1179 ); 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); 1183 return call; 1184 } 1185 1186 1187 /* Build IR to calculate N Z C V in bits 31:28 of the 1188 returned word. */ 1189 static IRExpr* mk_armg_calculate_flags_nzcv ( void ) 1190 { 1191 IRExpr** args 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) ); 1196 IRExpr* call 1197 = mkIRExprCCall( 1198 Ity_I32, 1199 0/*regparm*/, 1200 "armg_calculate_flags_nzcv", &armg_calculate_flags_nzcv, 1201 args 1202 ); 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); 1206 return call; 1207 } 1208 1209 static IRExpr* mk_armg_calculate_flag_qc ( IRExpr* resL, IRExpr* resR, Bool Q ) 1210 { 1211 IRExpr** args1; 1212 IRExpr** args2; 1213 IRExpr *call1, *call2, *res; 1214 1215 if (Q) { 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)) ); 1224 } else { 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)) ); 1229 } 1230 1231 #if 1 1232 call1 = mkIRExprCCall( 1233 Ity_I32, 1234 0/*regparm*/, 1235 "armg_calculate_flag_qc", &armg_calculate_flag_qc, 1236 args1 1237 ); 1238 if (Q) { 1239 call2 = mkIRExprCCall( 1240 Ity_I32, 1241 0/*regparm*/, 1242 "armg_calculate_flag_qc", &armg_calculate_flag_qc, 1243 args2 1244 ); 1245 } 1246 if (Q) { 1247 res = binop(Iop_Or32, call1, call2); 1248 } else { 1249 res = call1; 1250 } 1251 #else 1252 if (Q) { 1253 res = unop(Iop_1Uto32, 1254 binop(Iop_CmpNE32, 1255 binop(Iop_Or32, 1256 binop(Iop_Or32, 1257 binop(Iop_Xor32, 1258 args1[0], 1259 args1[2]), 1260 binop(Iop_Xor32, 1261 args1[1], 1262 args1[3])), 1263 binop(Iop_Or32, 1264 binop(Iop_Xor32, 1265 args2[0], 1266 args2[2]), 1267 binop(Iop_Xor32, 1268 args2[1], 1269 args2[3]))), 1270 mkU32(0))); 1271 } else { 1272 res = unop(Iop_1Uto32, 1273 binop(Iop_CmpNE32, 1274 binop(Iop_Or32, 1275 binop(Iop_Xor32, 1276 args1[0], 1277 args1[2]), 1278 binop(Iop_Xor32, 1279 args1[1], 1280 args1[3])), 1281 mkU32(0))); 1282 } 1283 #endif 1284 return res; 1285 } 1286 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, 1290 IRTemp condT ) 1291 { 1292 putMiscReg32 (OFFB_FPSCR, 1293 binop(Iop_Or32, 1294 IRExpr_Get(OFFB_FPSCR, Ity_I32), 1295 binop(Iop_Shl32, 1296 mk_armg_calculate_flag_qc(resL, resR, Q), 1297 mkU8(27))), 1298 condT); 1299 } 1300 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. */ 1304 static 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 */ ) 1308 { 1309 IRTemp c8; 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) { 1315 /* unconditional */ 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) )); 1320 } else { 1321 /* conditional */ 1322 c8 = newTemp(Ity_I8); 1323 assign( c8, unop(Iop_32to8, mkexpr(guardT)) ); 1324 stmt( IRStmt_Put( 1325 OFFB_CC_OP, 1326 IRExpr_Mux0X( mkexpr(c8), 1327 IRExpr_Get(OFFB_CC_OP, Ity_I32), 1328 mkU32(cc_op) ))); 1329 stmt( IRStmt_Put( 1330 OFFB_CC_DEP1, 1331 IRExpr_Mux0X( mkexpr(c8), 1332 IRExpr_Get(OFFB_CC_DEP1, Ity_I32), 1333 mkexpr(t_dep1) ))); 1334 stmt( IRStmt_Put( 1335 OFFB_CC_DEP2, 1336 IRExpr_Mux0X( mkexpr(c8), 1337 IRExpr_Get(OFFB_CC_DEP2, Ity_I32), 1338 mkexpr(t_dep2) ))); 1339 stmt( IRStmt_Put( 1340 OFFB_CC_NDEP, 1341 IRExpr_Mux0X( mkexpr(c8), 1342 IRExpr_Get(OFFB_CC_NDEP, Ity_I32), 1343 mkexpr(t_ndep) ))); 1344 } 1345 } 1346 1347 1348 /* Minor variant of the above that sets NDEP to zero (if it 1349 sets it at all) */ 1350 static void setFlags_D1_D2 ( UInt cc_op, IRTemp t_dep1, 1351 IRTemp t_dep2, 1352 IRTemp guardT /* :: Ity_I32, 0 or 1 */ ) 1353 { 1354 IRTemp z32 = newTemp(Ity_I32); 1355 assign( z32, mkU32(0) ); 1356 setFlags_D1_D2_ND( cc_op, t_dep1, t_dep2, z32, guardT ); 1357 } 1358 1359 1360 /* Minor variant of the above that sets DEP2 to zero (if it 1361 sets it at all) */ 1362 static void setFlags_D1_ND ( UInt cc_op, IRTemp t_dep1, 1363 IRTemp t_ndep, 1364 IRTemp guardT /* :: Ity_I32, 0 or 1 */ ) 1365 { 1366 IRTemp z32 = newTemp(Ity_I32); 1367 assign( z32, mkU32(0) ); 1368 setFlags_D1_D2_ND( cc_op, t_dep1, z32, t_ndep, guardT ); 1369 } 1370 1371 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 */ ) 1376 { 1377 IRTemp z32 = newTemp(Ity_I32); 1378 assign( z32, mkU32(0) ); 1379 setFlags_D1_D2_ND( cc_op, t_dep1, z32, z32, guardT ); 1380 } 1381 1382 1383 /* ARM only */ 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. 1390 */ 1391 static void mk_skip_over_A32_if_cond_is_false ( 1392 IRTemp guardT /* :: Ity_I32, 0 or 1 */ 1393 ) 1394 { 1395 ASSERT_IS_ARM; 1396 vassert(guardT != IRTemp_INVALID); 1397 vassert(0 == (guest_R15_curr_instr_notENC & 3)); 1398 stmt( IRStmt_Exit( 1399 unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))), 1400 Ijk_Boring, 1401 IRConst_U32(toUInt(guest_R15_curr_instr_notENC + 4)), 1402 OFFB_R15T 1403 )); 1404 } 1405 1406 /* Thumb16 only */ 1407 /* ditto, but jump over a 16-bit thumb insn */ 1408 static void mk_skip_over_T16_if_cond_is_false ( 1409 IRTemp guardT /* :: Ity_I32, 0 or 1 */ 1410 ) 1411 { 1412 ASSERT_IS_THUMB; 1413 vassert(guardT != IRTemp_INVALID); 1414 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 1415 stmt( IRStmt_Exit( 1416 unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))), 1417 Ijk_Boring, 1418 IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 2) | 1)), 1419 OFFB_R15T 1420 )); 1421 } 1422 1423 1424 /* Thumb32 only */ 1425 /* ditto, but jump over a 32-bit thumb insn */ 1426 static void mk_skip_over_T32_if_cond_is_false ( 1427 IRTemp guardT /* :: Ity_I32, 0 or 1 */ 1428 ) 1429 { 1430 ASSERT_IS_THUMB; 1431 vassert(guardT != IRTemp_INVALID); 1432 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 1433 stmt( IRStmt_Exit( 1434 unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))), 1435 Ijk_Boring, 1436 IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 4) | 1)), 1437 OFFB_R15T 1438 )); 1439 } 1440 1441 1442 /* Thumb16 and Thumb32 only 1443 Generate a SIGILL followed by a restart of the current instruction 1444 if the given temp is nonzero. */ 1445 static void gen_SIGILL_T_if_nonzero ( IRTemp t /* :: Ity_I32 */ ) 1446 { 1447 ASSERT_IS_THUMB; 1448 vassert(t != IRTemp_INVALID); 1449 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 1450 stmt( 1451 IRStmt_Exit( 1452 binop(Iop_CmpNE32, mkexpr(t), mkU32(0)), 1453 Ijk_NoDecode, 1454 IRConst_U32(toUInt(guest_R15_curr_instr_notENC | 1)), 1455 OFFB_R15T 1456 ) 1457 ); 1458 } 1459 1460 1461 /* Inspect the old_itstate, and generate a SIGILL if it indicates that 1462 we are currently in an IT block and are not the last in the block. 1463 This also rolls back guest_ITSTATE to its old value before the exit 1464 and restores it to its new value afterwards. This is so that if 1465 the exit is taken, we have an up to date version of ITSTATE 1466 available. Without doing that, we have no hope of making precise 1467 exceptions work. */ 1468 static void gen_SIGILL_T_if_in_but_NLI_ITBlock ( 1469 IRTemp old_itstate /* :: Ity_I32 */, 1470 IRTemp new_itstate /* :: Ity_I32 */ 1471 ) 1472 { 1473 ASSERT_IS_THUMB; 1474 put_ITSTATE(old_itstate); // backout 1475 IRTemp guards_for_next3 = newTemp(Ity_I32); 1476 assign(guards_for_next3, 1477 binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8))); 1478 gen_SIGILL_T_if_nonzero(guards_for_next3); 1479 put_ITSTATE(new_itstate); //restore 1480 } 1481 1482 1483 /* Simpler version of the above, which generates a SIGILL if 1484 we're anywhere within an IT block. */ 1485 static void gen_SIGILL_T_if_in_ITBlock ( 1486 IRTemp old_itstate /* :: Ity_I32 */, 1487 IRTemp new_itstate /* :: Ity_I32 */ 1488 ) 1489 { 1490 put_ITSTATE(old_itstate); // backout 1491 gen_SIGILL_T_if_nonzero(old_itstate); 1492 put_ITSTATE(new_itstate); //restore 1493 } 1494 1495 1496 /* Generate an APSR value, from the NZCV thunk, and 1497 from QFLAG32 and GEFLAG0 .. GEFLAG3. */ 1498 static IRTemp synthesise_APSR ( void ) 1499 { 1500 IRTemp res1 = newTemp(Ity_I32); 1501 // Get NZCV 1502 assign( res1, mk_armg_calculate_flags_nzcv() ); 1503 // OR in the Q value 1504 IRTemp res2 = newTemp(Ity_I32); 1505 assign( 1506 res2, 1507 binop(Iop_Or32, 1508 mkexpr(res1), 1509 binop(Iop_Shl32, 1510 unop(Iop_1Uto32, 1511 binop(Iop_CmpNE32, 1512 mkexpr(get_QFLAG32()), 1513 mkU32(0))), 1514 mkU8(ARMG_CC_SHIFT_Q))) 1515 ); 1516 // OR in GE0 .. GE3 1517 IRExpr* ge0 1518 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(0), mkU32(0))); 1519 IRExpr* ge1 1520 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(1), mkU32(0))); 1521 IRExpr* ge2 1522 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(2), mkU32(0))); 1523 IRExpr* ge3 1524 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(3), mkU32(0))); 1525 IRTemp res3 = newTemp(Ity_I32); 1526 assign(res3, 1527 binop(Iop_Or32, 1528 mkexpr(res2), 1529 binop(Iop_Or32, 1530 binop(Iop_Or32, 1531 binop(Iop_Shl32, ge0, mkU8(16)), 1532 binop(Iop_Shl32, ge1, mkU8(17))), 1533 binop(Iop_Or32, 1534 binop(Iop_Shl32, ge2, mkU8(18)), 1535 binop(Iop_Shl32, ge3, mkU8(19))) ))); 1536 return res3; 1537 } 1538 1539 1540 /* and the inverse transformation: given an APSR value, 1541 set the NZCV thunk, the Q flag, and the GE flags. */ 1542 static void desynthesise_APSR ( Bool write_nzcvq, Bool write_ge, 1543 IRTemp apsrT, IRTemp condT ) 1544 { 1545 vassert(write_nzcvq || write_ge); 1546 if (write_nzcvq) { 1547 // Do NZCV 1548 IRTemp immT = newTemp(Ity_I32); 1549 assign(immT, binop(Iop_And32, mkexpr(apsrT), mkU32(0xF0000000)) ); 1550 setFlags_D1(ARMG_CC_OP_COPY, immT, condT); 1551 // Do Q 1552 IRTemp qnewT = newTemp(Ity_I32); 1553 assign(qnewT, binop(Iop_And32, mkexpr(apsrT), mkU32(ARMG_CC_MASK_Q))); 1554 put_QFLAG32(qnewT, condT); 1555 } 1556 if (write_ge) { 1557 // Do GE3..0 1558 put_GEFLAG32(0, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<16)), 1559 condT); 1560 put_GEFLAG32(1, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<17)), 1561 condT); 1562 put_GEFLAG32(2, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<18)), 1563 condT); 1564 put_GEFLAG32(3, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<19)), 1565 condT); 1566 } 1567 } 1568 1569 1570 /*------------------------------------------------------------*/ 1571 /*--- Helpers for saturation ---*/ 1572 /*------------------------------------------------------------*/ 1573 1574 /* FIXME: absolutely the only diff. between (a) armUnsignedSatQ and 1575 (b) armSignedSatQ is that in (a) the floor is set to 0, whereas in 1576 (b) the floor is computed from the value of imm5. these two fnsn 1577 should be commoned up. */ 1578 1579 /* UnsignedSatQ(): 'clamp' each value so it lies between 0 <= x <= (2^N)-1 1580 Optionally return flag resQ saying whether saturation occurred. 1581 See definition in manual, section A2.2.1, page 41 1582 (bits(N), boolean) UnsignedSatQ( integer i, integer N ) 1583 { 1584 if ( i > (2^N)-1 ) { result = (2^N)-1; saturated = TRUE; } 1585 elsif ( i < 0 ) { result = 0; saturated = TRUE; } 1586 else { result = i; saturated = FALSE; } 1587 return ( result<N-1:0>, saturated ); 1588 } 1589 */ 1590 static void armUnsignedSatQ( IRTemp* res, /* OUT - Ity_I32 */ 1591 IRTemp* resQ, /* OUT - Ity_I32 */ 1592 IRTemp regT, /* value to clamp - Ity_I32 */ 1593 UInt imm5 ) /* saturation ceiling */ 1594 { 1595 UInt ceil = (1 << imm5) - 1; // (2^imm5)-1 1596 UInt floor = 0; 1597 1598 IRTemp node0 = newTemp(Ity_I32); 1599 IRTemp node1 = newTemp(Ity_I32); 1600 IRTemp node2 = newTemp(Ity_I1); 1601 IRTemp node3 = newTemp(Ity_I32); 1602 IRTemp node4 = newTemp(Ity_I32); 1603 IRTemp node5 = newTemp(Ity_I1); 1604 IRTemp node6 = newTemp(Ity_I32); 1605 1606 assign( node0, mkexpr(regT) ); 1607 assign( node1, mkU32(ceil) ); 1608 assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) ); 1609 assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)), 1610 mkexpr(node0), 1611 mkexpr(node1) ) ); 1612 assign( node4, mkU32(floor) ); 1613 assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) ); 1614 assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)), 1615 mkexpr(node3), 1616 mkexpr(node4) ) ); 1617 assign( *res, mkexpr(node6) ); 1618 1619 /* if saturation occurred, then resQ is set to some nonzero value 1620 if sat did not occur, resQ is guaranteed to be zero. */ 1621 if (resQ) { 1622 assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) ); 1623 } 1624 } 1625 1626 1627 /* SignedSatQ(): 'clamp' each value so it lies between -2^N <= x <= (2^N) - 1 1628 Optionally return flag resQ saying whether saturation occurred. 1629 - see definition in manual, section A2.2.1, page 41 1630 (bits(N), boolean ) SignedSatQ( integer i, integer N ) 1631 { 1632 if ( i > 2^(N-1) - 1 ) { result = 2^(N-1) - 1; saturated = TRUE; } 1633 elsif ( i < -(2^(N-1)) ) { result = -(2^(N-1)); saturated = FALSE; } 1634 else { result = i; saturated = FALSE; } 1635 return ( result[N-1:0], saturated ); 1636 } 1637 */ 1638 static void armSignedSatQ( IRTemp regT, /* value to clamp - Ity_I32 */ 1639 UInt imm5, /* saturation ceiling */ 1640 IRTemp* res, /* OUT - Ity_I32 */ 1641 IRTemp* resQ ) /* OUT - Ity_I32 */ 1642 { 1643 Int ceil = (1 << (imm5-1)) - 1; // (2^(imm5-1))-1 1644 Int floor = -(1 << (imm5-1)); // -(2^(imm5-1)) 1645 1646 IRTemp node0 = newTemp(Ity_I32); 1647 IRTemp node1 = newTemp(Ity_I32); 1648 IRTemp node2 = newTemp(Ity_I1); 1649 IRTemp node3 = newTemp(Ity_I32); 1650 IRTemp node4 = newTemp(Ity_I32); 1651 IRTemp node5 = newTemp(Ity_I1); 1652 IRTemp node6 = newTemp(Ity_I32); 1653 1654 assign( node0, mkexpr(regT) ); 1655 assign( node1, mkU32(ceil) ); 1656 assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) ); 1657 assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)), 1658 mkexpr(node0), mkexpr(node1) ) ); 1659 assign( node4, mkU32(floor) ); 1660 assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) ); 1661 assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)), 1662 mkexpr(node3), mkexpr(node4) ) ); 1663 assign( *res, mkexpr(node6) ); 1664 1665 /* if saturation occurred, then resQ is set to some nonzero value 1666 if sat did not occur, resQ is guaranteed to be zero. */ 1667 if (resQ) { 1668 assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) ); 1669 } 1670 } 1671 1672 1673 /* Compute a value 0 :: I32 or 1 :: I32, indicating whether signed 1674 overflow occurred for 32-bit addition. Needs both args and the 1675 result. HD p27. */ 1676 static 1677 IRExpr* signed_overflow_after_Add32 ( IRExpr* resE, 1678 IRTemp argL, IRTemp argR ) 1679 { 1680 IRTemp res = newTemp(Ity_I32); 1681 assign(res, resE); 1682 return 1683 binop( Iop_Shr32, 1684 binop( Iop_And32, 1685 binop( Iop_Xor32, mkexpr(res), mkexpr(argL) ), 1686 binop( Iop_Xor32, mkexpr(res), mkexpr(argR) )), 1687 mkU8(31) ); 1688 } 1689 1690 /* Similarly .. also from HD p27 .. */ 1691 static 1692 IRExpr* signed_overflow_after_Sub32 ( IRExpr* resE, 1693 IRTemp argL, IRTemp argR ) 1694 { 1695 IRTemp res = newTemp(Ity_I32); 1696 assign(res, resE); 1697 return 1698 binop( Iop_Shr32, 1699 binop( Iop_And32, 1700 binop( Iop_Xor32, mkexpr(argL), mkexpr(argR) ), 1701 binop( Iop_Xor32, mkexpr(res), mkexpr(argL) )), 1702 mkU8(31) ); 1703 } 1704 1705 1706 /*------------------------------------------------------------*/ 1707 /*--- Larger helpers ---*/ 1708 /*------------------------------------------------------------*/ 1709 1710 /* Compute both the result and new C flag value for a LSL by an imm5 1711 or by a register operand. May generate reads of the old C value 1712 (hence only safe to use before any writes to guest state happen). 1713 Are factored out so can be used by both ARM and Thumb. 1714 1715 Note that in compute_result_and_C_after_{LSL,LSR,ASR}_by{imm5,reg}, 1716 "res" (the result) is a.k.a. "shop", shifter operand 1717 "newC" (the new C) is a.k.a. "shco", shifter carry out 1718 1719 The calling convention for res and newC is a bit funny. They could 1720 be passed by value, but instead are passed by ref. 1721 1722 The C (shco) value computed must be zero in bits 31:1, as the IR 1723 optimisations for flag handling (guest_arm_spechelper) rely on 1724 that, and the slow-path handlers (armg_calculate_flags_nzcv) assert 1725 for it. Same applies to all these functions that compute shco 1726 after a shift or rotate, not just this one. 1727 */ 1728 1729 static void compute_result_and_C_after_LSL_by_imm5 ( 1730 /*OUT*/HChar* buf, 1731 IRTemp* res, 1732 IRTemp* newC, 1733 IRTemp rMt, UInt shift_amt, /* operands */ 1734 UInt rM /* only for debug printing */ 1735 ) 1736 { 1737 if (shift_amt == 0) { 1738 if (newC) { 1739 assign( *newC, mk_armg_calculate_flag_c() ); 1740 } 1741 assign( *res, mkexpr(rMt) ); 1742 DIS(buf, "r%u", rM); 1743 } else { 1744 vassert(shift_amt >= 1 && shift_amt <= 31); 1745 if (newC) { 1746 assign( *newC, 1747 binop(Iop_And32, 1748 binop(Iop_Shr32, mkexpr(rMt), 1749 mkU8(32 - shift_amt)), 1750 mkU32(1))); 1751 } 1752 assign( *res, 1753 binop(Iop_Shl32, mkexpr(rMt), mkU8(shift_amt)) ); 1754 DIS(buf, "r%u, LSL #%u", rM, shift_amt); 1755 } 1756 } 1757 1758 1759 static void compute_result_and_C_after_LSL_by_reg ( 1760 /*OUT*/HChar* buf, 1761 IRTemp* res, 1762 IRTemp* newC, 1763 IRTemp rMt, IRTemp rSt, /* operands */ 1764 UInt rM, UInt rS /* only for debug printing */ 1765 ) 1766 { 1767 // shift left in range 0 .. 255 1768 // amt = rS & 255 1769 // res = amt < 32 ? Rm << amt : 0 1770 // newC = amt == 0 ? oldC : 1771 // amt in 1..32 ? Rm[32-amt] : 0 1772 IRTemp amtT = newTemp(Ity_I32); 1773 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) ); 1774 if (newC) { 1775 /* mux0X(amt == 0, 1776 mux0X(amt < 32, 1777 0, 1778 Rm[(32-amt) & 31]), 1779 oldC) 1780 */ 1781 /* About the best you can do is pray that iropt is able 1782 to nuke most or all of the following junk. */ 1783 IRTemp oldC = newTemp(Ity_I32); 1784 assign(oldC, mk_armg_calculate_flag_c() ); 1785 assign( 1786 *newC, 1787 IRExpr_Mux0X( 1788 unop(Iop_1Uto8, 1789 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))), 1790 IRExpr_Mux0X( 1791 unop(Iop_1Uto8, 1792 binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))), 1793 mkU32(0), 1794 binop(Iop_And32, 1795 binop(Iop_Shr32, 1796 mkexpr(rMt), 1797 unop(Iop_32to8, 1798 binop(Iop_And32, 1799 binop(Iop_Sub32, 1800 mkU32(32), 1801 mkexpr(amtT)), 1802 mkU32(31) 1803 ) 1804 ) 1805 ), 1806 mkU32(1) 1807 ) 1808 ), 1809 mkexpr(oldC) 1810 ) 1811 ); 1812 } 1813 // (Rm << (Rs & 31)) & (((Rs & 255) - 32) >>s 31) 1814 // Lhs of the & limits the shift to 31 bits, so as to 1815 // give known IR semantics. Rhs of the & is all 1s for 1816 // Rs <= 31 and all 0s for Rs >= 32. 1817 assign( 1818 *res, 1819 binop( 1820 Iop_And32, 1821 binop(Iop_Shl32, 1822 mkexpr(rMt), 1823 unop(Iop_32to8, 1824 binop(Iop_And32, mkexpr(rSt), mkU32(31)))), 1825 binop(Iop_Sar32, 1826 binop(Iop_Sub32, 1827 mkexpr(amtT), 1828 mkU32(32)), 1829 mkU8(31)))); 1830 DIS(buf, "r%u, LSL r%u", rM, rS); 1831 } 1832 1833 1834 static void compute_result_and_C_after_LSR_by_imm5 ( 1835 /*OUT*/HChar* buf, 1836 IRTemp* res, 1837 IRTemp* newC, 1838 IRTemp rMt, UInt shift_amt, /* operands */ 1839 UInt rM /* only for debug printing */ 1840 ) 1841 { 1842 if (shift_amt == 0) { 1843 // conceptually a 32-bit shift, however: 1844 // res = 0 1845 // newC = Rm[31] 1846 if (newC) { 1847 assign( *newC, 1848 binop(Iop_And32, 1849 binop(Iop_Shr32, mkexpr(rMt), mkU8(31)), 1850 mkU32(1))); 1851 } 1852 assign( *res, mkU32(0) ); 1853 DIS(buf, "r%u, LSR #0(a.k.a. 32)", rM); 1854 } else { 1855 // shift in range 1..31 1856 // res = Rm >>u shift_amt 1857 // newC = Rm[shift_amt - 1] 1858 vassert(shift_amt >= 1 && shift_amt <= 31); 1859 if (newC) { 1860 assign( *newC, 1861 binop(Iop_And32, 1862 binop(Iop_Shr32, mkexpr(rMt), 1863 mkU8(shift_amt - 1)), 1864 mkU32(1))); 1865 } 1866 assign( *res, 1867 binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)) ); 1868 DIS(buf, "r%u, LSR #%u", rM, shift_amt); 1869 } 1870 } 1871 1872 1873 static void compute_result_and_C_after_LSR_by_reg ( 1874 /*OUT*/HChar* buf, 1875 IRTemp* res, 1876 IRTemp* newC, 1877 IRTemp rMt, IRTemp rSt, /* operands */ 1878 UInt rM, UInt rS /* only for debug printing */ 1879 ) 1880 { 1881 // shift right in range 0 .. 255 1882 // amt = rS & 255 1883 // res = amt < 32 ? Rm >>u amt : 0 1884 // newC = amt == 0 ? oldC : 1885 // amt in 1..32 ? Rm[amt-1] : 0 1886 IRTemp amtT = newTemp(Ity_I32); 1887 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) ); 1888 if (newC) { 1889 /* mux0X(amt == 0, 1890 mux0X(amt < 32, 1891 0, 1892 Rm[(amt-1) & 31]), 1893 oldC) 1894 */ 1895 IRTemp oldC = newTemp(Ity_I32); 1896 assign(oldC, mk_armg_calculate_flag_c() ); 1897 assign( 1898 *newC, 1899 IRExpr_Mux0X( 1900 unop(Iop_1Uto8, 1901 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))), 1902 IRExpr_Mux0X( 1903 unop(Iop_1Uto8, 1904 binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))), 1905 mkU32(0), 1906 binop(Iop_And32, 1907 binop(Iop_Shr32, 1908 mkexpr(rMt), 1909 unop(Iop_32to8, 1910 binop(Iop_And32, 1911 binop(Iop_Sub32, 1912 mkexpr(amtT), 1913 mkU32(1)), 1914 mkU32(31) 1915 ) 1916 ) 1917 ), 1918 mkU32(1) 1919 ) 1920 ), 1921 mkexpr(oldC) 1922 ) 1923 ); 1924 } 1925 // (Rm >>u (Rs & 31)) & (((Rs & 255) - 32) >>s 31) 1926 // Lhs of the & limits the shift to 31 bits, so as to 1927 // give known IR semantics. Rhs of the & is all 1s for 1928 // Rs <= 31 and all 0s for Rs >= 32. 1929 assign( 1930 *res, 1931 binop( 1932 Iop_And32, 1933 binop(Iop_Shr32, 1934 mkexpr(rMt), 1935 unop(Iop_32to8, 1936 binop(Iop_And32, mkexpr(rSt), mkU32(31)))), 1937 binop(Iop_Sar32, 1938 binop(Iop_Sub32, 1939 mkexpr(amtT), 1940 mkU32(32)), 1941 mkU8(31)))); 1942 DIS(buf, "r%u, LSR r%u", rM, rS); 1943 } 1944 1945 1946 static void compute_result_and_C_after_ASR_by_imm5 ( 1947 /*OUT*/HChar* buf, 1948 IRTemp* res, 1949 IRTemp* newC, 1950 IRTemp rMt, UInt shift_amt, /* operands */ 1951 UInt rM /* only for debug printing */ 1952 ) 1953 { 1954 if (shift_amt == 0) { 1955 // conceptually a 32-bit shift, however: 1956 // res = Rm >>s 31 1957 // newC = Rm[31] 1958 if (newC) { 1959 assign( *newC, 1960 binop(Iop_And32, 1961 binop(Iop_Shr32, mkexpr(rMt), mkU8(31)), 1962 mkU32(1))); 1963 } 1964 assign( *res, binop(Iop_Sar32, mkexpr(rMt), mkU8(31)) ); 1965 DIS(buf, "r%u, ASR #0(a.k.a. 32)", rM); 1966 } else { 1967 // shift in range 1..31 1968 // res = Rm >>s shift_amt 1969 // newC = Rm[shift_amt - 1] 1970 vassert(shift_amt >= 1 && shift_amt <= 31); 1971 if (newC) { 1972 assign( *newC, 1973 binop(Iop_And32, 1974 binop(Iop_Shr32, mkexpr(rMt), 1975 mkU8(shift_amt - 1)), 1976 mkU32(1))); 1977 } 1978 assign( *res, 1979 binop(Iop_Sar32, mkexpr(rMt), mkU8(shift_amt)) ); 1980 DIS(buf, "r%u, ASR #%u", rM, shift_amt); 1981 } 1982 } 1983 1984 1985 static void compute_result_and_C_after_ASR_by_reg ( 1986 /*OUT*/HChar* buf, 1987 IRTemp* res, 1988 IRTemp* newC, 1989 IRTemp rMt, IRTemp rSt, /* operands */ 1990 UInt rM, UInt rS /* only for debug printing */ 1991 ) 1992 { 1993 // arithmetic shift right in range 0 .. 255 1994 // amt = rS & 255 1995 // res = amt < 32 ? Rm >>s amt : Rm >>s 31 1996 // newC = amt == 0 ? oldC : 1997 // amt in 1..32 ? Rm[amt-1] : Rm[31] 1998 IRTemp amtT = newTemp(Ity_I32); 1999 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) ); 2000 if (newC) { 2001 /* mux0X(amt == 0, 2002 mux0X(amt < 32, 2003 Rm[31], 2004 Rm[(amt-1) & 31]) 2005 oldC) 2006 */ 2007 IRTemp oldC = newTemp(Ity_I32); 2008 assign(oldC, mk_armg_calculate_flag_c() ); 2009 assign( 2010 *newC, 2011 IRExpr_Mux0X( 2012 unop(Iop_1Uto8, 2013 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))), 2014 IRExpr_Mux0X( 2015 unop(Iop_1Uto8, 2016 binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))), 2017 binop(Iop_And32, 2018 binop(Iop_Shr32, 2019 mkexpr(rMt), 2020 mkU8(31) 2021 ), 2022 mkU32(1) 2023 ), 2024 binop(Iop_And32, 2025 binop(Iop_Shr32, 2026 mkexpr(rMt), 2027 unop(Iop_32to8, 2028 binop(Iop_And32, 2029 binop(Iop_Sub32, 2030 mkexpr(amtT), 2031 mkU32(1)), 2032 mkU32(31) 2033 ) 2034 ) 2035 ), 2036 mkU32(1) 2037 ) 2038 ), 2039 mkexpr(oldC) 2040 ) 2041 ); 2042 } 2043 // (Rm >>s (amt <u 32 ? amt : 31)) 2044 assign( 2045 *res, 2046 binop( 2047 Iop_Sar32, 2048 mkexpr(rMt), 2049 unop( 2050 Iop_32to8, 2051 IRExpr_Mux0X( 2052 unop( 2053 Iop_1Uto8, 2054 binop(Iop_CmpLT32U, mkexpr(amtT), mkU32(32))), 2055 mkU32(31), 2056 mkexpr(amtT))))); 2057 DIS(buf, "r%u, ASR r%u", rM, rS); 2058 } 2059 2060 2061 static void compute_result_and_C_after_ROR_by_reg ( 2062 /*OUT*/HChar* buf, 2063 IRTemp* res, 2064 IRTemp* newC, 2065 IRTemp rMt, IRTemp rSt, /* operands */ 2066 UInt rM, UInt rS /* only for debug printing */ 2067 ) 2068 { 2069 // rotate right in range 0 .. 255 2070 // amt = rS & 255 2071 // shop = Rm `ror` (amt & 31) 2072 // shco = amt == 0 ? oldC : Rm[(amt-1) & 31] 2073 IRTemp amtT = newTemp(Ity_I32); 2074 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) ); 2075 IRTemp amt5T = newTemp(Ity_I32); 2076 assign( amt5T, binop(Iop_And32, mkexpr(rSt), mkU32(31)) ); 2077 IRTemp oldC = newTemp(Ity_I32); 2078 assign(oldC, mk_armg_calculate_flag_c() ); 2079 if (newC) { 2080 assign( 2081 *newC, 2082 IRExpr_Mux0X( 2083 unop(Iop_32to8, mkexpr(amtT)), 2084 mkexpr(oldC), 2085 binop(Iop_And32, 2086 binop(Iop_Shr32, 2087 mkexpr(rMt), 2088 unop(Iop_32to8, 2089 binop(Iop_And32, 2090 binop(Iop_Sub32, 2091 mkexpr(amtT), 2092 mkU32(1) 2093 ), 2094 mkU32(31) 2095 ) 2096 ) 2097 ), 2098 mkU32(1) 2099 ) 2100 ) 2101 ); 2102 } 2103 assign( 2104 *res, 2105 IRExpr_Mux0X( 2106 unop(Iop_32to8, mkexpr(amt5T)), mkexpr(rMt), 2107 binop(Iop_Or32, 2108 binop(Iop_Shr32, 2109 mkexpr(rMt), 2110 unop(Iop_32to8, mkexpr(amt5T)) 2111 ), 2112 binop(Iop_Shl32, 2113 mkexpr(rMt), 2114 unop(Iop_32to8, 2115 binop(Iop_Sub32, mkU32(32), mkexpr(amt5T)) 2116 ) 2117 ) 2118 ) 2119 ) 2120 ); 2121 DIS(buf, "r%u, ROR r#%u", rM, rS); 2122 } 2123 2124 2125 /* Generate an expression corresponding to the immediate-shift case of 2126 a shifter operand. This is used both for ARM and Thumb2. 2127 2128 Bind it to a temporary, and return that via *res. If newC is 2129 non-NULL, also compute a value for the shifter's carry out (in the 2130 LSB of a word), bind it to a temporary, and return that via *shco. 2131 2132 Generates GETs from the guest state and is therefore not safe to 2133 use once we start doing PUTs to it, for any given instruction. 2134 2135 'how' is encoded thusly: 2136 00b LSL, 01b LSR, 10b ASR, 11b ROR 2137 Most but not all ARM and Thumb integer insns use this encoding. 2138 Be careful to ensure the right value is passed here. 2139 */ 2140 static void compute_result_and_C_after_shift_by_imm5 ( 2141 /*OUT*/HChar* buf, 2142 /*OUT*/IRTemp* res, 2143 /*OUT*/IRTemp* newC, 2144 IRTemp rMt, /* reg to shift */ 2145 UInt how, /* what kind of shift */ 2146 UInt shift_amt, /* shift amount (0..31) */ 2147 UInt rM /* only for debug printing */ 2148 ) 2149 { 2150 vassert(shift_amt < 32); 2151 vassert(how < 4); 2152 2153 switch (how) { 2154 2155 case 0: 2156 compute_result_and_C_after_LSL_by_imm5( 2157 buf, res, newC, rMt, shift_amt, rM 2158 ); 2159 break; 2160 2161 case 1: 2162 compute_result_and_C_after_LSR_by_imm5( 2163 buf, res, newC, rMt, shift_amt, rM 2164 ); 2165 break; 2166 2167 case 2: 2168 compute_result_and_C_after_ASR_by_imm5( 2169 buf, res, newC, rMt, shift_amt, rM 2170 ); 2171 break; 2172 2173 case 3: 2174 if (shift_amt == 0) { 2175 IRTemp oldcT = newTemp(Ity_I32); 2176 // rotate right 1 bit through carry (?) 2177 // RRX -- described at ARM ARM A5-17 2178 // res = (oldC << 31) | (Rm >>u 1) 2179 // newC = Rm[0] 2180 if (newC) { 2181 assign( *newC, 2182 binop(Iop_And32, mkexpr(rMt), mkU32(1))); 2183 } 2184 assign( oldcT, mk_armg_calculate_flag_c() ); 2185 assign( *res, 2186 binop(Iop_Or32, 2187 binop(Iop_Shl32, mkexpr(oldcT), mkU8(31)), 2188 binop(Iop_Shr32, mkexpr(rMt), mkU8(1))) ); 2189 DIS(buf, "r%u, RRX", rM); 2190 } else { 2191 // rotate right in range 1..31 2192 // res = Rm `ror` shift_amt 2193 // newC = Rm[shift_amt - 1] 2194 vassert(shift_amt >= 1 && shift_amt <= 31); 2195 if (newC) { 2196 assign( *newC, 2197 binop(Iop_And32, 2198 binop(Iop_Shr32, mkexpr(rMt), 2199 mkU8(shift_amt - 1)), 2200 mkU32(1))); 2201 } 2202 assign( *res, 2203 binop(Iop_Or32, 2204 binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)), 2205 binop(Iop_Shl32, mkexpr(rMt), 2206 mkU8(32-shift_amt)))); 2207 DIS(buf, "r%u, ROR #%u", rM, shift_amt); 2208 } 2209 break; 2210 2211 default: 2212 /*NOTREACHED*/ 2213 vassert(0); 2214 } 2215 } 2216 2217 2218 /* Generate an expression corresponding to the register-shift case of 2219 a shifter operand. This is used both for ARM and Thumb2. 2220 2221 Bind it to a temporary, and return that via *res. If newC is 2222 non-NULL, also compute a value for the shifter's carry out (in the 2223 LSB of a word), bind it to a temporary, and return that via *shco. 2224 2225 Generates GETs from the guest state and is therefore not safe to 2226 use once we start doing PUTs to it, for any given instruction. 2227 2228 'how' is encoded thusly: 2229 00b LSL, 01b LSR, 10b ASR, 11b ROR 2230 Most but not all ARM and Thumb integer insns use this encoding. 2231 Be careful to ensure the right value is passed here. 2232 */ 2233 static void compute_result_and_C_after_shift_by_reg ( 2234 /*OUT*/HChar* buf, 2235 /*OUT*/IRTemp* res, 2236 /*OUT*/IRTemp* newC, 2237 IRTemp rMt, /* reg to shift */ 2238 UInt how, /* what kind of shift */ 2239 IRTemp rSt, /* shift amount */ 2240 UInt rM, /* only for debug printing */ 2241 UInt rS /* only for debug printing */ 2242 ) 2243 { 2244 vassert(how < 4); 2245 switch (how) { 2246 case 0: { /* LSL */ 2247 compute_result_and_C_after_LSL_by_reg( 2248 buf, res, newC, rMt, rSt, rM, rS 2249 ); 2250 break; 2251 } 2252 case 1: { /* LSR */ 2253 compute_result_and_C_after_LSR_by_reg( 2254 buf, res, newC, rMt, rSt, rM, rS 2255 ); 2256 break; 2257 } 2258 case 2: { /* ASR */ 2259 compute_result_and_C_after_ASR_by_reg( 2260 buf, res, newC, rMt, rSt, rM, rS 2261 ); 2262 break; 2263 } 2264 case 3: { /* ROR */ 2265 compute_result_and_C_after_ROR_by_reg( 2266 buf, res, newC, rMt, rSt, rM, rS 2267 ); 2268 break; 2269 } 2270 default: 2271 /*NOTREACHED*/ 2272 vassert(0); 2273 } 2274 } 2275 2276 2277 /* Generate an expression corresponding to a shifter_operand, bind it 2278 to a temporary, and return that via *shop. If shco is non-NULL, 2279 also compute a value for the shifter's carry out (in the LSB of a 2280 word), bind it to a temporary, and return that via *shco. 2281 2282 If for some reason we can't come up with a shifter operand (missing 2283 case? not really a shifter operand?) return False. 2284 2285 Generates GETs from the guest state and is therefore not safe to 2286 use once we start doing PUTs to it, for any given instruction. 2287 2288 For ARM insns only; not for Thumb. 2289 */ 2290 static Bool mk_shifter_operand ( UInt insn_25, UInt insn_11_0, 2291 /*OUT*/IRTemp* shop, 2292 /*OUT*/IRTemp* shco, 2293 /*OUT*/HChar* buf ) 2294 { 2295 UInt insn_4 = (insn_11_0 >> 4) & 1; 2296 UInt insn_7 = (insn_11_0 >> 7) & 1; 2297 vassert(insn_25 <= 0x1); 2298 vassert(insn_11_0 <= 0xFFF); 2299 2300 vassert(shop && *shop == IRTemp_INVALID); 2301 *shop = newTemp(Ity_I32); 2302 2303 if (shco) { 2304 vassert(*shco == IRTemp_INVALID); 2305 *shco = newTemp(Ity_I32); 2306 } 2307 2308 /* 32-bit immediate */ 2309 2310 if (insn_25 == 1) { 2311 /* immediate: (7:0) rotated right by 2 * (11:8) */ 2312 UInt imm = (insn_11_0 >> 0) & 0xFF; 2313 UInt rot = 2 * ((insn_11_0 >> 8) & 0xF); 2314 vassert(rot <= 30); 2315 imm = ROR32(imm, rot); 2316 if (shco) { 2317 if (rot == 0) { 2318 assign( *shco, mk_armg_calculate_flag_c() ); 2319 } else { 2320 assign( *shco, mkU32( (imm >> 31) & 1 ) ); 2321 } 2322 } 2323 DIS(buf, "#0x%x", imm); 2324 assign( *shop, mkU32(imm) ); 2325 return True; 2326 } 2327 2328 /* Shift/rotate by immediate */ 2329 2330 if (insn_25 == 0 && insn_4 == 0) { 2331 /* Rm (3:0) shifted (6:5) by immediate (11:7) */ 2332 UInt shift_amt = (insn_11_0 >> 7) & 0x1F; 2333 UInt rM = (insn_11_0 >> 0) & 0xF; 2334 UInt how = (insn_11_0 >> 5) & 3; 2335 /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */ 2336 IRTemp rMt = newTemp(Ity_I32); 2337 assign(rMt, getIRegA(rM)); 2338 2339 vassert(shift_amt <= 31); 2340 2341 compute_result_and_C_after_shift_by_imm5( 2342 buf, shop, shco, rMt, how, shift_amt, rM 2343 ); 2344 return True; 2345 } 2346 2347 /* Shift/rotate by register */ 2348 if (insn_25 == 0 && insn_4 == 1) { 2349 /* Rm (3:0) shifted (6:5) by Rs (11:8) */ 2350 UInt rM = (insn_11_0 >> 0) & 0xF; 2351 UInt rS = (insn_11_0 >> 8) & 0xF; 2352 UInt how = (insn_11_0 >> 5) & 3; 2353 /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */ 2354 IRTemp rMt = newTemp(Ity_I32); 2355 IRTemp rSt = newTemp(Ity_I32); 2356 2357 if (insn_7 == 1) 2358 return False; /* not really a shifter operand */ 2359 2360 assign(rMt, getIRegA(rM)); 2361 assign(rSt, getIRegA(rS)); 2362 2363 compute_result_and_C_after_shift_by_reg( 2364 buf, shop, shco, rMt, how, rSt, rM, rS 2365 ); 2366 return True; 2367 } 2368 2369 vex_printf("mk_shifter_operand(0x%x,0x%x)\n", insn_25, insn_11_0 ); 2370 return False; 2371 } 2372 2373 2374 /* ARM only */ 2375 static 2376 IRExpr* mk_EA_reg_plusminus_imm12 ( UInt rN, UInt bU, UInt imm12, 2377 /*OUT*/HChar* buf ) 2378 { 2379 vassert(rN < 16); 2380 vassert(bU < 2); 2381 vassert(imm12 < 0x1000); 2382 UChar opChar = bU == 1 ? '+' : '-'; 2383 DIS(buf, "[r%u, #%c%u]", rN, opChar, imm12); 2384 return 2385 binop( (bU == 1 ? Iop_Add32 : Iop_Sub32), 2386 getIRegA(rN), 2387 mkU32(imm12) ); 2388 } 2389 2390 2391 /* ARM only. 2392 NB: This is "DecodeImmShift" in newer versions of the the ARM ARM. 2393 */ 2394 static 2395 IRExpr* mk_EA_reg_plusminus_shifted_reg ( UInt rN, UInt bU, UInt rM, 2396 UInt sh2, UInt imm5, 2397 /*OUT*/HChar* buf ) 2398 { 2399 vassert(rN < 16); 2400 vassert(bU < 2); 2401 vassert(rM < 16); 2402 vassert(sh2 < 4); 2403 vassert(imm5 < 32); 2404 UChar opChar = bU == 1 ? '+' : '-'; 2405 IRExpr* index = NULL; 2406 switch (sh2) { 2407 case 0: /* LSL */ 2408 /* imm5 can be in the range 0 .. 31 inclusive. */ 2409 index = binop(Iop_Shl32, getIRegA(rM), mkU8(imm5)); 2410 DIS(buf, "[r%u, %c r%u LSL #%u]", rN, opChar, rM, imm5); 2411 break; 2412 case 1: /* LSR */ 2413 if (imm5 == 0) { 2414 index = mkU32(0); 2415 vassert(0); // ATC 2416 } else { 2417 index = binop(Iop_Shr32, getIRegA(rM), mkU8(imm5)); 2418 } 2419 DIS(buf, "[r%u, %cr%u, LSR #%u]", 2420 rN, opChar, rM, imm5 == 0 ? 32 : imm5); 2421 break; 2422 case 2: /* ASR */ 2423 /* Doesn't this just mean that the behaviour with imm5 == 0 2424 is the same as if it had been 31 ? */ 2425 if (imm5 == 0) { 2426 index = binop(Iop_Sar32, getIRegA(rM), mkU8(31)); 2427 vassert(0); // ATC 2428 } else { 2429 index = binop(Iop_Sar32, getIRegA(rM), mkU8(imm5)); 2430 } 2431 DIS(buf, "[r%u, %cr%u, ASR #%u]", 2432 rN, opChar, rM, imm5 == 0 ? 32 : imm5); 2433 break; 2434 case 3: /* ROR or RRX */ 2435 if (imm5 == 0) { 2436 IRTemp rmT = newTemp(Ity_I32); 2437 IRTemp cflagT = newTemp(Ity_I32); 2438 assign(rmT, getIRegA(rM)); 2439 assign(cflagT, mk_armg_calculate_flag_c()); 2440 index = binop(Iop_Or32, 2441 binop(Iop_Shl32, mkexpr(cflagT), mkU8(31)), 2442 binop(Iop_Shr32, mkexpr(rmT), mkU8(1))); 2443 DIS(buf, "[r%u, %cr%u, RRX]", rN, opChar, rM); 2444 } else { 2445 IRTemp rmT = newTemp(Ity_I32); 2446 assign(rmT, getIRegA(rM)); 2447 vassert(imm5 >= 1 && imm5 <= 31); 2448 index = binop(Iop_Or32, 2449 binop(Iop_Shl32, mkexpr(rmT), mkU8(32-imm5)), 2450 binop(Iop_Shr32, mkexpr(rmT), mkU8(imm5))); 2451 DIS(buf, "[r%u, %cr%u, ROR #%u]", rN, opChar, rM, imm5); 2452 } 2453 break; 2454 default: 2455 vassert(0); 2456 } 2457 vassert(index); 2458 return binop(bU == 1 ? Iop_Add32 : Iop_Sub32, 2459 getIRegA(rN), index); 2460 } 2461 2462 2463 /* ARM only */ 2464 static 2465 IRExpr* mk_EA_reg_plusminus_imm8 ( UInt rN, UInt bU, UInt imm8, 2466 /*OUT*/HChar* buf ) 2467 { 2468 vassert(rN < 16); 2469 vassert(bU < 2); 2470 vassert(imm8 < 0x100); 2471 UChar opChar = bU == 1 ? '+' : '-'; 2472 DIS(buf, "[r%u, #%c%u]", rN, opChar, imm8); 2473 return 2474 binop( (bU == 1 ? Iop_Add32 : Iop_Sub32), 2475 getIRegA(rN), 2476 mkU32(imm8) ); 2477 } 2478 2479 2480 /* ARM only */ 2481 static 2482 IRExpr* mk_EA_reg_plusminus_reg ( UInt rN, UInt bU, UInt rM, 2483 /*OUT*/HChar* buf ) 2484 { 2485 vassert(rN < 16); 2486 vassert(bU < 2); 2487 vassert(rM < 16); 2488 UChar opChar = bU == 1 ? '+' : '-'; 2489 IRExpr* index = getIRegA(rM); 2490 DIS(buf, "[r%u, %c r%u]", rN, opChar, rM); 2491 return binop(bU == 1 ? Iop_Add32 : Iop_Sub32, 2492 getIRegA(rN), index); 2493 } 2494 2495 2496 /* irRes :: Ity_I32 holds a floating point comparison result encoded 2497 as an IRCmpF64Result. Generate code to convert it to an 2498 ARM-encoded (N,Z,C,V) group in the lowest 4 bits of an I32 value. 2499 Assign a new temp to hold that value, and return the temp. */ 2500 static 2501 IRTemp mk_convert_IRCmpF64Result_to_NZCV ( IRTemp irRes ) 2502 { 2503 IRTemp ix = newTemp(Ity_I32); 2504 IRTemp termL = newTemp(Ity_I32); 2505 IRTemp termR = newTemp(Ity_I32); 2506 IRTemp nzcv = newTemp(Ity_I32); 2507 2508 /* This is where the fun starts. We have to convert 'irRes' from 2509 an IR-convention return result (IRCmpF64Result) to an 2510 ARM-encoded (N,Z,C,V) group. The final result is in the bottom 2511 4 bits of 'nzcv'. */ 2512 /* Map compare result from IR to ARM(nzcv) */ 2513 /* 2514 FP cmp result | IR | ARM(nzcv) 2515 -------------------------------- 2516 UN 0x45 0011 2517 LT 0x01 1000 2518 GT 0x00 0010 2519 EQ 0x40 0110 2520 */ 2521 /* Now since you're probably wondering WTF .. 2522 2523 ix fishes the useful bits out of the IR value, bits 6 and 0, and 2524 places them side by side, giving a number which is 0, 1, 2 or 3. 2525 2526 termL is a sequence cooked up by GNU superopt. It converts ix 2527 into an almost correct value NZCV value (incredibly), except 2528 for the case of UN, where it produces 0100 instead of the 2529 required 0011. 2530 2531 termR is therefore a correction term, also computed from ix. It 2532 is 1 in the UN case and 0 for LT, GT and UN. Hence, to get 2533 the final correct value, we subtract termR from termL. 2534 2535 Don't take my word for it. There's a test program at the bottom 2536 of this file, to try this out with. 2537 */ 2538 assign( 2539 ix, 2540 binop(Iop_Or32, 2541 binop(Iop_And32, 2542 binop(Iop_Shr32, mkexpr(irRes), mkU8(5)), 2543 mkU32(3)), 2544 binop(Iop_And32, mkexpr(irRes), mkU32(1)))); 2545 2546 assign( 2547 termL, 2548 binop(Iop_Add32, 2549 binop(Iop_Shr32, 2550 binop(Iop_Sub32, 2551 binop(Iop_Shl32, 2552 binop(Iop_Xor32, mkexpr(ix), mkU32(1)), 2553 mkU8(30)), 2554 mkU32(1)), 2555 mkU8(29)), 2556 mkU32(1))); 2557 2558 assign( 2559 termR, 2560 binop(Iop_And32, 2561 binop(Iop_And32, 2562 mkexpr(ix), 2563 binop(Iop_Shr32, mkexpr(ix), mkU8(1))), 2564 mkU32(1))); 2565 2566 assign(nzcv, binop(Iop_Sub32, mkexpr(termL), mkexpr(termR))); 2567 return nzcv; 2568 } 2569 2570 2571 /* Thumb32 only. This is "ThumbExpandImm" in the ARM ARM. If 2572 updatesC is non-NULL, a boolean is written to it indicating whether 2573 or not the C flag is updated, as per ARM ARM "ThumbExpandImm_C". 2574 */ 2575 static UInt thumbExpandImm ( Bool* updatesC, 2576 UInt imm1, UInt imm3, UInt imm8 ) 2577 { 2578 vassert(imm1 < (1<<1)); 2579 vassert(imm3 < (1<<3)); 2580 vassert(imm8 < (1<<8)); 2581 UInt i_imm3_a = (imm1 << 4) | (imm3 << 1) | ((imm8 >> 7) & 1); 2582 UInt abcdefgh = imm8; 2583 UInt lbcdefgh = imm8 | 0x80; 2584 if (updatesC) { 2585 *updatesC = i_imm3_a >= 8; 2586 } 2587 switch (i_imm3_a) { 2588 case 0: case 1: 2589 return abcdefgh; 2590 case 2: case 3: 2591 return (abcdefgh << 16) | abcdefgh; 2592 case 4: case 5: 2593 return (abcdefgh << 24) | (abcdefgh << 8); 2594 case 6: case 7: 2595 return (abcdefgh << 24) | (abcdefgh << 16) 2596 | (abcdefgh << 8) | abcdefgh; 2597 case 8 ... 31: 2598 return lbcdefgh << (32 - i_imm3_a); 2599 default: 2600 break; 2601 } 2602 /*NOTREACHED*/vassert(0); 2603 } 2604 2605 2606 /* Version of thumbExpandImm where we simply feed it the 2607 instruction halfwords (the lowest addressed one is I0). */ 2608 static UInt thumbExpandImm_from_I0_I1 ( Bool* updatesC, 2609 UShort i0s, UShort i1s ) 2610 { 2611 UInt i0 = (UInt)i0s; 2612 UInt i1 = (UInt)i1s; 2613 UInt imm1 = SLICE_UInt(i0,10,10); 2614 UInt imm3 = SLICE_UInt(i1,14,12); 2615 UInt imm8 = SLICE_UInt(i1,7,0); 2616 return thumbExpandImm(updatesC, imm1, imm3, imm8); 2617 } 2618 2619 2620 /* Thumb16 only. Given the firstcond and mask fields from an IT 2621 instruction, compute the 32-bit ITSTATE value implied, as described 2622 in libvex_guest_arm.h. This is not the ARM ARM representation. 2623 Also produce the t/e chars for the 2nd, 3rd, 4th insns, for 2624 disassembly printing. Returns False if firstcond or mask 2625 denote something invalid. 2626 2627 The number and conditions for the instructions to be 2628 conditionalised depend on firstcond and mask: 2629 2630 mask cond 1 cond 2 cond 3 cond 4 2631 2632 1000 fc[3:0] 2633 x100 fc[3:0] fc[3:1]:x 2634 xy10 fc[3:0] fc[3:1]:x fc[3:1]:y 2635 xyz1 fc[3:0] fc[3:1]:x fc[3:1]:y fc[3:1]:z 2636 2637 The condition fields are assembled in *itstate backwards (cond 4 at 2638 the top, cond 1 at the bottom). Conditions are << 4'd and then 2639 ^0xE'd, and those fields that correspond to instructions in the IT 2640 block are tagged with a 1 bit. 2641 */ 2642 static Bool compute_ITSTATE ( /*OUT*/UInt* itstate, 2643 /*OUT*/UChar* ch1, 2644 /*OUT*/UChar* ch2, 2645 /*OUT*/UChar* ch3, 2646 UInt firstcond, UInt mask ) 2647 { 2648 vassert(firstcond <= 0xF); 2649 vassert(mask <= 0xF); 2650 *itstate = 0; 2651 *ch1 = *ch2 = *ch3 = '.'; 2652 if (mask == 0) 2653 return False; /* the logic below actually ensures this anyway, 2654 but clearer to make it explicit. */ 2655 if (firstcond == 0xF) 2656 return False; /* NV is not allowed */ 2657 if (firstcond == 0xE && popcount32(mask) != 1) 2658 return False; /* if firstcond is AL then all the rest must be too */ 2659 2660 UInt m3 = (mask >> 3) & 1; 2661 UInt m2 = (mask >> 2) & 1; 2662 UInt m1 = (mask >> 1) & 1; 2663 UInt m0 = (mask >> 0) & 1; 2664 2665 UInt fc = (firstcond << 4) | 1/*in-IT-block*/; 2666 UInt ni = (0xE/*AL*/ << 4) | 0/*not-in-IT-block*/; 2667 2668 if (m3 == 1 && (m2|m1|m0) == 0) { 2669 *itstate = (ni << 24) | (ni << 16) | (ni << 8) | fc; 2670 *itstate ^= 0xE0E0E0E0; 2671 return True; 2672 } 2673 2674 if (m2 == 1 && (m1|m0) == 0) { 2675 *itstate = (ni << 24) | (ni << 16) | (setbit32(fc, 4, m3) << 8) | fc; 2676 *itstate ^= 0xE0E0E0E0; 2677 *ch1 = m3 == (firstcond & 1) ? 't' : 'e'; 2678 return True; 2679 } 2680 2681 if (m1 == 1 && m0 == 0) { 2682 *itstate = (ni << 24) 2683 | (setbit32(fc, 4, m2) << 16) 2684 | (setbit32(fc, 4, m3) << 8) | fc; 2685 *itstate ^= 0xE0E0E0E0; 2686 *ch1 = m3 == (firstcond & 1) ? 't' : 'e'; 2687 *ch2 = m2 == (firstcond & 1) ? 't' : 'e'; 2688 return True; 2689 } 2690 2691 if (m0 == 1) { 2692 *itstate = (setbit32(fc, 4, m1) << 24) 2693 | (setbit32(fc, 4, m2) << 16) 2694 | (setbit32(fc, 4, m3) << 8) | fc; 2695 *itstate ^= 0xE0E0E0E0; 2696 *ch1 = m3 == (firstcond & 1) ? 't' : 'e'; 2697 *ch2 = m2 == (firstcond & 1) ? 't' : 'e'; 2698 *ch3 = m1 == (firstcond & 1) ? 't' : 'e'; 2699 return True; 2700 } 2701 2702 return False; 2703 } 2704 2705 2706 /* Generate IR to do 32-bit bit reversal, a la Hacker's Delight 2707 Chapter 7 Section 1. */ 2708 static IRTemp gen_BITREV ( IRTemp x0 ) 2709 { 2710 IRTemp x1 = newTemp(Ity_I32); 2711 IRTemp x2 = newTemp(Ity_I32); 2712 IRTemp x3 = newTemp(Ity_I32); 2713 IRTemp x4 = newTemp(Ity_I32); 2714 IRTemp x5 = newTemp(Ity_I32); 2715 UInt c1 = 0x55555555; 2716 UInt c2 = 0x33333333; 2717 UInt c3 = 0x0F0F0F0F; 2718 UInt c4 = 0x00FF00FF; 2719 UInt c5 = 0x0000FFFF; 2720 assign(x1, 2721 binop(Iop_Or32, 2722 binop(Iop_Shl32, 2723 binop(Iop_And32, mkexpr(x0), mkU32(c1)), 2724 mkU8(1)), 2725 binop(Iop_Shr32, 2726 binop(Iop_And32, mkexpr(x0), mkU32(~c1)), 2727 mkU8(1)) 2728 )); 2729 assign(x2, 2730 binop(Iop_Or32, 2731 binop(Iop_Shl32, 2732 binop(Iop_And32, mkexpr(x1), mkU32(c2)), 2733 mkU8(2)), 2734 binop(Iop_Shr32, 2735 binop(Iop_And32, mkexpr(x1), mkU32(~c2)), 2736 mkU8(2)) 2737 )); 2738 assign(x3, 2739 binop(Iop_Or32, 2740 binop(Iop_Shl32, 2741 binop(Iop_And32, mkexpr(x2), mkU32(c3)), 2742 mkU8(4)), 2743 binop(Iop_Shr32, 2744 binop(Iop_And32, mkexpr(x2), mkU32(~c3)), 2745 mkU8(4)) 2746 )); 2747 assign(x4, 2748 binop(Iop_Or32, 2749 binop(Iop_Shl32, 2750 binop(Iop_And32, mkexpr(x3), mkU32(c4)), 2751 mkU8(8)), 2752 binop(Iop_Shr32, 2753 binop(Iop_And32, mkexpr(x3), mkU32(~c4)), 2754 mkU8(8)) 2755 )); 2756 assign(x5, 2757 binop(Iop_Or32, 2758 binop(Iop_Shl32, 2759 binop(Iop_And32, mkexpr(x4), mkU32(c5)), 2760 mkU8(16)), 2761 binop(Iop_Shr32, 2762 binop(Iop_And32, mkexpr(x4), mkU32(~c5)), 2763 mkU8(16)) 2764 )); 2765 return x5; 2766 } 2767 2768 2769 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order 2770 0:1:2:3 (aka byte-swap). */ 2771 static IRTemp gen_REV ( IRTemp arg ) 2772 { 2773 IRTemp res = newTemp(Ity_I32); 2774 assign(res, 2775 binop(Iop_Or32, 2776 binop(Iop_Shl32, mkexpr(arg), mkU8(24)), 2777 binop(Iop_Or32, 2778 binop(Iop_And32, binop(Iop_Shl32, mkexpr(arg), mkU8(8)), 2779 mkU32(0x00FF0000)), 2780 binop(Iop_Or32, 2781 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(8)), 2782 mkU32(0x0000FF00)), 2783 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(24)), 2784 mkU32(0x000000FF) ) 2785 )))); 2786 return res; 2787 } 2788 2789 2790 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order 2791 2:3:0:1 (swap within lo and hi halves). */ 2792 static IRTemp gen_REV16 ( IRTemp arg ) 2793 { 2794 IRTemp res = newTemp(Ity_I32); 2795 assign(res, 2796 binop(Iop_Or32, 2797 binop(Iop_And32, 2798 binop(Iop_Shl32, mkexpr(arg), mkU8(8)), 2799 mkU32(0xFF00FF00)), 2800 binop(Iop_And32, 2801 binop(Iop_Shr32, mkexpr(arg), mkU8(8)), 2802 mkU32(0x00FF00FF)))); 2803 return res; 2804 } 2805 2806 2807 /*------------------------------------------------------------*/ 2808 /*--- Advanced SIMD (NEON) instructions ---*/ 2809 /*------------------------------------------------------------*/ 2810 2811 /*------------------------------------------------------------*/ 2812 /*--- NEON data processing ---*/ 2813 /*------------------------------------------------------------*/ 2814 2815 /* For all NEON DP ops, we use the normal scheme to handle conditional 2816 writes to registers -- pass in condT and hand that on to the 2817 put*Reg functions. In ARM mode condT is always IRTemp_INVALID 2818 since NEON is unconditional for ARM. In Thumb mode condT is 2819 derived from the ITSTATE shift register in the normal way. */ 2820 2821 static 2822 UInt get_neon_d_regno(UInt theInstr) 2823 { 2824 UInt x = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF); 2825 if (theInstr & 0x40) { 2826 if (x & 1) { 2827 x = x + 0x100; 2828 } else { 2829 x = x >> 1; 2830 } 2831 } 2832 return x; 2833 } 2834 2835 static 2836 UInt get_neon_n_regno(UInt theInstr) 2837 { 2838 UInt x = ((theInstr >> 3) & 0x10) | ((theInstr >> 16) & 0xF); 2839 if (theInstr & 0x40) { 2840 if (x & 1) { 2841 x = x + 0x100; 2842 } else { 2843 x = x >> 1; 2844 } 2845 } 2846 return x; 2847 } 2848 2849 static 2850 UInt get_neon_m_regno(UInt theInstr) 2851 { 2852 UInt x = ((theInstr >> 1) & 0x10) | (theInstr & 0xF); 2853 if (theInstr & 0x40) { 2854 if (x & 1) { 2855 x = x + 0x100; 2856 } else { 2857 x = x >> 1; 2858 } 2859 } 2860 return x; 2861 } 2862 2863 static 2864 Bool dis_neon_vext ( UInt theInstr, IRTemp condT ) 2865 { 2866 UInt dreg = get_neon_d_regno(theInstr); 2867 UInt mreg = get_neon_m_regno(theInstr); 2868 UInt nreg = get_neon_n_regno(theInstr); 2869 UInt imm4 = (theInstr >> 8) & 0xf; 2870 UInt Q = (theInstr >> 6) & 1; 2871 HChar reg_t = Q ? 'q' : 'd'; 2872 2873 if (Q) { 2874 putQReg(dreg, triop(Iop_ExtractV128, getQReg(nreg), 2875 getQReg(mreg), mkU8(imm4)), condT); 2876 } else { 2877 putDRegI64(dreg, triop(Iop_Extract64, getDRegI64(nreg), 2878 getDRegI64(mreg), mkU8(imm4)), condT); 2879 } 2880 DIP("vext.8 %c%d, %c%d, %c%d, #%d\n", reg_t, dreg, reg_t, nreg, 2881 reg_t, mreg, imm4); 2882 return True; 2883 } 2884 2885 /* VTBL, VTBX */ 2886 static 2887 Bool dis_neon_vtb ( UInt theInstr, IRTemp condT ) 2888 { 2889 UInt op = (theInstr >> 6) & 1; 2890 UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6)); 2891 UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6)); 2892 UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6)); 2893 UInt len = (theInstr >> 8) & 3; 2894 Int i; 2895 IROp cmp; 2896 ULong imm; 2897 IRTemp arg_l; 2898 IRTemp old_mask, new_mask, cur_mask; 2899 IRTemp old_res, new_res; 2900 IRTemp old_arg, new_arg; 2901 2902 if (dreg >= 0x100 || mreg >= 0x100 || nreg >= 0x100) 2903 return False; 2904 if (nreg + len > 31) 2905 return False; 2906 2907 cmp = Iop_CmpGT8Ux8; 2908 2909 old_mask = newTemp(Ity_I64); 2910 old_res = newTemp(Ity_I64); 2911 old_arg = newTemp(Ity_I64); 2912 assign(old_mask, mkU64(0)); 2913 assign(old_res, mkU64(0)); 2914 assign(old_arg, getDRegI64(mreg)); 2915 imm = 8; 2916 imm = (imm << 8) | imm; 2917 imm = (imm << 16) | imm; 2918 imm = (imm << 32) | imm; 2919 2920 for (i = 0; i <= len; i++) { 2921 arg_l = newTemp(Ity_I64); 2922 new_mask = newTemp(Ity_I64); 2923 cur_mask = newTemp(Ity_I64); 2924 new_res = newTemp(Ity_I64); 2925 new_arg = newTemp(Ity_I64); 2926 assign(arg_l, getDRegI64(nreg+i)); 2927 assign(new_arg, binop(Iop_Sub8x8, mkexpr(old_arg), mkU64(imm))); 2928 assign(cur_mask, binop(cmp, mkU64(imm), mkexpr(old_arg))); 2929 assign(new_mask, binop(Iop_Or64, mkexpr(old_mask), mkexpr(cur_mask))); 2930 assign(new_res, binop(Iop_Or64, 2931 mkexpr(old_res), 2932 binop(Iop_And64, 2933 binop(Iop_Perm8x8, 2934 mkexpr(arg_l), 2935 binop(Iop_And64, 2936 mkexpr(old_arg), 2937 mkexpr(cur_mask))), 2938 mkexpr(cur_mask)))); 2939 2940 old_arg = new_arg; 2941 old_mask = new_mask; 2942 old_res = new_res; 2943 } 2944 if (op) { 2945 new_res = newTemp(Ity_I64); 2946 assign(new_res, binop(Iop_Or64, 2947 binop(Iop_And64, 2948 getDRegI64(dreg), 2949 unop(Iop_Not64, mkexpr(old_mask))), 2950 mkexpr(old_res))); 2951 old_res = new_res; 2952 } 2953 2954 putDRegI64(dreg, mkexpr(old_res), condT); 2955 DIP("vtb%c.8 d%u, {", op ? 'x' : 'l', dreg); 2956 if (len > 0) { 2957 DIP("d%u-d%u", nreg, nreg + len); 2958 } else { 2959 DIP("d%u", nreg); 2960 } 2961 DIP("}, d%u\n", mreg); 2962 return True; 2963 } 2964 2965 /* VDUP (scalar) */ 2966 static 2967 Bool dis_neon_vdup ( UInt theInstr, IRTemp condT ) 2968 { 2969 UInt Q = (theInstr >> 6) & 1; 2970 UInt dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF); 2971 UInt mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF); 2972 UInt imm4 = (theInstr >> 16) & 0xF; 2973 UInt index; 2974 UInt size; 2975 IRTemp arg_m; 2976 IRTemp res; 2977 IROp op, op2; 2978 2979 if ((imm4 == 0) || (imm4 == 8)) 2980 return False; 2981 if ((Q == 1) && ((dreg & 1) == 1)) 2982 return False; 2983 if (Q) 2984 dreg >>= 1; 2985 arg_m = newTemp(Ity_I64); 2986 assign(arg_m, getDRegI64(mreg)); 2987 if (Q) 2988 res = newTemp(Ity_V128); 2989 else 2990 res = newTemp(Ity_I64); 2991 if ((imm4 & 1) == 1) { 2992 op = Q ? Iop_Dup8x16 : Iop_Dup8x8; 2993 op2 = Iop_GetElem8x8; 2994 index = imm4 >> 1; 2995 size = 8; 2996 } else if ((imm4 & 3) == 2) { 2997 op = Q ? Iop_Dup16x8 : Iop_Dup16x4; 2998 op2 = Iop_GetElem16x4; 2999 index = imm4 >> 2; 3000 size = 16; 3001 } else if ((imm4 & 7) == 4) { 3002 op = Q ? Iop_Dup32x4 : Iop_Dup32x2; 3003 op2 = Iop_GetElem32x2; 3004 index = imm4 >> 3; 3005 size = 32; 3006 } else { 3007 return False; // can this ever happen? 3008 } 3009 assign(res, unop(op, binop(op2, mkexpr(arg_m), mkU8(index)))); 3010 if (Q) { 3011 putQReg(dreg, mkexpr(res), condT); 3012 } else { 3013 putDRegI64(dreg, mkexpr(res), condT); 3014 } 3015 DIP("vdup.%d %c%d, d%d[%d]\n", size, Q ? 'q' : 'd', dreg, mreg, index); 3016 return True; 3017 } 3018 3019 /* A7.4.1 Three registers of the same length */ 3020 static 3021 Bool dis_neon_data_3same ( UInt theInstr, IRTemp condT ) 3022 { 3023 UInt Q = (theInstr >> 6) & 1; 3024 UInt dreg = get_neon_d_regno(theInstr); 3025 UInt nreg = get_neon_n_regno(theInstr); 3026 UInt mreg = get_neon_m_regno(theInstr); 3027 UInt A = (theInstr >> 8) & 0xF; 3028 UInt B = (theInstr >> 4) & 1; 3029 UInt C = (theInstr >> 20) & 0x3; 3030 UInt U = (theInstr >> 24) & 1; 3031 UInt size = C; 3032 3033 IRTemp arg_n; 3034 IRTemp arg_m; 3035 IRTemp res; 3036 3037 if (Q) { 3038 arg_n = newTemp(Ity_V128); 3039 arg_m = newTemp(Ity_V128); 3040 res = newTemp(Ity_V128); 3041 assign(arg_n, getQReg(nreg)); 3042 assign(arg_m, getQReg(mreg)); 3043 } else { 3044 arg_n = newTemp(Ity_I64); 3045 arg_m = newTemp(Ity_I64); 3046 res = newTemp(Ity_I64); 3047 assign(arg_n, getDRegI64(nreg)); 3048 assign(arg_m, getDRegI64(mreg)); 3049 } 3050 3051 switch(A) { 3052 case 0: 3053 if (B == 0) { 3054 /* VHADD */ 3055 ULong imm = 0; 3056 IRExpr *imm_val; 3057 IROp addOp; 3058 IROp andOp; 3059 IROp shOp; 3060 char regType = Q ? 'q' : 'd'; 3061 3062 if (size == 3) 3063 return False; 3064 switch(size) { 3065 case 0: imm = 0x101010101010101LL; break; 3066 case 1: imm = 0x1000100010001LL; break; 3067 case 2: imm = 0x100000001LL; break; 3068 default: vassert(0); 3069 } 3070 if (Q) { 3071 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)); 3072 andOp = Iop_AndV128; 3073 } else { 3074 imm_val = mkU64(imm); 3075 andOp = Iop_And64; 3076 } 3077 if (U) { 3078 switch(size) { 3079 case 0: 3080 addOp = Q ? Iop_Add8x16 : Iop_Add8x8; 3081 shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3082 break; 3083 case 1: 3084 addOp = Q ? Iop_Add16x8 : Iop_Add16x4; 3085 shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3086 break; 3087 case 2: 3088 addOp = Q ? Iop_Add32x4 : Iop_Add32x2; 3089 shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3090 break; 3091 default: 3092 vassert(0); 3093 } 3094 } else { 3095 switch(size) { 3096 case 0: 3097 addOp = Q ? Iop_Add8x16 : Iop_Add8x8; 3098 shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8; 3099 break; 3100 case 1: 3101 addOp = Q ? Iop_Add16x8 : Iop_Add16x4; 3102 shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4; 3103 break; 3104 case 2: 3105 addOp = Q ? Iop_Add32x4 : Iop_Add32x2; 3106 shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2; 3107 break; 3108 default: 3109 vassert(0); 3110 } 3111 } 3112 assign(res, 3113 binop(addOp, 3114 binop(addOp, 3115 binop(shOp, mkexpr(arg_m), mkU8(1)), 3116 binop(shOp, mkexpr(arg_n), mkU8(1))), 3117 binop(shOp, 3118 binop(addOp, 3119 binop(andOp, mkexpr(arg_m), imm_val), 3120 binop(andOp, mkexpr(arg_n), imm_val)), 3121 mkU8(1)))); 3122 DIP("vhadd.%c%d %c%d, %c%d, %c%d\n", 3123 U ? 'u' : 's', 8 << size, regType, 3124 dreg, regType, nreg, regType, mreg); 3125 } else { 3126 /* VQADD */ 3127 IROp op, op2; 3128 IRTemp tmp; 3129 char reg_t = Q ? 'q' : 'd'; 3130 if (Q) { 3131 switch (size) { 3132 case 0: 3133 op = U ? Iop_QAdd8Ux16 : Iop_QAdd8Sx16; 3134 op2 = Iop_Add8x16; 3135 break; 3136 case 1: 3137 op = U ? Iop_QAdd16Ux8 : Iop_QAdd16Sx8; 3138 op2 = Iop_Add16x8; 3139 break; 3140 case 2: 3141 op = U ? Iop_QAdd32Ux4 : Iop_QAdd32Sx4; 3142 op2 = Iop_Add32x4; 3143 break; 3144 case 3: 3145 op = U ? Iop_QAdd64Ux2 : Iop_QAdd64Sx2; 3146 op2 = Iop_Add64x2; 3147 break; 3148 default: 3149 vassert(0); 3150 } 3151 } else { 3152 switch (size) { 3153 case 0: 3154 op = U ? Iop_QAdd8Ux8 : Iop_QAdd8Sx8; 3155 op2 = Iop_Add8x8; 3156 break; 3157 case 1: 3158 op = U ? Iop_QAdd16Ux4 : Iop_QAdd16Sx4; 3159 op2 = Iop_Add16x4; 3160 break; 3161 case 2: 3162 op = U ? Iop_QAdd32Ux2 : Iop_QAdd32Sx2; 3163 op2 = Iop_Add32x2; 3164 break; 3165 case 3: 3166 op = U ? Iop_QAdd64Ux1 : Iop_QAdd64Sx1; 3167 op2 = Iop_Add64; 3168 break; 3169 default: 3170 vassert(0); 3171 } 3172 } 3173 if (Q) { 3174 tmp = newTemp(Ity_V128); 3175 } else { 3176 tmp = newTemp(Ity_I64); 3177 } 3178 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 3179 #ifndef DISABLE_QC_FLAG 3180 assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m))); 3181 setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT); 3182 #endif 3183 DIP("vqadd.%c%d %c%d, %c%d, %c%d\n", 3184 U ? 'u' : 's', 3185 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg); 3186 } 3187 break; 3188 case 1: 3189 if (B == 0) { 3190 /* VRHADD */ 3191 /* VRHADD C, A, B ::= 3192 C = (A >> 1) + (B >> 1) + (((A & 1) + (B & 1) + 1) >> 1) */ 3193 IROp shift_op, add_op; 3194 IRTemp cc; 3195 ULong one = 1; 3196 HChar reg_t = Q ? 'q' : 'd'; 3197 switch (size) { 3198 case 0: one = (one << 8) | one; /* fall through */ 3199 case 1: one = (one << 16) | one; /* fall through */ 3200 case 2: one = (one << 32) | one; break; 3201 case 3: return False; 3202 default: vassert(0); 3203 } 3204 if (Q) { 3205 switch (size) { 3206 case 0: 3207 shift_op = U ? Iop_ShrN8x16 : Iop_SarN8x16; 3208 add_op = Iop_Add8x16; 3209 break; 3210 case 1: 3211 shift_op = U ? Iop_ShrN16x8 : Iop_SarN16x8; 3212 add_op = Iop_Add16x8; 3213 break; 3214 case 2: 3215 shift_op = U ? Iop_ShrN32x4 : Iop_SarN32x4; 3216 add_op = Iop_Add32x4; 3217 break; 3218 case 3: 3219 return False; 3220 default: 3221 vassert(0); 3222 } 3223 } else { 3224 switch (size) { 3225 case 0: 3226 shift_op = U ? Iop_ShrN8x8 : Iop_SarN8x8; 3227 add_op = Iop_Add8x8; 3228 break; 3229 case 1: 3230 shift_op = U ? Iop_ShrN16x4 : Iop_SarN16x4; 3231 add_op = Iop_Add16x4; 3232 break; 3233 case 2: 3234 shift_op = U ? Iop_ShrN32x2 : Iop_SarN32x2; 3235 add_op = Iop_Add32x2; 3236 break; 3237 case 3: 3238 return False; 3239 default: 3240 vassert(0); 3241 } 3242 } 3243 if (Q) { 3244 cc = newTemp(Ity_V128); 3245 assign(cc, binop(shift_op, 3246 binop(add_op, 3247 binop(add_op, 3248 binop(Iop_AndV128, 3249 mkexpr(arg_n), 3250 binop(Iop_64HLtoV128, 3251 mkU64(one), 3252 mkU64(one))), 3253 binop(Iop_AndV128, 3254 mkexpr(arg_m), 3255 binop(Iop_64HLtoV128, 3256 mkU64(one), 3257 mkU64(one)))), 3258 binop(Iop_64HLtoV128, 3259 mkU64(one), 3260 mkU64(one))), 3261 mkU8(1))); 3262 assign(res, binop(add_op, 3263 binop(add_op, 3264 binop(shift_op, 3265 mkexpr(arg_n), 3266 mkU8(1)), 3267 binop(shift_op, 3268 mkexpr(arg_m), 3269 mkU8(1))), 3270 mkexpr(cc))); 3271 } else { 3272 cc = newTemp(Ity_I64); 3273 assign(cc, binop(shift_op, 3274 binop(add_op, 3275 binop(add_op, 3276 binop(Iop_And64, 3277 mkexpr(arg_n), 3278 mkU64(one)), 3279 binop(Iop_And64, 3280 mkexpr(arg_m), 3281 mkU64(one))), 3282 mkU64(one)), 3283 mkU8(1))); 3284 assign(res, binop(add_op, 3285 binop(add_op, 3286 binop(shift_op, 3287 mkexpr(arg_n), 3288 mkU8(1)), 3289 binop(shift_op, 3290 mkexpr(arg_m), 3291 mkU8(1))), 3292 mkexpr(cc))); 3293 } 3294 DIP("vrhadd.%c%d %c%d, %c%d, %c%d\n", 3295 U ? 'u' : 's', 3296 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg); 3297 } else { 3298 if (U == 0) { 3299 switch(C) { 3300 case 0: { 3301 /* VAND */ 3302 HChar reg_t = Q ? 'q' : 'd'; 3303 if (Q) { 3304 assign(res, binop(Iop_AndV128, mkexpr(arg_n), 3305 mkexpr(arg_m))); 3306 } else { 3307 assign(res, binop(Iop_And64, mkexpr(arg_n), 3308 mkexpr(arg_m))); 3309 } 3310 DIP("vand %c%d, %c%d, %c%d\n", 3311 reg_t, dreg, reg_t, nreg, reg_t, mreg); 3312 break; 3313 } 3314 case 1: { 3315 /* VBIC */ 3316 HChar reg_t = Q ? 'q' : 'd'; 3317 if (Q) { 3318 assign(res, binop(Iop_AndV128,mkexpr(arg_n), 3319 unop(Iop_NotV128, mkexpr(arg_m)))); 3320 } else { 3321 assign(res, binop(Iop_And64, mkexpr(arg_n), 3322 unop(Iop_Not64, mkexpr(arg_m)))); 3323 } 3324 DIP("vbic %c%d, %c%d, %c%d\n", 3325 reg_t, dreg, reg_t, nreg, reg_t, mreg); 3326 break; 3327 } 3328 case 2: 3329 if ( nreg != mreg) { 3330 /* VORR */ 3331 HChar reg_t = Q ? 'q' : 'd'; 3332 if (Q) { 3333 assign(res, binop(Iop_OrV128, mkexpr(arg_n), 3334 mkexpr(arg_m))); 3335 } else { 3336 assign(res, binop(Iop_Or64, mkexpr(arg_n), 3337 mkexpr(arg_m))); 3338 } 3339 DIP("vorr %c%d, %c%d, %c%d\n", 3340 reg_t, dreg, reg_t, nreg, reg_t, mreg); 3341 } else { 3342 /* VMOV */ 3343 HChar reg_t = Q ? 'q' : 'd'; 3344 assign(res, mkexpr(arg_m)); 3345 DIP("vmov %c%d, %c%d\n", reg_t, dreg, reg_t, mreg); 3346 } 3347 break; 3348 case 3:{ 3349 /* VORN */ 3350 HChar reg_t = Q ? 'q' : 'd'; 3351 if (Q) { 3352 assign(res, binop(Iop_OrV128,mkexpr(arg_n), 3353 unop(Iop_NotV128, mkexpr(arg_m)))); 3354 } else { 3355 assign(res, binop(Iop_Or64, mkexpr(arg_n), 3356 unop(Iop_Not64, mkexpr(arg_m)))); 3357 } 3358 DIP("vorn %c%d, %c%d, %c%d\n", 3359 reg_t, dreg, reg_t, nreg, reg_t, mreg); 3360 break; 3361 } 3362 } 3363 } else { 3364 switch(C) { 3365 case 0: 3366 /* VEOR (XOR) */ 3367 if (Q) { 3368 assign(res, binop(Iop_XorV128, mkexpr(arg_n), 3369 mkexpr(arg_m))); 3370 } else { 3371 assign(res, binop(Iop_Xor64, mkexpr(arg_n), 3372 mkexpr(arg_m))); 3373 } 3374 DIP("veor %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg, 3375 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 3376 break; 3377 case 1: 3378 /* VBSL */ 3379 if (Q) { 3380 IRTemp reg_d = newTemp(Ity_V128); 3381 assign(reg_d, getQReg(dreg)); 3382 assign(res, 3383 binop(Iop_OrV128, 3384 binop(Iop_AndV128, mkexpr(arg_n), 3385 mkexpr(reg_d)), 3386 binop(Iop_AndV128, 3387 mkexpr(arg_m), 3388 unop(Iop_NotV128, 3389 mkexpr(reg_d)) ) ) ); 3390 } else { 3391 IRTemp reg_d = newTemp(Ity_I64); 3392 assign(reg_d, getDRegI64(dreg)); 3393 assign(res, 3394 binop(Iop_Or64, 3395 binop(Iop_And64, mkexpr(arg_n), 3396 mkexpr(reg_d)), 3397 binop(Iop_And64, 3398 mkexpr(arg_m), 3399 unop(Iop_Not64, mkexpr(reg_d))))); 3400 } 3401 DIP("vbsl %c%u, %c%u, %c%u\n", 3402 Q ? 'q' : 'd', dreg, 3403 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 3404 break; 3405 case 2: 3406 /* VBIT */ 3407 if (Q) { 3408 IRTemp reg_d = newTemp(Ity_V128); 3409 assign(reg_d, getQReg(dreg)); 3410 assign(res, 3411 binop(Iop_OrV128, 3412 binop(Iop_AndV128, mkexpr(arg_n), 3413 mkexpr(arg_m)), 3414 binop(Iop_AndV128, 3415 mkexpr(reg_d), 3416 unop(Iop_NotV128, mkexpr(arg_m))))); 3417 } else { 3418 IRTemp reg_d = newTemp(Ity_I64); 3419 assign(reg_d, getDRegI64(dreg)); 3420 assign(res, 3421 binop(Iop_Or64, 3422 binop(Iop_And64, mkexpr(arg_n), 3423 mkexpr(arg_m)), 3424 binop(Iop_And64, 3425 mkexpr(reg_d), 3426 unop(Iop_Not64, mkexpr(arg_m))))); 3427 } 3428 DIP("vbit %c%u, %c%u, %c%u\n", 3429 Q ? 'q' : 'd', dreg, 3430 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 3431 break; 3432 case 3: 3433 /* VBIF */ 3434 if (Q) { 3435 IRTemp reg_d = newTemp(Ity_V128); 3436 assign(reg_d, getQReg(dreg)); 3437 assign(res, 3438 binop(Iop_OrV128, 3439 binop(Iop_AndV128, mkexpr(reg_d), 3440 mkexpr(arg_m)), 3441 binop(Iop_AndV128, 3442 mkexpr(arg_n), 3443 unop(Iop_NotV128, mkexpr(arg_m))))); 3444 } else { 3445 IRTemp reg_d = newTemp(Ity_I64); 3446 assign(reg_d, getDRegI64(dreg)); 3447 assign(res, 3448 binop(Iop_Or64, 3449 binop(Iop_And64, mkexpr(reg_d), 3450 mkexpr(arg_m)), 3451 binop(Iop_And64, 3452 mkexpr(arg_n), 3453 unop(Iop_Not64, mkexpr(arg_m))))); 3454 } 3455 DIP("vbif %c%u, %c%u, %c%u\n", 3456 Q ? 'q' : 'd', dreg, 3457 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 3458 break; 3459 } 3460 } 3461 } 3462 break; 3463 case 2: 3464 if (B == 0) { 3465 /* VHSUB */ 3466 /* (A >> 1) - (B >> 1) - (NOT (A) & B & 1) */ 3467 ULong imm = 0; 3468 IRExpr *imm_val; 3469 IROp subOp; 3470 IROp notOp; 3471 IROp andOp; 3472 IROp shOp; 3473 if (size == 3) 3474 return False; 3475 switch(size) { 3476 case 0: imm = 0x101010101010101LL; break; 3477 case 1: imm = 0x1000100010001LL; break; 3478 case 2: imm = 0x100000001LL; break; 3479 default: vassert(0); 3480 } 3481 if (Q) { 3482 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)); 3483 andOp = Iop_AndV128; 3484 notOp = Iop_NotV128; 3485 } else { 3486 imm_val = mkU64(imm); 3487 andOp = Iop_And64; 3488 notOp = Iop_Not64; 3489 } 3490 if (U) { 3491 switch(size) { 3492 case 0: 3493 subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8; 3494 shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3495 break; 3496 case 1: 3497 subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4; 3498 shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3499 break; 3500 case 2: 3501 subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2; 3502 shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3503 break; 3504 default: 3505 vassert(0); 3506 } 3507 } else { 3508 switch(size) { 3509 case 0: 3510 subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8; 3511 shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8; 3512 break; 3513 case 1: 3514 subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4; 3515 shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4; 3516 break; 3517 case 2: 3518 subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2; 3519 shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2; 3520 break; 3521 default: 3522 vassert(0); 3523 } 3524 } 3525 assign(res, 3526 binop(subOp, 3527 binop(subOp, 3528 binop(shOp, mkexpr(arg_n), mkU8(1)), 3529 binop(shOp, mkexpr(arg_m), mkU8(1))), 3530 binop(andOp, 3531 binop(andOp, 3532 unop(notOp, mkexpr(arg_n)), 3533 mkexpr(arg_m)), 3534 imm_val))); 3535 DIP("vhsub.%c%u %c%u, %c%u, %c%u\n", 3536 U ? 'u' : 's', 8 << size, 3537 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 3538 mreg); 3539 } else { 3540 /* VQSUB */ 3541 IROp op, op2; 3542 IRTemp tmp; 3543 if (Q) { 3544 switch (size) { 3545 case 0: 3546 op = U ? Iop_QSub8Ux16 : Iop_QSub8Sx16; 3547 op2 = Iop_Sub8x16; 3548 break; 3549 case 1: 3550 op = U ? Iop_QSub16Ux8 : Iop_QSub16Sx8; 3551 op2 = Iop_Sub16x8; 3552 break; 3553 case 2: 3554 op = U ? Iop_QSub32Ux4 : Iop_QSub32Sx4; 3555 op2 = Iop_Sub32x4; 3556 break; 3557 case 3: 3558 op = U ? Iop_QSub64Ux2 : Iop_QSub64Sx2; 3559 op2 = Iop_Sub64x2; 3560 break; 3561 default: 3562 vassert(0); 3563 } 3564 } else { 3565 switch (size) { 3566 case 0: 3567 op = U ? Iop_QSub8Ux8 : Iop_QSub8Sx8; 3568 op2 = Iop_Sub8x8; 3569 break; 3570 case 1: 3571 op = U ? Iop_QSub16Ux4 : Iop_QSub16Sx4; 3572 op2 = Iop_Sub16x4; 3573 break; 3574 case 2: 3575 op = U ? Iop_QSub32Ux2 : Iop_QSub32Sx2; 3576 op2 = Iop_Sub32x2; 3577 break; 3578 case 3: 3579 op = U ? Iop_QSub64Ux1 : Iop_QSub64Sx1; 3580 op2 = Iop_Sub64; 3581 break; 3582 default: 3583 vassert(0); 3584 } 3585 } 3586 if (Q) 3587 tmp = newTemp(Ity_V128); 3588 else 3589 tmp = newTemp(Ity_I64); 3590 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 3591 #ifndef DISABLE_QC_FLAG 3592 assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m))); 3593 setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT); 3594 #endif 3595 DIP("vqsub.%c%u %c%u, %c%u, %c%u\n", 3596 U ? 'u' : 's', 8 << size, 3597 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 3598 mreg); 3599 } 3600 break; 3601 case 3: { 3602 IROp op; 3603 if (Q) { 3604 switch (size) { 3605 case 0: op = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; break; 3606 case 1: op = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; break; 3607 case 2: op = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; break; 3608 case 3: return False; 3609 default: vassert(0); 3610 } 3611 } else { 3612 switch (size) { 3613 case 0: op = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; break; 3614 case 1: op = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; break; 3615 case 2: op = U ? Iop_CmpGT32Ux2: Iop_CmpGT32Sx2; break; 3616 case 3: return False; 3617 default: vassert(0); 3618 } 3619 } 3620 if (B == 0) { 3621 /* VCGT */ 3622 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 3623 DIP("vcgt.%c%u %c%u, %c%u, %c%u\n", 3624 U ? 'u' : 's', 8 << size, 3625 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 3626 mreg); 3627 } else { 3628 /* VCGE */ 3629 /* VCGE res, argn, argm 3630 is equal to 3631 VCGT tmp, argm, argn 3632 VNOT res, tmp */ 3633 assign(res, 3634 unop(Q ? Iop_NotV128 : Iop_Not64, 3635 binop(op, mkexpr(arg_m), mkexpr(arg_n)))); 3636 DIP("vcge.%c%u %c%u, %c%u, %c%u\n", 3637 U ? 'u' : 's', 8 << size, 3638 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 3639 mreg); 3640 } 3641 } 3642 break; 3643 case 4: 3644 if (B == 0) { 3645 /* VSHL */ 3646 IROp op, sub_op; 3647 IRTemp tmp; 3648 if (U) { 3649 switch (size) { 3650 case 0: op = Q ? Iop_Shl8x16 : Iop_Shl8x8; break; 3651 case 1: op = Q ? Iop_Shl16x8 : Iop_Shl16x4; break; 3652 case 2: op = Q ? Iop_Shl32x4 : Iop_Shl32x2; break; 3653 case 3: op = Q ? Iop_Shl64x2 : Iop_Shl64; break; 3654 default: vassert(0); 3655 } 3656 } else { 3657 tmp = newTemp(Q ? Ity_V128 : Ity_I64); 3658 switch (size) { 3659 case 0: 3660 op = Q ? Iop_Sar8x16 : Iop_Sar8x8; 3661 sub_op = Q ? Iop_Sub8x16 : Iop_Sub8x8; 3662 break; 3663 case 1: 3664 op = Q ? Iop_Sar16x8 : Iop_Sar16x4; 3665 sub_op = Q ? Iop_Sub16x8 : Iop_Sub16x4; 3666 break; 3667 case 2: 3668 op = Q ? Iop_Sar32x4 : Iop_Sar32x2; 3669 sub_op = Q ? Iop_Sub32x4 : Iop_Sub32x2; 3670 break; 3671 case 3: 3672 op = Q ? Iop_Sar64x2 : Iop_Sar64; 3673 sub_op = Q ? Iop_Sub64x2 : Iop_Sub64; 3674 break; 3675 default: 3676 vassert(0); 3677 } 3678 } 3679 if (U) { 3680 if (!Q && (size == 3)) 3681 assign(res, binop(op, mkexpr(arg_m), 3682 unop(Iop_64to8, mkexpr(arg_n)))); 3683 else 3684 assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n))); 3685 } else { 3686 if (Q) 3687 assign(tmp, binop(sub_op, 3688 binop(Iop_64HLtoV128, mkU64(0), mkU64(0)), 3689 mkexpr(arg_n))); 3690 else 3691 assign(tmp, binop(sub_op, mkU64(0), mkexpr(arg_n))); 3692 if (!Q && (size == 3)) 3693 assign(res, binop(op, mkexpr(arg_m), 3694 unop(Iop_64to8, mkexpr(tmp)))); 3695 else 3696 assign(res, binop(op, mkexpr(arg_m), mkexpr(tmp))); 3697 } 3698 DIP("vshl.%c%u %c%u, %c%u, %c%u\n", 3699 U ? 'u' : 's', 8 << size, 3700 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd', 3701 nreg); 3702 } else { 3703 /* VQSHL */ 3704 IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt; 3705 IRTemp tmp, shval, mask, old_shval; 3706 UInt i; 3707 ULong esize; 3708 cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; 3709 cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; 3710 if (U) { 3711 switch (size) { 3712 case 0: 3713 op = Q ? Iop_QShl8x16 : Iop_QShl8x8; 3714 op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8; 3715 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3716 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 3717 break; 3718 case 1: 3719 op = Q ? Iop_QShl16x8 : Iop_QShl16x4; 3720 op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4; 3721 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3722 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 3723 break; 3724 case 2: 3725 op = Q ? Iop_QShl32x4 : Iop_QShl32x2; 3726 op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2; 3727 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3728 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; 3729 break; 3730 case 3: 3731 op = Q ? Iop_QShl64x2 : Iop_QShl64x1; 3732 op_rev = Q ? Iop_Shr64x2 : Iop_Shr64; 3733 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 3734 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 3735 break; 3736 default: 3737 vassert(0); 3738 } 3739 } else { 3740 switch (size) { 3741 case 0: 3742 op = Q ? Iop_QSal8x16 : Iop_QSal8x8; 3743 op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8; 3744 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3745 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 3746 break; 3747 case 1: 3748 op = Q ? Iop_QSal16x8 : Iop_QSal16x4; 3749 op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4; 3750 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3751 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 3752 break; 3753 case 2: 3754 op = Q ? Iop_QSal32x4 : Iop_QSal32x2; 3755 op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2; 3756 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3757 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; 3758 break; 3759 case 3: 3760 op = Q ? Iop_QSal64x2 : Iop_QSal64x1; 3761 op_rev = Q ? Iop_Sar64x2 : Iop_Sar64; 3762 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 3763 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 3764 break; 3765 default: 3766 vassert(0); 3767 } 3768 } 3769 if (Q) { 3770 tmp = newTemp(Ity_V128); 3771 shval = newTemp(Ity_V128); 3772 mask = newTemp(Ity_V128); 3773 } else { 3774 tmp = newTemp(Ity_I64); 3775 shval = newTemp(Ity_I64); 3776 mask = newTemp(Ity_I64); 3777 } 3778 assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n))); 3779 #ifndef DISABLE_QC_FLAG 3780 /* Only least significant byte from second argument is used. 3781 Copy this byte to the whole vector element. */ 3782 assign(shval, binop(op_shrn, 3783 binop(op_shln, 3784 mkexpr(arg_n), 3785 mkU8((8 << size) - 8)), 3786 mkU8((8 << size) - 8))); 3787 for(i = 0; i < size; i++) { 3788 old_shval = shval; 3789 shval = newTemp(Q ? Ity_V128 : Ity_I64); 3790 assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64, 3791 mkexpr(old_shval), 3792 binop(op_shln, 3793 mkexpr(old_shval), 3794 mkU8(8 << i)))); 3795 } 3796 /* If shift is greater or equal to the element size and 3797 element is non-zero, then QC flag should be set. */ 3798 esize = (8 << size) - 1; 3799 esize = (esize << 8) | esize; 3800 esize = (esize << 16) | esize; 3801 esize = (esize << 32) | esize; 3802 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 3803 binop(cmp_gt, mkexpr(shval), 3804 Q ? mkU128(esize) : mkU64(esize)), 3805 unop(cmp_neq, mkexpr(arg_m))), 3806 Q ? mkU128(0) : mkU64(0), 3807 Q, condT); 3808 /* Othervise QC flag should be set if shift value is positive and 3809 result beign rightshifted the same value is not equal to left 3810 argument. */ 3811 assign(mask, binop(cmp_gt, mkexpr(shval), 3812 Q ? mkU128(0) : mkU64(0))); 3813 if (!Q && size == 3) 3814 assign(tmp, binop(op_rev, mkexpr(res), 3815 unop(Iop_64to8, mkexpr(arg_n)))); 3816 else 3817 assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n))); 3818 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 3819 mkexpr(tmp), mkexpr(mask)), 3820 binop(Q ? Iop_AndV128 : Iop_And64, 3821 mkexpr(arg_m), mkexpr(mask)), 3822 Q, condT); 3823 #endif 3824 DIP("vqshl.%c%u %c%u, %c%u, %c%u\n", 3825 U ? 'u' : 's', 8 << size, 3826 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd', 3827 nreg); 3828 } 3829 break; 3830 case 5: 3831 if (B == 0) { 3832 /* VRSHL */ 3833 IROp op, op_shrn, op_shln, cmp_gt, op_add; 3834 IRTemp shval, old_shval, imm_val, round; 3835 UInt i; 3836 ULong imm; 3837 cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; 3838 imm = 1L; 3839 switch (size) { 3840 case 0: imm = (imm << 8) | imm; /* fall through */ 3841 case 1: imm = (imm << 16) | imm; /* fall through */ 3842 case 2: imm = (imm << 32) | imm; /* fall through */ 3843 case 3: break; 3844 default: vassert(0); 3845 } 3846 imm_val = newTemp(Q ? Ity_V128 : Ity_I64); 3847 round = newTemp(Q ? Ity_V128 : Ity_I64); 3848 assign(imm_val, Q ? mkU128(imm) : mkU64(imm)); 3849 if (U) { 3850 switch (size) { 3851 case 0: 3852 op = Q ? Iop_Shl8x16 : Iop_Shl8x8; 3853 op_add = Q ? Iop_Add8x16 : Iop_Add8x8; 3854 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3855 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 3856 break; 3857 case 1: 3858 op = Q ? Iop_Shl16x8 : Iop_Shl16x4; 3859 op_add = Q ? Iop_Add16x8 : Iop_Add16x4; 3860 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3861 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 3862 break; 3863 case 2: 3864 op = Q ? Iop_Shl32x4 : Iop_Shl32x2; 3865 op_add = Q ? Iop_Add32x4 : Iop_Add32x2; 3866 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3867 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; 3868 break; 3869 case 3: 3870 op = Q ? Iop_Shl64x2 : Iop_Shl64; 3871 op_add = Q ? Iop_Add64x2 : Iop_Add64; 3872 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 3873 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 3874 break; 3875 default: 3876 vassert(0); 3877 } 3878 } else { 3879 switch (size) { 3880 case 0: 3881 op = Q ? Iop_Sal8x16 : Iop_Sal8x8; 3882 op_add = Q ? Iop_Add8x16 : Iop_Add8x8; 3883 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3884 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 3885 break; 3886 case 1: 3887 op = Q ? Iop_Sal16x8 : Iop_Sal16x4; 3888 op_add = Q ? Iop_Add16x8 : Iop_Add16x4; 3889 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3890 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 3891 break; 3892 case 2: 3893 op = Q ? Iop_Sal32x4 : Iop_Sal32x2; 3894 op_add = Q ? Iop_Add32x4 : Iop_Add32x2; 3895 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3896 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; 3897 break; 3898 case 3: 3899 op = Q ? Iop_Sal64x2 : Iop_Sal64x1; 3900 op_add = Q ? Iop_Add64x2 : Iop_Add64; 3901 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 3902 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 3903 break; 3904 default: 3905 vassert(0); 3906 } 3907 } 3908 if (Q) { 3909 shval = newTemp(Ity_V128); 3910 } else { 3911 shval = newTemp(Ity_I64); 3912 } 3913 /* Only least significant byte from second argument is used. 3914 Copy this byte to the whole vector element. */ 3915 assign(shval, binop(op_shrn, 3916 binop(op_shln, 3917 mkexpr(arg_n), 3918 mkU8((8 << size) - 8)), 3919 mkU8((8 << size) - 8))); 3920 for (i = 0; i < size; i++) { 3921 old_shval = shval; 3922 shval = newTemp(Q ? Ity_V128 : Ity_I64); 3923 assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64, 3924 mkexpr(old_shval), 3925 binop(op_shln, 3926 mkexpr(old_shval), 3927 mkU8(8 << i)))); 3928 } 3929 /* Compute the result */ 3930 if (!Q && size == 3 && U) { 3931 assign(round, binop(Q ? Iop_AndV128 : Iop_And64, 3932 binop(op, 3933 mkexpr(arg_m), 3934 unop(Iop_64to8, 3935 binop(op_add, 3936 mkexpr(arg_n), 3937 mkexpr(imm_val)))), 3938 binop(Q ? Iop_AndV128 : Iop_And64, 3939 mkexpr(imm_val), 3940 binop(cmp_gt, 3941 Q ? mkU128(0) : mkU64(0), 3942 mkexpr(arg_n))))); 3943 assign(res, binop(op_add, 3944 binop(op, 3945 mkexpr(arg_m), 3946 unop(Iop_64to8, mkexpr(arg_n))), 3947 mkexpr(round))); 3948 } else { 3949 assign(round, binop(Q ? Iop_AndV128 : Iop_And64, 3950 binop(op, 3951 mkexpr(arg_m), 3952 binop(op_add, 3953 mkexpr(arg_n), 3954 mkexpr(imm_val))), 3955 binop(Q ? Iop_AndV128 : Iop_And64, 3956 mkexpr(imm_val), 3957 binop(cmp_gt, 3958 Q ? mkU128(0) : mkU64(0), 3959 mkexpr(arg_n))))); 3960 assign(res, binop(op_add, 3961 binop(op, mkexpr(arg_m), mkexpr(arg_n)), 3962 mkexpr(round))); 3963 } 3964 DIP("vrshl.%c%u %c%u, %c%u, %c%u\n", 3965 U ? 'u' : 's', 8 << size, 3966 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd', 3967 nreg); 3968 } else { 3969 /* VQRSHL */ 3970 IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt, op_add; 3971 IRTemp tmp, shval, mask, old_shval, imm_val, round; 3972 UInt i; 3973 ULong esize, imm; 3974 cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; 3975 cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; 3976 imm = 1L; 3977 switch (size) { 3978 case 0: imm = (imm << 8) | imm; /* fall through */ 3979 case 1: imm = (imm << 16) | imm; /* fall through */ 3980 case 2: imm = (imm << 32) | imm; /* fall through */ 3981 case 3: break; 3982 default: vassert(0); 3983 } 3984 imm_val = newTemp(Q ? Ity_V128 : Ity_I64); 3985 round = newTemp(Q ? Ity_V128 : Ity_I64); 3986 assign(imm_val, Q ? mkU128(imm) : mkU64(imm)); 3987 if (U) { 3988 switch (size) { 3989 case 0: 3990 op = Q ? Iop_QShl8x16 : Iop_QShl8x8; 3991 op_add = Q ? Iop_Add8x16 : Iop_Add8x8; 3992 op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8; 3993 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3994 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 3995 break; 3996 case 1: 3997 op = Q ? Iop_QShl16x8 : Iop_QShl16x4; 3998 op_add = Q ? Iop_Add16x8 : Iop_Add16x4; 3999 op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4; 4000 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 4001 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 4002 break; 4003 case 2: 4004 op = Q ? Iop_QShl32x4 : Iop_QShl32x2; 4005 op_add = Q ? Iop_Add32x4 : Iop_Add32x2; 4006 op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2; 4007 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 4008 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; 4009 break; 4010 case 3: 4011 op = Q ? Iop_QShl64x2 : Iop_QShl64x1; 4012 op_add = Q ? Iop_Add64x2 : Iop_Add64; 4013 op_rev = Q ? Iop_Shr64x2 : Iop_Shr64; 4014 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 4015 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 4016 break; 4017 default: 4018 vassert(0); 4019 } 4020 } else { 4021 switch (size) { 4022 case 0: 4023 op = Q ? Iop_QSal8x16 : Iop_QSal8x8; 4024 op_add = Q ? Iop_Add8x16 : Iop_Add8x8; 4025 op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8; 4026 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 4027 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 4028 break; 4029 case 1: 4030 op = Q ? Iop_QSal16x8 : Iop_QSal16x4; 4031 op_add = Q ? Iop_Add16x8 : Iop_Add16x4; 4032 op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4; 4033 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 4034 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 4035 break; 4036 case 2: 4037 op = Q ? Iop_QSal32x4 : Iop_QSal32x2; 4038 op_add = Q ? Iop_Add32x4 : Iop_Add32x2; 4039 op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2; 4040 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 4041 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; 4042 break; 4043 case 3: 4044 op = Q ? Iop_QSal64x2 : Iop_QSal64x1; 4045 op_add = Q ? Iop_Add64x2 : Iop_Add64; 4046 op_rev = Q ? Iop_Sar64x2 : Iop_Sar64; 4047 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 4048 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 4049 break; 4050 default: 4051 vassert(0); 4052 } 4053 } 4054 if (Q) { 4055 tmp = newTemp(Ity_V128); 4056 shval = newTemp(Ity_V128); 4057 mask = newTemp(Ity_V128); 4058 } else { 4059 tmp = newTemp(Ity_I64); 4060 shval = newTemp(Ity_I64); 4061 mask = newTemp(Ity_I64); 4062 } 4063 /* Only least significant byte from second argument is used. 4064 Copy this byte to the whole vector element. */ 4065 assign(shval, binop(op_shrn, 4066 binop(op_shln, 4067 mkexpr(arg_n), 4068 mkU8((8 << size) - 8)), 4069 mkU8((8 << size) - 8))); 4070 for (i = 0; i < size; i++) { 4071 old_shval = shval; 4072 shval = newTemp(Q ? Ity_V128 : Ity_I64); 4073 assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64, 4074 mkexpr(old_shval), 4075 binop(op_shln, 4076 mkexpr(old_shval), 4077 mkU8(8 << i)))); 4078 } 4079 /* Compute the result */ 4080 assign(round, binop(Q ? Iop_AndV128 : Iop_And64, 4081 binop(op, 4082 mkexpr(arg_m), 4083 binop(op_add, 4084 mkexpr(arg_n), 4085 mkexpr(imm_val))), 4086 binop(Q ? Iop_AndV128 : Iop_And64, 4087 mkexpr(imm_val), 4088 binop(cmp_gt, 4089 Q ? mkU128(0) : mkU64(0), 4090 mkexpr(arg_n))))); 4091 assign(res, binop(op_add, 4092 binop(op, mkexpr(arg_m), mkexpr(arg_n)), 4093 mkexpr(round))); 4094 #ifndef DISABLE_QC_FLAG 4095 /* If shift is greater or equal to the element size and element is 4096 non-zero, then QC flag should be set. */ 4097 esize = (8 << size) - 1; 4098 esize = (esize << 8) | esize; 4099 esize = (esize << 16) | esize; 4100 esize = (esize << 32) | esize; 4101 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 4102 binop(cmp_gt, mkexpr(shval), 4103 Q ? mkU128(esize) : mkU64(esize)), 4104 unop(cmp_neq, mkexpr(arg_m))), 4105 Q ? mkU128(0) : mkU64(0), 4106 Q, condT); 4107 /* Othervise QC flag should be set if shift value is positive and 4108 result beign rightshifted the same value is not equal to left 4109 argument. */ 4110 assign(mask, binop(cmp_gt, mkexpr(shval), 4111 Q ? mkU128(0) : mkU64(0))); 4112 if (!Q && size == 3) 4113 assign(tmp, binop(op_rev, mkexpr(res), 4114 unop(Iop_64to8, mkexpr(arg_n)))); 4115 else 4116 assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n))); 4117 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 4118 mkexpr(tmp), mkexpr(mask)), 4119 binop(Q ? Iop_AndV128 : Iop_And64, 4120 mkexpr(arg_m), mkexpr(mask)), 4121 Q, condT); 4122 #endif 4123 DIP("vqrshl.%c%u %c%u, %c%u, %c%u\n", 4124 U ? 'u' : 's', 8 << size, 4125 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd', 4126 nreg); 4127 } 4128 break; 4129 case 6: 4130 /* VMAX, VMIN */ 4131 if (B == 0) { 4132 /* VMAX */ 4133 IROp op; 4134 if (U == 0) { 4135 switch (size) { 4136 case 0: op = Q ? Iop_Max8Sx16 : Iop_Max8Sx8; break; 4137 case 1: op = Q ? Iop_Max16Sx8 : Iop_Max16Sx4; break; 4138 case 2: op = Q ? Iop_Max32Sx4 : Iop_Max32Sx2; break; 4139 case 3: return False; 4140 default: vassert(0); 4141 } 4142 } else { 4143 switch (size) { 4144 case 0: op = Q ? Iop_Max8Ux16 : Iop_Max8Ux8; break; 4145 case 1: op = Q ? Iop_Max16Ux8 : Iop_Max16Ux4; break; 4146 case 2: op = Q ? Iop_Max32Ux4 : Iop_Max32Ux2; break; 4147 case 3: return False; 4148 default: vassert(0); 4149 } 4150 } 4151 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4152 DIP("vmax.%c%u %c%u, %c%u, %c%u\n", 4153 U ? 'u' : 's', 8 << size, 4154 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4155 mreg); 4156 } else { 4157 /* VMIN */ 4158 IROp op; 4159 if (U == 0) { 4160 switch (size) { 4161 case 0: op = Q ? Iop_Min8Sx16 : Iop_Min8Sx8; break; 4162 case 1: op = Q ? Iop_Min16Sx8 : Iop_Min16Sx4; break; 4163 case 2: op = Q ? Iop_Min32Sx4 : Iop_Min32Sx2; break; 4164 case 3: return False; 4165 default: vassert(0); 4166 } 4167 } else { 4168 switch (size) { 4169 case 0: op = Q ? Iop_Min8Ux16 : Iop_Min8Ux8; break; 4170 case 1: op = Q ? Iop_Min16Ux8 : Iop_Min16Ux4; break; 4171 case 2: op = Q ? Iop_Min32Ux4 : Iop_Min32Ux2; break; 4172 case 3: return False; 4173 default: vassert(0); 4174 } 4175 } 4176 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4177 DIP("vmin.%c%u %c%u, %c%u, %c%u\n", 4178 U ? 'u' : 's', 8 << size, 4179 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4180 mreg); 4181 } 4182 break; 4183 case 7: 4184 if (B == 0) { 4185 /* VABD */ 4186 IROp op_cmp, op_sub; 4187 IRTemp cond; 4188 if ((theInstr >> 23) & 1) { 4189 vpanic("VABDL should not be in dis_neon_data_3same\n"); 4190 } 4191 if (Q) { 4192 switch (size) { 4193 case 0: 4194 op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; 4195 op_sub = Iop_Sub8x16; 4196 break; 4197 case 1: 4198 op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; 4199 op_sub = Iop_Sub16x8; 4200 break; 4201 case 2: 4202 op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; 4203 op_sub = Iop_Sub32x4; 4204 break; 4205 case 3: 4206 return False; 4207 default: 4208 vassert(0); 4209 } 4210 } else { 4211 switch (size) { 4212 case 0: 4213 op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; 4214 op_sub = Iop_Sub8x8; 4215 break; 4216 case 1: 4217 op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; 4218 op_sub = Iop_Sub16x4; 4219 break; 4220 case 2: 4221 op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2; 4222 op_sub = Iop_Sub32x2; 4223 break; 4224 case 3: 4225 return False; 4226 default: 4227 vassert(0); 4228 } 4229 } 4230 if (Q) { 4231 cond = newTemp(Ity_V128); 4232 } else { 4233 cond = newTemp(Ity_I64); 4234 } 4235 assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m))); 4236 assign(res, binop(Q ? Iop_OrV128 : Iop_Or64, 4237 binop(Q ? Iop_AndV128 : Iop_And64, 4238 binop(op_sub, mkexpr(arg_n), 4239 mkexpr(arg_m)), 4240 mkexpr(cond)), 4241 binop(Q ? Iop_AndV128 : Iop_And64, 4242 binop(op_sub, mkexpr(arg_m), 4243 mkexpr(arg_n)), 4244 unop(Q ? Iop_NotV128 : Iop_Not64, 4245 mkexpr(cond))))); 4246 DIP("vabd.%c%u %c%u, %c%u, %c%u\n", 4247 U ? 'u' : 's', 8 << size, 4248 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4249 mreg); 4250 } else { 4251 /* VABA */ 4252 IROp op_cmp, op_sub, op_add; 4253 IRTemp cond, acc, tmp; 4254 if ((theInstr >> 23) & 1) { 4255 vpanic("VABAL should not be in dis_neon_data_3same"); 4256 } 4257 if (Q) { 4258 switch (size) { 4259 case 0: 4260 op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; 4261 op_sub = Iop_Sub8x16; 4262 op_add = Iop_Add8x16; 4263 break; 4264 case 1: 4265 op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; 4266 op_sub = Iop_Sub16x8; 4267 op_add = Iop_Add16x8; 4268 break; 4269 case 2: 4270 op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; 4271 op_sub = Iop_Sub32x4; 4272 op_add = Iop_Add32x4; 4273 break; 4274 case 3: 4275 return False; 4276 default: 4277 vassert(0); 4278 } 4279 } else { 4280 switch (size) { 4281 case 0: 4282 op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; 4283 op_sub = Iop_Sub8x8; 4284 op_add = Iop_Add8x8; 4285 break; 4286 case 1: 4287 op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; 4288 op_sub = Iop_Sub16x4; 4289 op_add = Iop_Add16x4; 4290 break; 4291 case 2: 4292 op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2; 4293 op_sub = Iop_Sub32x2; 4294 op_add = Iop_Add32x2; 4295 break; 4296 case 3: 4297 return False; 4298 default: 4299 vassert(0); 4300 } 4301 } 4302 if (Q) { 4303 cond = newTemp(Ity_V128); 4304 acc = newTemp(Ity_V128); 4305 tmp = newTemp(Ity_V128); 4306 assign(acc, getQReg(dreg)); 4307 } else { 4308 cond = newTemp(Ity_I64); 4309 acc = newTemp(Ity_I64); 4310 tmp = newTemp(Ity_I64); 4311 assign(acc, getDRegI64(dreg)); 4312 } 4313 assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m))); 4314 assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64, 4315 binop(Q ? Iop_AndV128 : Iop_And64, 4316 binop(op_sub, mkexpr(arg_n), 4317 mkexpr(arg_m)), 4318 mkexpr(cond)), 4319 binop(Q ? Iop_AndV128 : Iop_And64, 4320 binop(op_sub, mkexpr(arg_m), 4321 mkexpr(arg_n)), 4322 unop(Q ? Iop_NotV128 : Iop_Not64, 4323 mkexpr(cond))))); 4324 assign(res, binop(op_add, mkexpr(acc), mkexpr(tmp))); 4325 DIP("vaba.%c%u %c%u, %c%u, %c%u\n", 4326 U ? 'u' : 's', 8 << size, 4327 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4328 mreg); 4329 } 4330 break; 4331 case 8: 4332 if (B == 0) { 4333 IROp op; 4334 if (U == 0) { 4335 /* VADD */ 4336 switch (size) { 4337 case 0: op = Q ? Iop_Add8x16 : Iop_Add8x8; break; 4338 case 1: op = Q ? Iop_Add16x8 : Iop_Add16x4; break; 4339 case 2: op = Q ? Iop_Add32x4 : Iop_Add32x2; break; 4340 case 3: op = Q ? Iop_Add64x2 : Iop_Add64; break; 4341 default: vassert(0); 4342 } 4343 DIP("vadd.i%u %c%u, %c%u, %c%u\n", 4344 8 << size, Q ? 'q' : 'd', 4345 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4346 } else { 4347 /* VSUB */ 4348 switch (size) { 4349 case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break; 4350 case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break; 4351 case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break; 4352 case 3: op = Q ? Iop_Sub64x2 : Iop_Sub64; break; 4353 default: vassert(0); 4354 } 4355 DIP("vsub.i%u %c%u, %c%u, %c%u\n", 4356 8 << size, Q ? 'q' : 'd', 4357 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4358 } 4359 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4360 } else { 4361 IROp op; 4362 switch (size) { 4363 case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break; 4364 case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break; 4365 case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break; 4366 case 3: op = Q ? Iop_CmpNEZ64x2 : Iop_CmpwNEZ64; break; 4367 default: vassert(0); 4368 } 4369 if (U == 0) { 4370 /* VTST */ 4371 assign(res, unop(op, binop(Q ? Iop_AndV128 : Iop_And64, 4372 mkexpr(arg_n), 4373 mkexpr(arg_m)))); 4374 DIP("vtst.%u %c%u, %c%u, %c%u\n", 4375 8 << size, Q ? 'q' : 'd', 4376 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4377 } else { 4378 /* VCEQ */ 4379 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64, 4380 unop(op, 4381 binop(Q ? Iop_XorV128 : Iop_Xor64, 4382 mkexpr(arg_n), 4383 mkexpr(arg_m))))); 4384 DIP("vceq.i%u %c%u, %c%u, %c%u\n", 4385 8 << size, Q ? 'q' : 'd', 4386 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4387 } 4388 } 4389 break; 4390 case 9: 4391 if (B == 0) { 4392 /* VMLA, VMLS (integer) */ 4393 IROp op, op2; 4394 UInt P = (theInstr >> 24) & 1; 4395 if (P) { 4396 switch (size) { 4397 case 0: 4398 op = Q ? Iop_Mul8x16 : Iop_Mul8x8; 4399 op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8; 4400 break; 4401 case 1: 4402 op = Q ? Iop_Mul16x8 : Iop_Mul16x4; 4403 op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4; 4404 break; 4405 case 2: 4406 op = Q ? Iop_Mul32x4 : Iop_Mul32x2; 4407 op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2; 4408 break; 4409 case 3: 4410 return False; 4411 default: 4412 vassert(0); 4413 } 4414 } else { 4415 switch (size) { 4416 case 0: 4417 op = Q ? Iop_Mul8x16 : Iop_Mul8x8; 4418 op2 = Q ? Iop_Add8x16 : Iop_Add8x8; 4419 break; 4420 case 1: 4421 op = Q ? Iop_Mul16x8 : Iop_Mul16x4; 4422 op2 = Q ? Iop_Add16x8 : Iop_Add16x4; 4423 break; 4424 case 2: 4425 op = Q ? Iop_Mul32x4 : Iop_Mul32x2; 4426 op2 = Q ? Iop_Add32x4 : Iop_Add32x2; 4427 break; 4428 case 3: 4429 return False; 4430 default: 4431 vassert(0); 4432 } 4433 } 4434 assign(res, binop(op2, 4435 Q ? getQReg(dreg) : getDRegI64(dreg), 4436 binop(op, mkexpr(arg_n), mkexpr(arg_m)))); 4437 DIP("vml%c.i%u %c%u, %c%u, %c%u\n", 4438 P ? 's' : 'a', 8 << size, 4439 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4440 mreg); 4441 } else { 4442 /* VMUL */ 4443 IROp op; 4444 UInt P = (theInstr >> 24) & 1; 4445 if (P) { 4446 switch (size) { 4447 case 0: 4448 op = Q ? Iop_PolynomialMul8x16 : Iop_PolynomialMul8x8; 4449 break; 4450 case 1: case 2: case 3: return False; 4451 default: vassert(0); 4452 } 4453 } else { 4454 switch (size) { 4455 case 0: op = Q ? Iop_Mul8x16 : Iop_Mul8x8; break; 4456 case 1: op = Q ? Iop_Mul16x8 : Iop_Mul16x4; break; 4457 case 2: op = Q ? Iop_Mul32x4 : Iop_Mul32x2; break; 4458 case 3: return False; 4459 default: vassert(0); 4460 } 4461 } 4462 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4463 DIP("vmul.%c%u %c%u, %c%u, %c%u\n", 4464 P ? 'p' : 'i', 8 << size, 4465 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4466 mreg); 4467 } 4468 break; 4469 case 10: { 4470 /* VPMAX, VPMIN */ 4471 UInt P = (theInstr >> 4) & 1; 4472 IROp op; 4473 if (Q) 4474 return False; 4475 if (P) { 4476 switch (size) { 4477 case 0: op = U ? Iop_PwMin8Ux8 : Iop_PwMin8Sx8; break; 4478 case 1: op = U ? Iop_PwMin16Ux4 : Iop_PwMin16Sx4; break; 4479 case 2: op = U ? Iop_PwMin32Ux2 : Iop_PwMin32Sx2; break; 4480 case 3: return False; 4481 default: vassert(0); 4482 } 4483 } else { 4484 switch (size) { 4485 case 0: op = U ? Iop_PwMax8Ux8 : Iop_PwMax8Sx8; break; 4486 case 1: op = U ? Iop_PwMax16Ux4 : Iop_PwMax16Sx4; break; 4487 case 2: op = U ? Iop_PwMax32Ux2 : Iop_PwMax32Sx2; break; 4488 case 3: return False; 4489 default: vassert(0); 4490 } 4491 } 4492 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4493 DIP("vp%s.%c%u %c%u, %c%u, %c%u\n", 4494 P ? "min" : "max", U ? 'u' : 's', 4495 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, 4496 Q ? 'q' : 'd', mreg); 4497 break; 4498 } 4499 case 11: 4500 if (B == 0) { 4501 if (U == 0) { 4502 /* VQDMULH */ 4503 IROp op ,op2; 4504 ULong imm; 4505 switch (size) { 4506 case 0: case 3: 4507 return False; 4508 case 1: 4509 op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4; 4510 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4; 4511 imm = 1LL << 15; 4512 imm = (imm << 16) | imm; 4513 imm = (imm << 32) | imm; 4514 break; 4515 case 2: 4516 op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2; 4517 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2; 4518 imm = 1LL << 31; 4519 imm = (imm << 32) | imm; 4520 break; 4521 default: 4522 vassert(0); 4523 } 4524 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4525 #ifndef DISABLE_QC_FLAG 4526 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 4527 binop(op2, mkexpr(arg_n), 4528 Q ? mkU128(imm) : mkU64(imm)), 4529 binop(op2, mkexpr(arg_m), 4530 Q ? mkU128(imm) : mkU64(imm))), 4531 Q ? mkU128(0) : mkU64(0), 4532 Q, condT); 4533 #endif 4534 DIP("vqdmulh.s%u %c%u, %c%u, %c%u\n", 4535 8 << size, Q ? 'q' : 'd', 4536 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4537 } else { 4538 /* VQRDMULH */ 4539 IROp op ,op2; 4540 ULong imm; 4541 switch(size) { 4542 case 0: case 3: 4543 return False; 4544 case 1: 4545 imm = 1LL << 15; 4546 imm = (imm << 16) | imm; 4547 imm = (imm << 32) | imm; 4548 op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4; 4549 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4; 4550 break; 4551 case 2: 4552 imm = 1LL << 31; 4553 imm = (imm << 32) | imm; 4554 op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2; 4555 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2; 4556 break; 4557 default: 4558 vassert(0); 4559 } 4560 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4561 #ifndef DISABLE_QC_FLAG 4562 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 4563 binop(op2, mkexpr(arg_n), 4564 Q ? mkU128(imm) : mkU64(imm)), 4565 binop(op2, mkexpr(arg_m), 4566 Q ? mkU128(imm) : mkU64(imm))), 4567 Q ? mkU128(0) : mkU64(0), 4568 Q, condT); 4569 #endif 4570 DIP("vqrdmulh.s%u %c%u, %c%u, %c%u\n", 4571 8 << size, Q ? 'q' : 'd', 4572 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4573 } 4574 } else { 4575 if (U == 0) { 4576 /* VPADD */ 4577 IROp op; 4578 if (Q) 4579 return False; 4580 switch (size) { 4581 case 0: op = Q ? Iop_PwAdd8x16 : Iop_PwAdd8x8; break; 4582 case 1: op = Q ? Iop_PwAdd16x8 : Iop_PwAdd16x4; break; 4583 case 2: op = Q ? Iop_PwAdd32x4 : Iop_PwAdd32x2; break; 4584 case 3: return False; 4585 default: vassert(0); 4586 } 4587 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4588 DIP("vpadd.i%d %c%u, %c%u, %c%u\n", 4589 8 << size, Q ? 'q' : 'd', 4590 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4591 } 4592 } 4593 break; 4594 /* Starting from here these are FP SIMD cases */ 4595 case 13: 4596 if (B == 0) { 4597 IROp op; 4598 if (U == 0) { 4599 if ((C >> 1) == 0) { 4600 /* VADD */ 4601 op = Q ? Iop_Add32Fx4 : Iop_Add32Fx2 ; 4602 DIP("vadd.f32 %c%u, %c%u, %c%u\n", 4603 Q ? 'q' : 'd', dreg, 4604 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4605 } else { 4606 /* VSUB */ 4607 op = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2 ; 4608 DIP("vsub.f32 %c%u, %c%u, %c%u\n", 4609 Q ? 'q' : 'd', dreg, 4610 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4611 } 4612 } else { 4613 if ((C >> 1) == 0) { 4614 /* VPADD */ 4615 if (Q) 4616 return False; 4617 op = Iop_PwAdd32Fx2; 4618 DIP("vpadd.f32 d%u, d%u, d%u\n", dreg, nreg, mreg); 4619 } else { 4620 /* VABD */ 4621 if (Q) { 4622 assign(res, unop(Iop_Abs32Fx4, 4623 binop(Iop_Sub32Fx4, 4624 mkexpr(arg_n), 4625 mkexpr(arg_m)))); 4626 } else { 4627 assign(res, unop(Iop_Abs32Fx2, 4628 binop(Iop_Sub32Fx2, 4629 mkexpr(arg_n), 4630 mkexpr(arg_m)))); 4631 } 4632 DIP("vabd.f32 %c%u, %c%u, %c%u\n", 4633 Q ? 'q' : 'd', dreg, 4634 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4635 break; 4636 } 4637 } 4638 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4639 } else { 4640 if (U == 0) { 4641 /* VMLA, VMLS */ 4642 IROp op, op2; 4643 UInt P = (theInstr >> 21) & 1; 4644 if (P) { 4645 switch (size & 1) { 4646 case 0: 4647 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2; 4648 op2 = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2; 4649 break; 4650 case 1: return False; 4651 default: vassert(0); 4652 } 4653 } else { 4654 switch (size & 1) { 4655 case 0: 4656 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2; 4657 op2 = Q ? Iop_Add32Fx4 : Iop_Add32Fx2; 4658 break; 4659 case 1: return False; 4660 default: vassert(0); 4661 } 4662 } 4663 assign(res, binop(op2, 4664 Q ? getQReg(dreg) : getDRegI64(dreg), 4665 binop(op, mkexpr(arg_n), mkexpr(arg_m)))); 4666 4667 DIP("vml%c.f32 %c%u, %c%u, %c%u\n", 4668 P ? 's' : 'a', Q ? 'q' : 'd', 4669 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4670 } else { 4671 /* VMUL */ 4672 IROp op; 4673 if ((C >> 1) != 0) 4674 return False; 4675 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2 ; 4676 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4677 DIP("vmul.f32 %c%u, %c%u, %c%u\n", 4678 Q ? 'q' : 'd', dreg, 4679 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4680 } 4681 } 4682 break; 4683 case 14: 4684 if (B == 0) { 4685 if (U == 0) { 4686 if ((C >> 1) == 0) { 4687 /* VCEQ */ 4688 IROp op; 4689 if ((theInstr >> 20) & 1) 4690 return False; 4691 op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2; 4692 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4693 DIP("vceq.f32 %c%u, %c%u, %c%u\n", 4694 Q ? 'q' : 'd', dreg, 4695 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4696 } else { 4697 return False; 4698 } 4699 } else { 4700 if ((C >> 1) == 0) { 4701 /* VCGE */ 4702 IROp op; 4703 if ((theInstr >> 20) & 1) 4704 return False; 4705 op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; 4706 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4707 DIP("vcge.f32 %c%u, %c%u, %c%u\n", 4708 Q ? 'q' : 'd', dreg, 4709 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4710 } else { 4711 /* VCGT */ 4712 IROp op; 4713 if ((theInstr >> 20) & 1) 4714 return False; 4715 op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; 4716 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4717 DIP("vcgt.f32 %c%u, %c%u, %c%u\n", 4718 Q ? 'q' : 'd', dreg, 4719 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4720 } 4721 } 4722 } else { 4723 if (U == 1) { 4724 /* VACGE, VACGT */ 4725 UInt op_bit = (theInstr >> 21) & 1; 4726 IROp op, op2; 4727 op2 = Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2; 4728 if (op_bit) { 4729 op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; 4730 assign(res, binop(op, 4731 unop(op2, mkexpr(arg_n)), 4732 unop(op2, mkexpr(arg_m)))); 4733 } else { 4734 op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; 4735 assign(res, binop(op, 4736 unop(op2, mkexpr(arg_n)), 4737 unop(op2, mkexpr(arg_m)))); 4738 } 4739 DIP("vacg%c.f32 %c%u, %c%u, %c%u\n", op_bit ? 't' : 'e', 4740 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, 4741 Q ? 'q' : 'd', mreg); 4742 } 4743 } 4744 break; 4745 case 15: 4746 if (B == 0) { 4747 if (U == 0) { 4748 /* VMAX, VMIN */ 4749 IROp op; 4750 if ((theInstr >> 20) & 1) 4751 return False; 4752 if ((theInstr >> 21) & 1) { 4753 op = Q ? Iop_Min32Fx4 : Iop_Min32Fx2; 4754 DIP("vmin.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg, 4755 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4756 } else { 4757 op = Q ? Iop_Max32Fx4 : Iop_Max32Fx2; 4758 DIP("vmax.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg, 4759 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4760 } 4761 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4762 } else { 4763 /* VPMAX, VPMIN */ 4764 IROp op; 4765 if (Q) 4766 return False; 4767 if ((theInstr >> 20) & 1) 4768 return False; 4769 if ((theInstr >> 21) & 1) { 4770 op = Iop_PwMin32Fx2; 4771 DIP("vpmin.f32 d%u, d%u, d%u\n", dreg, nreg, mreg); 4772 } else { 4773 op = Iop_PwMax32Fx2; 4774 DIP("vpmax.f32 d%u, d%u, d%u\n", dreg, nreg, mreg); 4775 } 4776 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4777 } 4778 } else { 4779 if (U == 0) { 4780 if ((C >> 1) == 0) { 4781 /* VRECPS */ 4782 if ((theInstr >> 20) & 1) 4783 return False; 4784 assign(res, binop(Q ? Iop_Recps32Fx4 : Iop_Recps32Fx2, 4785 mkexpr(arg_n), 4786 mkexpr(arg_m))); 4787 DIP("vrecps.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg, 4788 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4789 } else { 4790 /* VRSQRTS */ 4791 if ((theInstr >> 20) & 1) 4792 return False; 4793 assign(res, binop(Q ? Iop_Rsqrts32Fx4 : Iop_Rsqrts32Fx2, 4794 mkexpr(arg_n), 4795 mkexpr(arg_m))); 4796 DIP("vrsqrts.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg, 4797 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4798 } 4799 } 4800 } 4801 break; 4802 } 4803 4804 if (Q) { 4805 putQReg(dreg, mkexpr(res), condT); 4806 } else { 4807 putDRegI64(dreg, mkexpr(res), condT); 4808 } 4809 4810 return True; 4811 } 4812 4813 /* A7.4.2 Three registers of different length */ 4814 static 4815 Bool dis_neon_data_3diff ( UInt theInstr, IRTemp condT ) 4816 { 4817 UInt A = (theInstr >> 8) & 0xf; 4818 UInt B = (theInstr >> 20) & 3; 4819 UInt U = (theInstr >> 24) & 1; 4820 UInt P = (theInstr >> 9) & 1; 4821 UInt mreg = get_neon_m_regno(theInstr); 4822 UInt nreg = get_neon_n_regno(theInstr); 4823 UInt dreg = get_neon_d_regno(theInstr); 4824 UInt size = B; 4825 ULong imm; 4826 IRTemp res, arg_m, arg_n, cond, tmp; 4827 IROp cvt, cvt2, cmp, op, op2, sh, add; 4828 switch (A) { 4829 case 0: case 1: case 2: case 3: 4830 /* VADDL, VADDW, VSUBL, VSUBW */ 4831 if (dreg & 1) 4832 return False; 4833 dreg >>= 1; 4834 size = B; 4835 switch (size) { 4836 case 0: 4837 cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8; 4838 op = (A & 2) ? Iop_Sub16x8 : Iop_Add16x8; 4839 break; 4840 case 1: 4841 cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4; 4842 op = (A & 2) ? Iop_Sub32x4 : Iop_Add32x4; 4843 break; 4844 case 2: 4845 cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2; 4846 op = (A & 2) ? Iop_Sub64x2 : Iop_Add64x2; 4847 break; 4848 case 3: 4849 return False; 4850 default: 4851 vassert(0); 4852 } 4853 arg_n = newTemp(Ity_V128); 4854 arg_m = newTemp(Ity_V128); 4855 if (A & 1) { 4856 if (nreg & 1) 4857 return False; 4858 nreg >>= 1; 4859 assign(arg_n, getQReg(nreg)); 4860 } else { 4861 assign(arg_n, unop(cvt, getDRegI64(nreg))); 4862 } 4863 assign(arg_m, unop(cvt, getDRegI64(mreg))); 4864 putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)), 4865 condT); 4866 DIP("v%s%c.%c%u q%u, %c%u, d%u\n", (A & 2) ? "sub" : "add", 4867 (A & 1) ? 'w' : 'l', U ? 'u' : 's', 8 << size, dreg, 4868 (A & 1) ? 'q' : 'd', nreg, mreg); 4869 return True; 4870 case 4: 4871 /* VADDHN, VRADDHN */ 4872 if (mreg & 1) 4873 return False; 4874 mreg >>= 1; 4875 if (nreg & 1) 4876 return False; 4877 nreg >>= 1; 4878 size = B; 4879 switch (size) { 4880 case 0: 4881 op = Iop_Add16x8; 4882 cvt = Iop_NarrowUn16to8x8; 4883 sh = Iop_ShrN16x8; 4884 imm = 1U << 7; 4885 imm = (imm << 16) | imm; 4886 imm = (imm << 32) | imm; 4887 break; 4888 case 1: 4889 op = Iop_Add32x4; 4890 cvt = Iop_NarrowUn32to16x4; 4891 sh = Iop_ShrN32x4; 4892 imm = 1U << 15; 4893 imm = (imm << 32) | imm; 4894 break; 4895 case 2: 4896 op = Iop_Add64x2; 4897 cvt = Iop_NarrowUn64to32x2; 4898 sh = Iop_ShrN64x2; 4899 imm = 1U << 31; 4900 break; 4901 case 3: 4902 return False; 4903 default: 4904 vassert(0); 4905 } 4906 tmp = newTemp(Ity_V128); 4907 res = newTemp(Ity_V128); 4908 assign(tmp, binop(op, getQReg(nreg), getQReg(mreg))); 4909 if (U) { 4910 /* VRADDHN */ 4911 assign(res, binop(op, mkexpr(tmp), 4912 binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)))); 4913 } else { 4914 assign(res, mkexpr(tmp)); 4915 } 4916 putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))), 4917 condT); 4918 DIP("v%saddhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg, 4919 nreg, mreg); 4920 return True; 4921 case 5: 4922 /* VABAL */ 4923 if (!((theInstr >> 23) & 1)) { 4924 vpanic("VABA should not be in dis_neon_data_3diff\n"); 4925 } 4926 if (dreg & 1) 4927 return False; 4928 dreg >>= 1; 4929 switch (size) { 4930 case 0: 4931 cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; 4932 cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8; 4933 cvt2 = Iop_Widen8Sto16x8; 4934 op = Iop_Sub16x8; 4935 op2 = Iop_Add16x8; 4936 break; 4937 case 1: 4938 cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; 4939 cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4; 4940 cvt2 = Iop_Widen16Sto32x4; 4941 op = Iop_Sub32x4; 4942 op2 = Iop_Add32x4; 4943 break; 4944 case 2: 4945 cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2; 4946 cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2; 4947 cvt2 = Iop_Widen32Sto64x2; 4948 op = Iop_Sub64x2; 4949 op2 = Iop_Add64x2; 4950 break; 4951 case 3: 4952 return False; 4953 default: 4954 vassert(0); 4955 } 4956 arg_n = newTemp(Ity_V128); 4957 arg_m = newTemp(Ity_V128); 4958 cond = newTemp(Ity_V128); 4959 res = newTemp(Ity_V128); 4960 assign(arg_n, unop(cvt, getDRegI64(nreg))); 4961 assign(arg_m, unop(cvt, getDRegI64(mreg))); 4962 assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg), 4963 getDRegI64(mreg)))); 4964 assign(res, binop(op2, 4965 binop(Iop_OrV128, 4966 binop(Iop_AndV128, 4967 binop(op, mkexpr(arg_n), mkexpr(arg_m)), 4968 mkexpr(cond)), 4969 binop(Iop_AndV128, 4970 binop(op, mkexpr(arg_m), mkexpr(arg_n)), 4971 unop(Iop_NotV128, mkexpr(cond)))), 4972 getQReg(dreg))); 4973 putQReg(dreg, mkexpr(res), condT); 4974 DIP("vabal.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg, 4975 nreg, mreg); 4976 return True; 4977 case 6: 4978 /* VSUBHN, VRSUBHN */ 4979 if (mreg & 1) 4980 return False; 4981 mreg >>= 1; 4982 if (nreg & 1) 4983 return False; 4984 nreg >>= 1; 4985 size = B; 4986 switch (size) { 4987 case 0: 4988 op = Iop_Sub16x8; 4989 op2 = Iop_Add16x8; 4990 cvt = Iop_NarrowUn16to8x8; 4991 sh = Iop_ShrN16x8; 4992 imm = 1U << 7; 4993 imm = (imm << 16) | imm; 4994 imm = (imm << 32) | imm; 4995 break; 4996 case 1: 4997 op = Iop_Sub32x4; 4998 op2 = Iop_Add32x4; 4999 cvt = Iop_NarrowUn32to16x4; 5000 sh = Iop_ShrN32x4; 5001 imm = 1U << 15; 5002 imm = (imm << 32) | imm; 5003 break; 5004 case 2: 5005 op = Iop_Sub64x2; 5006 op2 = Iop_Add64x2; 5007 cvt = Iop_NarrowUn64to32x2; 5008 sh = Iop_ShrN64x2; 5009 imm = 1U << 31; 5010 break; 5011 case 3: 5012 return False; 5013 default: 5014 vassert(0); 5015 } 5016 tmp = newTemp(Ity_V128); 5017 res = newTemp(Ity_V128); 5018 assign(tmp, binop(op, getQReg(nreg), getQReg(mreg))); 5019 if (U) { 5020 /* VRSUBHN */ 5021 assign(res, binop(op2, mkexpr(tmp), 5022 binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)))); 5023 } else { 5024 assign(res, mkexpr(tmp)); 5025 } 5026 putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))), 5027 condT); 5028 DIP("v%ssubhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg, 5029 nreg, mreg); 5030 return True; 5031 case 7: 5032 /* VABDL */ 5033 if (!((theInstr >> 23) & 1)) { 5034 vpanic("VABL should not be in dis_neon_data_3diff\n"); 5035 } 5036 if (dreg & 1) 5037 return False; 5038 dreg >>= 1; 5039 switch (size) { 5040 case 0: 5041 cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; 5042 cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8; 5043 cvt2 = Iop_Widen8Sto16x8; 5044 op = Iop_Sub16x8; 5045 break; 5046 case 1: 5047 cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; 5048 cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4; 5049 cvt2 = Iop_Widen16Sto32x4; 5050 op = Iop_Sub32x4; 5051 break; 5052 case 2: 5053 cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2; 5054 cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2; 5055 cvt2 = Iop_Widen32Sto64x2; 5056 op = Iop_Sub64x2; 5057 break; 5058 case 3: 5059 return False; 5060 default: 5061 vassert(0); 5062 } 5063 arg_n = newTemp(Ity_V128); 5064 arg_m = newTemp(Ity_V128); 5065 cond = newTemp(Ity_V128); 5066 res = newTemp(Ity_V128); 5067 assign(arg_n, unop(cvt, getDRegI64(nreg))); 5068 assign(arg_m, unop(cvt, getDRegI64(mreg))); 5069 assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg), 5070 getDRegI64(mreg)))); 5071 assign(res, binop(Iop_OrV128, 5072 binop(Iop_AndV128, 5073 binop(op, mkexpr(arg_n), mkexpr(arg_m)), 5074 mkexpr(cond)), 5075 binop(Iop_AndV128, 5076 binop(op, mkexpr(arg_m), mkexpr(arg_n)), 5077 unop(Iop_NotV128, mkexpr(cond))))); 5078 putQReg(dreg, mkexpr(res), condT); 5079 DIP("vabdl.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg, 5080 nreg, mreg); 5081 return True; 5082 case 8: 5083 case 10: 5084 /* VMLAL, VMLSL (integer) */ 5085 if (dreg & 1) 5086 return False; 5087 dreg >>= 1; 5088 size = B; 5089 switch (size) { 5090 case 0: 5091 op = U ? Iop_Mull8Ux8 : Iop_Mull8Sx8; 5092 op2 = P ? Iop_Sub16x8 : Iop_Add16x8; 5093 break; 5094 case 1: 5095 op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; 5096 op2 = P ? Iop_Sub32x4 : Iop_Add32x4; 5097 break; 5098 case 2: 5099 op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; 5100 op2 = P ? Iop_Sub64x2 : Iop_Add64x2; 5101 break; 5102 case 3: 5103 return False; 5104 default: 5105 vassert(0); 5106 } 5107 res = newTemp(Ity_V128); 5108 assign(res, binop(op, getDRegI64(nreg),getDRegI64(mreg))); 5109 putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT); 5110 DIP("vml%cl.%c%u q%u, d%u, d%u\n", P ? 's' : 'a', U ? 'u' : 's', 5111 8 << size, dreg, nreg, mreg); 5112 return True; 5113 case 9: 5114 case 11: 5115 /* VQDMLAL, VQDMLSL */ 5116 if (U) 5117 return False; 5118 if (dreg & 1) 5119 return False; 5120 dreg >>= 1; 5121 size = B; 5122 switch (size) { 5123 case 0: case 3: 5124 return False; 5125 case 1: 5126 op = Iop_QDMulLong16Sx4; 5127 cmp = Iop_CmpEQ16x4; 5128 add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4; 5129 op2 = P ? Iop_Sub32x4 : Iop_Add32x4; 5130 imm = 1LL << 15; 5131 imm = (imm << 16) | imm; 5132 imm = (imm << 32) | imm; 5133 break; 5134 case 2: 5135 op = Iop_QDMulLong32Sx2; 5136 cmp = Iop_CmpEQ32x2; 5137 add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2; 5138 op2 = P ? Iop_Sub64x2 : Iop_Add64x2; 5139 imm = 1LL << 31; 5140 imm = (imm << 32) | imm; 5141 break; 5142 default: 5143 vassert(0); 5144 } 5145 res = newTemp(Ity_V128); 5146 tmp = newTemp(Ity_V128); 5147 assign(res, binop(op, getDRegI64(nreg), getDRegI64(mreg))); 5148 #ifndef DISABLE_QC_FLAG 5149 assign(tmp, binop(op2, getQReg(dreg), mkexpr(res))); 5150 setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)), 5151 True, condT); 5152 setFlag_QC(binop(Iop_And64, 5153 binop(cmp, getDRegI64(nreg), mkU64(imm)), 5154 binop(cmp, getDRegI64(mreg), mkU64(imm))), 5155 mkU64(0), 5156 False, condT); 5157 #endif 5158 putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT); 5159 DIP("vqdml%cl.s%u q%u, d%u, d%u\n", P ? 's' : 'a', 8 << size, dreg, 5160 nreg, mreg); 5161 return True; 5162 case 12: 5163 case 14: 5164 /* VMULL (integer or polynomial) */ 5165 if (dreg & 1) 5166 return False; 5167 dreg >>= 1; 5168 size = B; 5169 switch (size) { 5170 case 0: 5171 op = (U) ? Iop_Mull8Ux8 : Iop_Mull8Sx8; 5172 if (P) 5173 op = Iop_PolynomialMull8x8; 5174 break; 5175 case 1: 5176 op = (U) ? Iop_Mull16Ux4 : Iop_Mull16Sx4; 5177 break; 5178 case 2: 5179 op = (U) ? Iop_Mull32Ux2 : Iop_Mull32Sx2; 5180 break; 5181 default: 5182 vassert(0); 5183 } 5184 putQReg(dreg, binop(op, getDRegI64(nreg), 5185 getDRegI64(mreg)), condT); 5186 DIP("vmull.%c%u q%u, d%u, d%u\n", P ? 'p' : (U ? 'u' : 's'), 5187 8 << size, dreg, nreg, mreg); 5188 return True; 5189 case 13: 5190 /* VQDMULL */ 5191 if (U) 5192 return False; 5193 if (dreg & 1) 5194 return False; 5195 dreg >>= 1; 5196 size = B; 5197 switch (size) { 5198 case 0: 5199 case 3: 5200 return False; 5201 case 1: 5202 op = Iop_QDMulLong16Sx4; 5203 op2 = Iop_CmpEQ16x4; 5204 imm = 1LL << 15; 5205 imm = (imm << 16) | imm; 5206 imm = (imm << 32) | imm; 5207 break; 5208 case 2: 5209 op = Iop_QDMulLong32Sx2; 5210 op2 = Iop_CmpEQ32x2; 5211 imm = 1LL << 31; 5212 imm = (imm << 32) | imm; 5213 break; 5214 default: 5215 vassert(0); 5216 } 5217 putQReg(dreg, binop(op, getDRegI64(nreg), getDRegI64(mreg)), 5218 condT); 5219 #ifndef DISABLE_QC_FLAG 5220 setFlag_QC(binop(Iop_And64, 5221 binop(op2, getDRegI64(nreg), mkU64(imm)), 5222 binop(op2, getDRegI64(mreg), mkU64(imm))), 5223 mkU64(0), 5224 False, condT); 5225 #endif 5226 DIP("vqdmull.s%u q%u, d%u, d%u\n", 8 << size, dreg, nreg, mreg); 5227 return True; 5228 default: 5229 return False; 5230 } 5231 return False; 5232 } 5233 5234 /* A7.4.3 Two registers and a scalar */ 5235 static 5236 Bool dis_neon_data_2reg_and_scalar ( UInt theInstr, IRTemp condT ) 5237 { 5238 # define INSN(_bMax,_bMin) SLICE_UInt(theInstr, (_bMax), (_bMin)) 5239 UInt U = INSN(24,24); 5240 UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6)); 5241 UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6)); 5242 UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6)); 5243 UInt size = INSN(21,20); 5244 UInt index; 5245 UInt Q = INSN(24,24); 5246 5247 if (INSN(27,25) != 1 || INSN(23,23) != 1 5248 || INSN(6,6) != 1 || INSN(4,4) != 0) 5249 return False; 5250 5251 /* VMLA, VMLS (scalar) */ 5252 if ((INSN(11,8) & BITS4(1,0,1,0)) == BITS4(0,0,0,0)) { 5253 IRTemp res, arg_m, arg_n; 5254 IROp dup, get, op, op2, add, sub; 5255 if (Q) { 5256 if ((dreg & 1) || (nreg & 1)) 5257 return False; 5258 dreg >>= 1; 5259 nreg >>= 1; 5260 res = newTemp(Ity_V128); 5261 arg_m = newTemp(Ity_V128); 5262 arg_n = newTemp(Ity_V128); 5263 assign(arg_n, getQReg(nreg)); 5264 switch(size) { 5265 case 1: 5266 dup = Iop_Dup16x8; 5267 get = Iop_GetElem16x4; 5268 index = mreg >> 3; 5269 mreg &= 7; 5270 break; 5271 case 2: 5272 dup = Iop_Dup32x4; 5273 get = Iop_GetElem32x2; 5274 index = mreg >> 4; 5275 mreg &= 0xf; 5276 break; 5277 case 0: 5278 case 3: 5279 return False; 5280 default: 5281 vassert(0); 5282 } 5283 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5284 } else { 5285 res = newTemp(Ity_I64); 5286 arg_m = newTemp(Ity_I64); 5287 arg_n = newTemp(Ity_I64); 5288 assign(arg_n, getDRegI64(nreg)); 5289 switch(size) { 5290 case 1: 5291 dup = Iop_Dup16x4; 5292 get = Iop_GetElem16x4; 5293 index = mreg >> 3; 5294 mreg &= 7; 5295 break; 5296 case 2: 5297 dup = Iop_Dup32x2; 5298 get = Iop_GetElem32x2; 5299 index = mreg >> 4; 5300 mreg &= 0xf; 5301 break; 5302 case 0: 5303 case 3: 5304 return False; 5305 default: 5306 vassert(0); 5307 } 5308 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5309 } 5310 if (INSN(8,8)) { 5311 switch (size) { 5312 case 2: 5313 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2; 5314 add = Q ? Iop_Add32Fx4 : Iop_Add32Fx2; 5315 sub = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2; 5316 break; 5317 case 0: 5318 case 1: 5319 case 3: 5320 return False; 5321 default: 5322 vassert(0); 5323 } 5324 } else { 5325 switch (size) { 5326 case 1: 5327 op = Q ? Iop_Mul16x8 : Iop_Mul16x4; 5328 add = Q ? Iop_Add16x8 : Iop_Add16x4; 5329 sub = Q ? Iop_Sub16x8 : Iop_Sub16x4; 5330 break; 5331 case 2: 5332 op = Q ? Iop_Mul32x4 : Iop_Mul32x2; 5333 add = Q ? Iop_Add32x4 : Iop_Add32x2; 5334 sub = Q ? Iop_Sub32x4 : Iop_Sub32x2; 5335 break; 5336 case 0: 5337 case 3: 5338 return False; 5339 default: 5340 vassert(0); 5341 } 5342 } 5343 op2 = INSN(10,10) ? sub : add; 5344 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5345 if (Q) 5346 putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), 5347 condT); 5348 else 5349 putDRegI64(dreg, binop(op2, getDRegI64(dreg), mkexpr(res)), 5350 condT); 5351 DIP("vml%c.%c%u %c%u, %c%u, d%u[%u]\n", INSN(10,10) ? 's' : 'a', 5352 INSN(8,8) ? 'f' : 'i', 8 << size, 5353 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, mreg, index); 5354 return True; 5355 } 5356 5357 /* VMLAL, VMLSL (scalar) */ 5358 if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,0)) { 5359 IRTemp res, arg_m, arg_n; 5360 IROp dup, get, op, op2, add, sub; 5361 if (dreg & 1) 5362 return False; 5363 dreg >>= 1; 5364 res = newTemp(Ity_V128); 5365 arg_m = newTemp(Ity_I64); 5366 arg_n = newTemp(Ity_I64); 5367 assign(arg_n, getDRegI64(nreg)); 5368 switch(size) { 5369 case 1: 5370 dup = Iop_Dup16x4; 5371 get = Iop_GetElem16x4; 5372 index = mreg >> 3; 5373 mreg &= 7; 5374 break; 5375 case 2: 5376 dup = Iop_Dup32x2; 5377 get = Iop_GetElem32x2; 5378 index = mreg >> 4; 5379 mreg &= 0xf; 5380 break; 5381 case 0: 5382 case 3: 5383 return False; 5384 default: 5385 vassert(0); 5386 } 5387 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5388 switch (size) { 5389 case 1: 5390 op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; 5391 add = Iop_Add32x4; 5392 sub = Iop_Sub32x4; 5393 break; 5394 case 2: 5395 op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; 5396 add = Iop_Add64x2; 5397 sub = Iop_Sub64x2; 5398 break; 5399 case 0: 5400 case 3: 5401 return False; 5402 default: 5403 vassert(0); 5404 } 5405 op2 = INSN(10,10) ? sub : add; 5406 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5407 putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT); 5408 DIP("vml%cl.%c%u q%u, d%u, d%u[%u]\n", 5409 INSN(10,10) ? 's' : 'a', U ? 'u' : 's', 5410 8 << size, dreg, nreg, mreg, index); 5411 return True; 5412 } 5413 5414 /* VQDMLAL, VQDMLSL (scalar) */ 5415 if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,1) && !U) { 5416 IRTemp res, arg_m, arg_n, tmp; 5417 IROp dup, get, op, op2, add, cmp; 5418 UInt P = INSN(10,10); 5419 ULong imm; 5420 if (dreg & 1) 5421 return False; 5422 dreg >>= 1; 5423 res = newTemp(Ity_V128); 5424 arg_m = newTemp(Ity_I64); 5425 arg_n = newTemp(Ity_I64); 5426 assign(arg_n, getDRegI64(nreg)); 5427 switch(size) { 5428 case 1: 5429 dup = Iop_Dup16x4; 5430 get = Iop_GetElem16x4; 5431 index = mreg >> 3; 5432 mreg &= 7; 5433 break; 5434 case 2: 5435 dup = Iop_Dup32x2; 5436 get = Iop_GetElem32x2; 5437 index = mreg >> 4; 5438 mreg &= 0xf; 5439 break; 5440 case 0: 5441 case 3: 5442 return False; 5443 default: 5444 vassert(0); 5445 } 5446 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5447 switch (size) { 5448 case 0: 5449 case 3: 5450 return False; 5451 case 1: 5452 op = Iop_QDMulLong16Sx4; 5453 cmp = Iop_CmpEQ16x4; 5454 add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4; 5455 op2 = P ? Iop_Sub32x4 : Iop_Add32x4; 5456 imm = 1LL << 15; 5457 imm = (imm << 16) | imm; 5458 imm = (imm << 32) | imm; 5459 break; 5460 case 2: 5461 op = Iop_QDMulLong32Sx2; 5462 cmp = Iop_CmpEQ32x2; 5463 add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2; 5464 op2 = P ? Iop_Sub64x2 : Iop_Add64x2; 5465 imm = 1LL << 31; 5466 imm = (imm << 32) | imm; 5467 break; 5468 default: 5469 vassert(0); 5470 } 5471 res = newTemp(Ity_V128); 5472 tmp = newTemp(Ity_V128); 5473 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5474 #ifndef DISABLE_QC_FLAG 5475 assign(tmp, binop(op2, getQReg(dreg), mkexpr(res))); 5476 setFlag_QC(binop(Iop_And64, 5477 binop(cmp, mkexpr(arg_n), mkU64(imm)), 5478 binop(cmp, mkexpr(arg_m), mkU64(imm))), 5479 mkU64(0), 5480 False, condT); 5481 setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)), 5482 True, condT); 5483 #endif 5484 putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT); 5485 DIP("vqdml%cl.s%u q%u, d%u, d%u[%u]\n", P ? 's' : 'a', 8 << size, 5486 dreg, nreg, mreg, index); 5487 return True; 5488 } 5489 5490 /* VMUL (by scalar) */ 5491 if ((INSN(11,8) & BITS4(1,1,1,0)) == BITS4(1,0,0,0)) { 5492 IRTemp res, arg_m, arg_n; 5493 IROp dup, get, op; 5494 if (Q) { 5495 if ((dreg & 1) || (nreg & 1)) 5496 return False; 5497 dreg >>= 1; 5498 nreg >>= 1; 5499 res = newTemp(Ity_V128); 5500 arg_m = newTemp(Ity_V128); 5501 arg_n = newTemp(Ity_V128); 5502 assign(arg_n, getQReg(nreg)); 5503 switch(size) { 5504 case 1: 5505 dup = Iop_Dup16x8; 5506 get = Iop_GetElem16x4; 5507 index = mreg >> 3; 5508 mreg &= 7; 5509 break; 5510 case 2: 5511 dup = Iop_Dup32x4; 5512 get = Iop_GetElem32x2; 5513 index = mreg >> 4; 5514 mreg &= 0xf; 5515 break; 5516 case 0: 5517 case 3: 5518 return False; 5519 default: 5520 vassert(0); 5521 } 5522 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5523 } else { 5524 res = newTemp(Ity_I64); 5525 arg_m = newTemp(Ity_I64); 5526 arg_n = newTemp(Ity_I64); 5527 assign(arg_n, getDRegI64(nreg)); 5528 switch(size) { 5529 case 1: 5530 dup = Iop_Dup16x4; 5531 get = Iop_GetElem16x4; 5532 index = mreg >> 3; 5533 mreg &= 7; 5534 break; 5535 case 2: 5536 dup = Iop_Dup32x2; 5537 get = Iop_GetElem32x2; 5538 index = mreg >> 4; 5539 mreg &= 0xf; 5540 break; 5541 case 0: 5542 case 3: 5543 return False; 5544 default: 5545 vassert(0); 5546 } 5547 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5548 } 5549 if (INSN(8,8)) { 5550 switch (size) { 5551 case 2: 5552 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2; 5553 break; 5554 case 0: 5555 case 1: 5556 case 3: 5557 return False; 5558 default: 5559 vassert(0); 5560 } 5561 } else { 5562 switch (size) { 5563 case 1: 5564 op = Q ? Iop_Mul16x8 : Iop_Mul16x4; 5565 break; 5566 case 2: 5567 op = Q ? Iop_Mul32x4 : Iop_Mul32x2; 5568 break; 5569 case 0: 5570 case 3: 5571 return False; 5572 default: 5573 vassert(0); 5574 } 5575 } 5576 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5577 if (Q) 5578 putQReg(dreg, mkexpr(res), condT); 5579 else 5580 putDRegI64(dreg, mkexpr(res), condT); 5581 DIP("vmul.%c%u %c%u, %c%u, d%u[%u]\n", INSN(8,8) ? 'f' : 'i', 5582 8 << size, Q ? 'q' : 'd', dreg, 5583 Q ? 'q' : 'd', nreg, mreg, index); 5584 return True; 5585 } 5586 5587 /* VMULL (scalar) */ 5588 if (INSN(11,8) == BITS4(1,0,1,0)) { 5589 IRTemp res, arg_m, arg_n; 5590 IROp dup, get, op; 5591 if (dreg & 1) 5592 return False; 5593 dreg >>= 1; 5594 res = newTemp(Ity_V128); 5595 arg_m = newTemp(Ity_I64); 5596 arg_n = newTemp(Ity_I64); 5597 assign(arg_n, getDRegI64(nreg)); 5598 switch(size) { 5599 case 1: 5600 dup = Iop_Dup16x4; 5601 get = Iop_GetElem16x4; 5602 index = mreg >> 3; 5603 mreg &= 7; 5604 break; 5605 case 2: 5606 dup = Iop_Dup32x2; 5607 get = Iop_GetElem32x2; 5608 index = mreg >> 4; 5609 mreg &= 0xf; 5610 break; 5611 case 0: 5612 case 3: 5613 return False; 5614 default: 5615 vassert(0); 5616 } 5617 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5618 switch (size) { 5619 case 1: op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; break; 5620 case 2: op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; break; 5621 case 0: case 3: return False; 5622 default: vassert(0); 5623 } 5624 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5625 putQReg(dreg, mkexpr(res), condT); 5626 DIP("vmull.%c%u q%u, d%u, d%u[%u]\n", U ? 'u' : 's', 8 << size, dreg, 5627 nreg, mreg, index); 5628 return True; 5629 } 5630 5631 /* VQDMULL */ 5632 if (INSN(11,8) == BITS4(1,0,1,1) && !U) { 5633 IROp op ,op2, dup, get; 5634 ULong imm; 5635 IRTemp arg_m, arg_n; 5636 if (dreg & 1) 5637 return False; 5638 dreg >>= 1; 5639 arg_m = newTemp(Ity_I64); 5640 arg_n = newTemp(Ity_I64); 5641 assign(arg_n, getDRegI64(nreg)); 5642 switch(size) { 5643 case 1: 5644 dup = Iop_Dup16x4; 5645 get = Iop_GetElem16x4; 5646 index = mreg >> 3; 5647 mreg &= 7; 5648 break; 5649 case 2: 5650 dup = Iop_Dup32x2; 5651 get = Iop_GetElem32x2; 5652 index = mreg >> 4; 5653 mreg &= 0xf; 5654 break; 5655 case 0: 5656 case 3: 5657 return False; 5658 default: 5659 vassert(0); 5660 } 5661 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5662 switch (size) { 5663 case 0: 5664 case 3: 5665 return False; 5666 case 1: 5667 op = Iop_QDMulLong16Sx4; 5668 op2 = Iop_CmpEQ16x4; 5669 imm = 1LL << 15; 5670 imm = (imm << 16) | imm; 5671 imm = (imm << 32) | imm; 5672 break; 5673 case 2: 5674 op = Iop_QDMulLong32Sx2; 5675 op2 = Iop_CmpEQ32x2; 5676 imm = 1LL << 31; 5677 imm = (imm << 32) | imm; 5678 break; 5679 default: 5680 vassert(0); 5681 } 5682 putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)), 5683 condT); 5684 #ifndef DISABLE_QC_FLAG 5685 setFlag_QC(binop(Iop_And64, 5686 binop(op2, mkexpr(arg_n), mkU64(imm)), 5687 binop(op2, mkexpr(arg_m), mkU64(imm))), 5688 mkU64(0), 5689 False, condT); 5690 #endif 5691 DIP("vqdmull.s%u q%u, d%u, d%u[%u]\n", 8 << size, dreg, nreg, mreg, 5692 index); 5693 return True; 5694 } 5695 5696 /* VQDMULH */ 5697 if (INSN(11,8) == BITS4(1,1,0,0)) { 5698 IROp op ,op2, dup, get; 5699 ULong imm; 5700 IRTemp res, arg_m, arg_n; 5701 if (Q) { 5702 if ((dreg & 1) || (nreg & 1)) 5703 return False; 5704 dreg >>= 1; 5705 nreg >>= 1; 5706 res = newTemp(Ity_V128); 5707 arg_m = newTemp(Ity_V128); 5708 arg_n = newTemp(Ity_V128); 5709 assign(arg_n, getQReg(nreg)); 5710 switch(size) { 5711 case 1: 5712 dup = Iop_Dup16x8; 5713 get = Iop_GetElem16x4; 5714 index = mreg >> 3; 5715 mreg &= 7; 5716 break; 5717 case 2: 5718 dup = Iop_Dup32x4; 5719 get = Iop_GetElem32x2; 5720 index = mreg >> 4; 5721 mreg &= 0xf; 5722 break; 5723 case 0: 5724 case 3: 5725 return False; 5726 default: 5727 vassert(0); 5728 } 5729 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5730 } else { 5731 res = newTemp(Ity_I64); 5732 arg_m = newTemp(Ity_I64); 5733 arg_n = newTemp(Ity_I64); 5734 assign(arg_n, getDRegI64(nreg)); 5735 switch(size) { 5736 case 1: 5737 dup = Iop_Dup16x4; 5738 get = Iop_GetElem16x4; 5739 index = mreg >> 3; 5740 mreg &= 7; 5741 break; 5742 case 2: 5743 dup = Iop_Dup32x2; 5744 get = Iop_GetElem32x2; 5745 index = mreg >> 4; 5746 mreg &= 0xf; 5747 break; 5748 case 0: 5749 case 3: 5750 return False; 5751 default: 5752 vassert(0); 5753 } 5754 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5755 } 5756 switch (size) { 5757 case 0: 5758 case 3: 5759 return False; 5760 case 1: 5761 op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4; 5762 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4; 5763 imm = 1LL << 15; 5764 imm = (imm << 16) | imm; 5765 imm = (imm << 32) | imm; 5766 break; 5767 case 2: 5768 op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2; 5769 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2; 5770 imm = 1LL << 31; 5771 imm = (imm << 32) | imm; 5772 break; 5773 default: 5774 vassert(0); 5775 } 5776 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5777 #ifndef DISABLE_QC_FLAG 5778 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 5779 binop(op2, mkexpr(arg_n), 5780 Q ? mkU128(imm) : mkU64(imm)), 5781 binop(op2, mkexpr(arg_m), 5782 Q ? mkU128(imm) : mkU64(imm))), 5783 Q ? mkU128(0) : mkU64(0), 5784 Q, condT); 5785 #endif 5786 if (Q) 5787 putQReg(dreg, mkexpr(res), condT); 5788 else 5789 putDRegI64(dreg, mkexpr(res), condT); 5790 DIP("vqdmulh.s%u %c%u, %c%u, d%u[%u]\n", 5791 8 << size, Q ? 'q' : 'd', dreg, 5792 Q ? 'q' : 'd', nreg, mreg, index); 5793 return True; 5794 } 5795 5796 /* VQRDMULH (scalar) */ 5797 if (INSN(11,8) == BITS4(1,1,0,1)) { 5798 IROp op ,op2, dup, get; 5799 ULong imm; 5800 IRTemp res, arg_m, arg_n; 5801 if (Q) { 5802 if ((dreg & 1) || (nreg & 1)) 5803 return False; 5804 dreg >>= 1; 5805 nreg >>= 1; 5806 res = newTemp(Ity_V128); 5807 arg_m = newTemp(Ity_V128); 5808 arg_n = newTemp(Ity_V128); 5809 assign(arg_n, getQReg(nreg)); 5810 switch(size) { 5811 case 1: 5812 dup = Iop_Dup16x8; 5813 get = Iop_GetElem16x4; 5814 index = mreg >> 3; 5815 mreg &= 7; 5816 break; 5817 case 2: 5818 dup = Iop_Dup32x4; 5819 get = Iop_GetElem32x2; 5820 index = mreg >> 4; 5821 mreg &= 0xf; 5822 break; 5823 case 0: 5824 case 3: 5825 return False; 5826 default: 5827 vassert(0); 5828 } 5829 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5830 } else { 5831 res = newTemp(Ity_I64); 5832 arg_m = newTemp(Ity_I64); 5833 arg_n = newTemp(Ity_I64); 5834 assign(arg_n, getDRegI64(nreg)); 5835 switch(size) { 5836 case 1: 5837 dup = Iop_Dup16x4; 5838 get = Iop_GetElem16x4; 5839 index = mreg >> 3; 5840 mreg &= 7; 5841 break; 5842 case 2: 5843 dup = Iop_Dup32x2; 5844 get = Iop_GetElem32x2; 5845 index = mreg >> 4; 5846 mreg &= 0xf; 5847 break; 5848 case 0: 5849 case 3: 5850 return False; 5851 default: 5852 vassert(0); 5853 } 5854 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5855 } 5856 switch (size) { 5857 case 0: 5858 case 3: 5859 return False; 5860 case 1: 5861 op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4; 5862 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4; 5863 imm = 1LL << 15; 5864 imm = (imm << 16) | imm; 5865 imm = (imm << 32) | imm; 5866 break; 5867 case 2: 5868 op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2; 5869 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2; 5870 imm = 1LL << 31; 5871 imm = (imm << 32) | imm; 5872 break; 5873 default: 5874 vassert(0); 5875 } 5876 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5877 #ifndef DISABLE_QC_FLAG 5878 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 5879 binop(op2, mkexpr(arg_n), 5880 Q ? mkU128(imm) : mkU64(imm)), 5881 binop(op2, mkexpr(arg_m), 5882 Q ? mkU128(imm) : mkU64(imm))), 5883 Q ? mkU128(0) : mkU64(0), 5884 Q, condT); 5885 #endif 5886 if (Q) 5887 putQReg(dreg, mkexpr(res), condT); 5888 else 5889 putDRegI64(dreg, mkexpr(res), condT); 5890 DIP("vqrdmulh.s%u %c%u, %c%u, d%u[%u]\n", 5891 8 << size, Q ? 'q' : 'd', dreg, 5892 Q ? 'q' : 'd', nreg, mreg, index); 5893 return True; 5894 } 5895 5896 return False; 5897 # undef INSN 5898 } 5899 5900 /* A7.4.4 Two registers and a shift amount */ 5901 static 5902 Bool dis_neon_data_2reg_and_shift ( UInt theInstr, IRTemp condT ) 5903 { 5904 UInt A = (theInstr >> 8) & 0xf; 5905 UInt B = (theInstr >> 6) & 1; 5906 UInt L = (theInstr >> 7) & 1; 5907 UInt U = (theInstr >> 24) & 1; 5908 UInt Q = B; 5909 UInt imm6 = (theInstr >> 16) & 0x3f; 5910 UInt shift_imm; 5911 UInt size = 4; 5912 UInt tmp; 5913 UInt mreg = get_neon_m_regno(theInstr); 5914 UInt dreg = get_neon_d_regno(theInstr); 5915 ULong imm = 0; 5916 IROp op, cvt, add = Iop_INVALID, cvt2, op_rev; 5917 IRTemp reg_m, res, mask; 5918 5919 if (L == 0 && ((theInstr >> 19) & 7) == 0) 5920 /* It is one reg and immediate */ 5921 return False; 5922 5923 tmp = (L << 6) | imm6; 5924 if (tmp & 0x40) { 5925 size = 3; 5926 shift_imm = 64 - imm6; 5927 } else if (tmp & 0x20) { 5928 size = 2; 5929 shift_imm = 64 - imm6; 5930 } else if (tmp & 0x10) { 5931 size = 1; 5932 shift_imm = 32 - imm6; 5933 } else if (tmp & 0x8) { 5934 size = 0; 5935 shift_imm = 16 - imm6; 5936 } else { 5937 return False; 5938 } 5939 5940 switch (A) { 5941 case 3: 5942 case 2: 5943 /* VRSHR, VRSRA */ 5944 if (shift_imm > 0) { 5945 IRExpr *imm_val; 5946 imm = 1L; 5947 switch (size) { 5948 case 0: 5949 imm = (imm << 8) | imm; 5950 /* fall through */ 5951 case 1: 5952 imm = (imm << 16) | imm; 5953 /* fall through */ 5954 case 2: 5955 imm = (imm << 32) | imm; 5956 /* fall through */ 5957 case 3: 5958 break; 5959 default: 5960 vassert(0); 5961 } 5962 if (Q) { 5963 reg_m = newTemp(Ity_V128); 5964 res = newTemp(Ity_V128); 5965 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)); 5966 assign(reg_m, getQReg(mreg)); 5967 switch (size) { 5968 case 0: 5969 add = Iop_Add8x16; 5970 op = U ? Iop_ShrN8x16 : Iop_SarN8x16; 5971 break; 5972 case 1: 5973 add = Iop_Add16x8; 5974 op = U ? Iop_ShrN16x8 : Iop_SarN16x8; 5975 break; 5976 case 2: 5977 add = Iop_Add32x4; 5978 op = U ? Iop_ShrN32x4 : Iop_SarN32x4; 5979 break; 5980 case 3: 5981 add = Iop_Add64x2; 5982 op = U ? Iop_ShrN64x2 : Iop_SarN64x2; 5983 break; 5984 default: 5985 vassert(0); 5986 } 5987 } else { 5988 reg_m = newTemp(Ity_I64); 5989 res = newTemp(Ity_I64); 5990 imm_val = mkU64(imm); 5991 assign(reg_m, getDRegI64(mreg)); 5992 switch (size) { 5993 case 0: 5994 add = Iop_Add8x8; 5995 op = U ? Iop_ShrN8x8 : Iop_SarN8x8; 5996 break; 5997 case 1: 5998 add = Iop_Add16x4; 5999 op = U ? Iop_ShrN16x4 : Iop_SarN16x4; 6000 break; 6001 case 2: 6002 add = Iop_Add32x2; 6003 op = U ? Iop_ShrN32x2 : Iop_SarN32x2; 6004 break; 6005 case 3: 6006 add = Iop_Add64; 6007 op = U ? Iop_Shr64 : Iop_Sar64; 6008 break; 6009 default: 6010 vassert(0); 6011 } 6012 } 6013 assign(res, 6014 binop(add, 6015 binop(op, 6016 mkexpr(reg_m), 6017 mkU8(shift_imm)), 6018 binop(Q ? Iop_AndV128 : Iop_And64, 6019 binop(op, 6020 mkexpr(reg_m), 6021 mkU8(shift_imm - 1)), 6022 imm_val))); 6023 } else { 6024 if (Q) { 6025 res = newTemp(Ity_V128); 6026 assign(res, getQReg(mreg)); 6027 } else { 6028 res = newTemp(Ity_I64); 6029 assign(res, getDRegI64(mreg)); 6030 } 6031 } 6032 if (A == 3) { 6033 if (Q) { 6034 putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)), 6035 condT); 6036 } else { 6037 putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)), 6038 condT); 6039 } 6040 DIP("vrsra.%c%u %c%u, %c%u, #%u\n", 6041 U ? 'u' : 's', 8 << size, 6042 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6043 } else { 6044 if (Q) { 6045 putQReg(dreg, mkexpr(res), condT); 6046 } else { 6047 putDRegI64(dreg, mkexpr(res), condT); 6048 } 6049 DIP("vrshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size, 6050 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6051 } 6052 return True; 6053 case 1: 6054 case 0: 6055 /* VSHR, VSRA */ 6056 if (Q) { 6057 reg_m = newTemp(Ity_V128); 6058 assign(reg_m, getQReg(mreg)); 6059 res = newTemp(Ity_V128); 6060 } else { 6061 reg_m = newTemp(Ity_I64); 6062 assign(reg_m, getDRegI64(mreg)); 6063 res = newTemp(Ity_I64); 6064 } 6065 if (Q) { 6066 switch (size) { 6067 case 0: 6068 op = U ? Iop_ShrN8x16 : Iop_SarN8x16; 6069 add = Iop_Add8x16; 6070 break; 6071 case 1: 6072 op = U ? Iop_ShrN16x8 : Iop_SarN16x8; 6073 add = Iop_Add16x8; 6074 break; 6075 case 2: 6076 op = U ? Iop_ShrN32x4 : Iop_SarN32x4; 6077 add = Iop_Add32x4; 6078 break; 6079 case 3: 6080 op = U ? Iop_ShrN64x2 : Iop_SarN64x2; 6081 add = Iop_Add64x2; 6082 break; 6083 default: 6084 vassert(0); 6085 } 6086 } else { 6087 switch (size) { 6088 case 0: 6089 op = U ? Iop_ShrN8x8 : Iop_SarN8x8; 6090 add = Iop_Add8x8; 6091 break; 6092 case 1: 6093 op = U ? Iop_ShrN16x4 : Iop_SarN16x4; 6094 add = Iop_Add16x4; 6095 break; 6096 case 2: 6097 op = U ? Iop_ShrN32x2 : Iop_SarN32x2; 6098 add = Iop_Add32x2; 6099 break; 6100 case 3: 6101 op = U ? Iop_Shr64 : Iop_Sar64; 6102 add = Iop_Add64; 6103 break; 6104 default: 6105 vassert(0); 6106 } 6107 } 6108 assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm))); 6109 if (A == 1) { 6110 if (Q) { 6111 putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)), 6112 condT); 6113 } else { 6114 putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)), 6115 condT); 6116 } 6117 DIP("vsra.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size, 6118 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6119 } else { 6120 if (Q) { 6121 putQReg(dreg, mkexpr(res), condT); 6122 } else { 6123 putDRegI64(dreg, mkexpr(res), condT); 6124 } 6125 DIP("vshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size, 6126 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6127 } 6128 return True; 6129 case 4: 6130 /* VSRI */ 6131 if (!U) 6132 return False; 6133 if (Q) { 6134 res = newTemp(Ity_V128); 6135 mask = newTemp(Ity_V128); 6136 } else { 6137 res = newTemp(Ity_I64); 6138 mask = newTemp(Ity_I64); 6139 } 6140 switch (size) { 6141 case 0: op = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; break; 6142 case 1: op = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; break; 6143 case 2: op = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; break; 6144 case 3: op = Q ? Iop_ShrN64x2 : Iop_Shr64; break; 6145 default: vassert(0); 6146 } 6147 if (Q) { 6148 assign(mask, binop(op, binop(Iop_64HLtoV128, 6149 mkU64(0xFFFFFFFFFFFFFFFFLL), 6150 mkU64(0xFFFFFFFFFFFFFFFFLL)), 6151 mkU8(shift_imm))); 6152 assign(res, binop(Iop_OrV128, 6153 binop(Iop_AndV128, 6154 getQReg(dreg), 6155 unop(Iop_NotV128, 6156 mkexpr(mask))), 6157 binop(op, 6158 getQReg(mreg), 6159 mkU8(shift_imm)))); 6160 putQReg(dreg, mkexpr(res), condT); 6161 } else { 6162 assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL), 6163 mkU8(shift_imm))); 6164 assign(res, binop(Iop_Or64, 6165 binop(Iop_And64, 6166 getDRegI64(dreg), 6167 unop(Iop_Not64, 6168 mkexpr(mask))), 6169 binop(op, 6170 getDRegI64(mreg), 6171 mkU8(shift_imm)))); 6172 putDRegI64(dreg, mkexpr(res), condT); 6173 } 6174 DIP("vsri.%u %c%u, %c%u, #%u\n", 6175 8 << size, Q ? 'q' : 'd', dreg, 6176 Q ? 'q' : 'd', mreg, shift_imm); 6177 return True; 6178 case 5: 6179 if (U) { 6180 /* VSLI */ 6181 shift_imm = 8 * (1 << size) - shift_imm; 6182 if (Q) { 6183 res = newTemp(Ity_V128); 6184 mask = newTemp(Ity_V128); 6185 } else { 6186 res = newTemp(Ity_I64); 6187 mask = newTemp(Ity_I64); 6188 } 6189 switch (size) { 6190 case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break; 6191 case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break; 6192 case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break; 6193 case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break; 6194 default: vassert(0); 6195 } 6196 if (Q) { 6197 assign(mask, binop(op, binop(Iop_64HLtoV128, 6198 mkU64(0xFFFFFFFFFFFFFFFFLL), 6199 mkU64(0xFFFFFFFFFFFFFFFFLL)), 6200 mkU8(shift_imm))); 6201 assign(res, binop(Iop_OrV128, 6202 binop(Iop_AndV128, 6203 getQReg(dreg), 6204 unop(Iop_NotV128, 6205 mkexpr(mask))), 6206 binop(op, 6207 getQReg(mreg), 6208 mkU8(shift_imm)))); 6209 putQReg(dreg, mkexpr(res), condT); 6210 } else { 6211 assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL), 6212 mkU8(shift_imm))); 6213 assign(res, binop(Iop_Or64, 6214 binop(Iop_And64, 6215 getDRegI64(dreg), 6216 unop(Iop_Not64, 6217 mkexpr(mask))), 6218 binop(op, 6219 getDRegI64(mreg), 6220 mkU8(shift_imm)))); 6221 putDRegI64(dreg, mkexpr(res), condT); 6222 } 6223 DIP("vsli.%u %c%u, %c%u, #%u\n", 6224 8 << size, Q ? 'q' : 'd', dreg, 6225 Q ? 'q' : 'd', mreg, shift_imm); 6226 return True; 6227 } else { 6228 /* VSHL #imm */ 6229 shift_imm = 8 * (1 << size) - shift_imm; 6230 if (Q) { 6231 res = newTemp(Ity_V128); 6232 } else { 6233 res = newTemp(Ity_I64); 6234 } 6235 switch (size) { 6236 case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break; 6237 case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break; 6238 case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break; 6239 case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break; 6240 default: vassert(0); 6241 } 6242 assign(res, binop(op, Q ? getQReg(mreg) : getDRegI64(mreg), 6243 mkU8(shift_imm))); 6244 if (Q) { 6245 putQReg(dreg, mkexpr(res), condT); 6246 } else { 6247 putDRegI64(dreg, mkexpr(res), condT); 6248 } 6249 DIP("vshl.i%u %c%u, %c%u, #%u\n", 6250 8 << size, Q ? 'q' : 'd', dreg, 6251 Q ? 'q' : 'd', mreg, shift_imm); 6252 return True; 6253 } 6254 break; 6255 case 6: 6256 case 7: 6257 /* VQSHL, VQSHLU */ 6258 shift_imm = 8 * (1 << size) - shift_imm; 6259 if (U) { 6260 if (A & 1) { 6261 switch (size) { 6262 case 0: 6263 op = Q ? Iop_QShlN8x16 : Iop_QShlN8x8; 6264 op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 6265 break; 6266 case 1: 6267 op = Q ? Iop_QShlN16x8 : Iop_QShlN16x4; 6268 op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 6269 break; 6270 case 2: 6271 op = Q ? Iop_QShlN32x4 : Iop_QShlN32x2; 6272 op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 6273 break; 6274 case 3: 6275 op = Q ? Iop_QShlN64x2 : Iop_QShlN64x1; 6276 op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64; 6277 break; 6278 default: 6279 vassert(0); 6280 } 6281 DIP("vqshl.u%u %c%u, %c%u, #%u\n", 6282 8 << size, 6283 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6284 } else { 6285 switch (size) { 6286 case 0: 6287 op = Q ? Iop_QShlN8Sx16 : Iop_QShlN8Sx8; 6288 op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 6289 break; 6290 case 1: 6291 op = Q ? Iop_QShlN16Sx8 : Iop_QShlN16Sx4; 6292 op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 6293 break; 6294 case 2: 6295 op = Q ? Iop_QShlN32Sx4 : Iop_QShlN32Sx2; 6296 op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 6297 break; 6298 case 3: 6299 op = Q ? Iop_QShlN64Sx2 : Iop_QShlN64Sx1; 6300 op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64; 6301 break; 6302 default: 6303 vassert(0); 6304 } 6305 DIP("vqshlu.s%u %c%u, %c%u, #%u\n", 6306 8 << size, 6307 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6308 } 6309 } else { 6310 if (!(A & 1)) 6311 return False; 6312 switch (size) { 6313 case 0: 6314 op = Q ? Iop_QSalN8x16 : Iop_QSalN8x8; 6315 op_rev = Q ? Iop_SarN8x16 : Iop_SarN8x8; 6316 break; 6317 case 1: 6318 op = Q ? Iop_QSalN16x8 : Iop_QSalN16x4; 6319 op_rev = Q ? Iop_SarN16x8 : Iop_SarN16x4; 6320 break; 6321 case 2: 6322 op = Q ? Iop_QSalN32x4 : Iop_QSalN32x2; 6323 op_rev = Q ? Iop_SarN32x4 : Iop_SarN32x2; 6324 break; 6325 case 3: 6326 op = Q ? Iop_QSalN64x2 : Iop_QSalN64x1; 6327 op_rev = Q ? Iop_SarN64x2 : Iop_Sar64; 6328 break; 6329 default: 6330 vassert(0); 6331 } 6332 DIP("vqshl.s%u %c%u, %c%u, #%u\n", 6333 8 << size, 6334 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6335 } 6336 if (Q) { 6337 tmp = newTemp(Ity_V128); 6338 res = newTemp(Ity_V128); 6339 reg_m = newTemp(Ity_V128); 6340 assign(reg_m, getQReg(mreg)); 6341 } else { 6342 tmp = newTemp(Ity_I64); 6343 res = newTemp(Ity_I64); 6344 reg_m = newTemp(Ity_I64); 6345 assign(reg_m, getDRegI64(mreg)); 6346 } 6347 assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm))); 6348 #ifndef DISABLE_QC_FLAG 6349 assign(tmp, binop(op_rev, mkexpr(res), mkU8(shift_imm))); 6350 setFlag_QC(mkexpr(tmp), mkexpr(reg_m), Q, condT); 6351 #endif 6352 if (Q) 6353 putQReg(dreg, mkexpr(res), condT); 6354 else 6355 putDRegI64(dreg, mkexpr(res), condT); 6356 return True; 6357 case 8: 6358 if (!U) { 6359 if (L == 1) 6360 return False; 6361 size++; 6362 dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF); 6363 mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF); 6364 if (mreg & 1) 6365 return False; 6366 mreg >>= 1; 6367 if (!B) { 6368 /* VSHRN*/ 6369 IROp narOp; 6370 reg_m = newTemp(Ity_V128); 6371 assign(reg_m, getQReg(mreg)); 6372 res = newTemp(Ity_I64); 6373 switch (size) { 6374 case 1: 6375 op = Iop_ShrN16x8; 6376 narOp = Iop_NarrowUn16to8x8; 6377 break; 6378 case 2: 6379 op = Iop_ShrN32x4; 6380 narOp = Iop_NarrowUn32to16x4; 6381 break; 6382 case 3: 6383 op = Iop_ShrN64x2; 6384 narOp = Iop_NarrowUn64to32x2; 6385 break; 6386 default: 6387 vassert(0); 6388 } 6389 assign(res, unop(narOp, 6390 binop(op, 6391 mkexpr(reg_m), 6392 mkU8(shift_imm)))); 6393 putDRegI64(dreg, mkexpr(res), condT); 6394 DIP("vshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg, 6395 shift_imm); 6396 return True; 6397 } else { 6398 /* VRSHRN */ 6399 IROp addOp, shOp, narOp; 6400 IRExpr *imm_val; 6401 reg_m = newTemp(Ity_V128); 6402 assign(reg_m, getQReg(mreg)); 6403 res = newTemp(Ity_I64); 6404 imm = 1L; 6405 switch (size) { 6406 case 0: imm = (imm << 8) | imm; /* fall through */ 6407 case 1: imm = (imm << 16) | imm; /* fall through */ 6408 case 2: imm = (imm << 32) | imm; /* fall through */ 6409 case 3: break; 6410 default: vassert(0); 6411 } 6412 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)); 6413 switch (size) { 6414 case 1: 6415 addOp = Iop_Add16x8; 6416 shOp = Iop_ShrN16x8; 6417 narOp = Iop_NarrowUn16to8x8; 6418 break; 6419 case 2: 6420 addOp = Iop_Add32x4; 6421 shOp = Iop_ShrN32x4; 6422 narOp = Iop_NarrowUn32to16x4; 6423 break; 6424 case 3: 6425 addOp = Iop_Add64x2; 6426 shOp = Iop_ShrN64x2; 6427 narOp = Iop_NarrowUn64to32x2; 6428 break; 6429 default: 6430 vassert(0); 6431 } 6432 assign(res, unop(narOp, 6433 binop(addOp, 6434 binop(shOp, 6435 mkexpr(reg_m), 6436 mkU8(shift_imm)), 6437 binop(Iop_AndV128, 6438 binop(shOp, 6439 mkexpr(reg_m), 6440 mkU8(shift_imm - 1)), 6441 imm_val)))); 6442 putDRegI64(dreg, mkexpr(res), condT); 6443 if (shift_imm == 0) { 6444 DIP("vmov%u d%u, q%u, #%u\n", 8 << size, dreg, mreg, 6445 shift_imm); 6446 } else { 6447 DIP("vrshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg, 6448 shift_imm); 6449 } 6450 return True; 6451 } 6452 } else { 6453 /* fall through */ 6454 } 6455 case 9: 6456 dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF); 6457 mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF); 6458 if (mreg & 1) 6459 return False; 6460 mreg >>= 1; 6461 size++; 6462 if ((theInstr >> 8) & 1) { 6463 switch (size) { 6464 case 1: 6465 op = U ? Iop_ShrN16x8 : Iop_SarN16x8; 6466 cvt = U ? Iop_QNarrowUn16Uto8Ux8 : Iop_QNarrowUn16Sto8Sx8; 6467 cvt2 = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8; 6468 break; 6469 case 2: 6470 op = U ? Iop_ShrN32x4 : Iop_SarN32x4; 6471 cvt = U ? Iop_QNarrowUn32Uto16Ux4 : Iop_QNarrowUn32Sto16Sx4; 6472 cvt2 = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4; 6473 break; 6474 case 3: 6475 op = U ? Iop_ShrN64x2 : Iop_SarN64x2; 6476 cvt = U ? Iop_QNarrowUn64Uto32Ux2 : Iop_QNarrowUn64Sto32Sx2; 6477 cvt2 = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2; 6478 break; 6479 default: 6480 vassert(0); 6481 } 6482 DIP("vq%sshrn.%c%u d%u, q%u, #%u\n", B ? "r" : "", 6483 U ? 'u' : 's', 8 << size, dreg, mreg, shift_imm); 6484 } else { 6485 vassert(U); 6486 switch (size) { 6487 case 1: 6488 op = Iop_SarN16x8; 6489 cvt = Iop_QNarrowUn16Sto8Ux8; 6490 cvt2 = Iop_Widen8Uto16x8; 6491 break; 6492 case 2: 6493 op = Iop_SarN32x4; 6494 cvt = Iop_QNarrowUn32Sto16Ux4; 6495 cvt2 = Iop_Widen16Uto32x4; 6496 break; 6497 case 3: 6498 op = Iop_SarN64x2; 6499 cvt = Iop_QNarrowUn64Sto32Ux2; 6500 cvt2 = Iop_Widen32Uto64x2; 6501 break; 6502 default: 6503 vassert(0); 6504 } 6505 DIP("vq%sshrun.s%u d%u, q%u, #%u\n", B ? "r" : "", 6506 8 << size, dreg, mreg, shift_imm); 6507 } 6508 if (B) { 6509 if (shift_imm > 0) { 6510 imm = 1; 6511 switch (size) { 6512 case 1: imm = (imm << 16) | imm; /* fall through */ 6513 case 2: imm = (imm << 32) | imm; /* fall through */ 6514 case 3: break; 6515 case 0: default: vassert(0); 6516 } 6517 switch (size) { 6518 case 1: add = Iop_Add16x8; break; 6519 case 2: add = Iop_Add32x4; break; 6520 case 3: add = Iop_Add64x2; break; 6521 case 0: default: vassert(0); 6522 } 6523 } 6524 } 6525 reg_m = newTemp(Ity_V128); 6526 res = newTemp(Ity_V128); 6527 assign(reg_m, getQReg(mreg)); 6528 if (B) { 6529 /* VQRSHRN, VQRSHRUN */ 6530 assign(res, binop(add, 6531 binop(op, mkexpr(reg_m), mkU8(shift_imm)), 6532 binop(Iop_AndV128, 6533 binop(op, 6534 mkexpr(reg_m), 6535 mkU8(shift_imm - 1)), 6536 mkU128(imm)))); 6537 } else { 6538 /* VQSHRN, VQSHRUN */ 6539 assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm))); 6540 } 6541 #ifndef DISABLE_QC_FLAG 6542 setFlag_QC(unop(cvt2, unop(cvt, mkexpr(res))), mkexpr(res), 6543 True, condT); 6544 #endif 6545 putDRegI64(dreg, unop(cvt, mkexpr(res)), condT); 6546 return True; 6547 case 10: 6548 /* VSHLL 6549 VMOVL ::= VSHLL #0 */ 6550 if (B) 6551 return False; 6552 if (dreg & 1) 6553 return False; 6554 dreg >>= 1; 6555 shift_imm = (8 << size) - shift_imm; 6556 res = newTemp(Ity_V128); 6557 switch (size) { 6558 case 0: 6559 op = Iop_ShlN16x8; 6560 cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8; 6561 break; 6562 case 1: 6563 op = Iop_ShlN32x4; 6564 cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4; 6565 break; 6566 case 2: 6567 op = Iop_ShlN64x2; 6568 cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2; 6569 break; 6570 case 3: 6571 return False; 6572 default: 6573 vassert(0); 6574 } 6575 assign(res, binop(op, unop(cvt, getDRegI64(mreg)), mkU8(shift_imm))); 6576 putQReg(dreg, mkexpr(res), condT); 6577 if (shift_imm == 0) { 6578 DIP("vmovl.%c%u q%u, d%u\n", U ? 'u' : 's', 8 << size, 6579 dreg, mreg); 6580 } else { 6581 DIP("vshll.%c%u q%u, d%u, #%u\n", U ? 'u' : 's', 8 << size, 6582 dreg, mreg, shift_imm); 6583 } 6584 return True; 6585 case 14: 6586 case 15: 6587 /* VCVT floating-point <-> fixed-point */ 6588 if ((theInstr >> 8) & 1) { 6589 if (U) { 6590 op = Q ? Iop_F32ToFixed32Ux4_RZ : Iop_F32ToFixed32Ux2_RZ; 6591 } else { 6592 op = Q ? Iop_F32ToFixed32Sx4_RZ : Iop_F32ToFixed32Sx2_RZ; 6593 } 6594 DIP("vcvt.%c32.f32 %c%u, %c%u, #%u\n", U ? 'u' : 's', 6595 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, 6596 64 - ((theInstr >> 16) & 0x3f)); 6597 } else { 6598 if (U) { 6599 op = Q ? Iop_Fixed32UToF32x4_RN : Iop_Fixed32UToF32x2_RN; 6600 } else { 6601 op = Q ? Iop_Fixed32SToF32x4_RN : Iop_Fixed32SToF32x2_RN; 6602 } 6603 DIP("vcvt.f32.%c32 %c%u, %c%u, #%u\n", U ? 'u' : 's', 6604 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, 6605 64 - ((theInstr >> 16) & 0x3f)); 6606 } 6607 if (((theInstr >> 21) & 1) == 0) 6608 return False; 6609 if (Q) { 6610 putQReg(dreg, binop(op, getQReg(mreg), 6611 mkU8(64 - ((theInstr >> 16) & 0x3f))), condT); 6612 } else { 6613 putDRegI64(dreg, binop(op, getDRegI64(mreg), 6614 mkU8(64 - ((theInstr >> 16) & 0x3f))), condT); 6615 } 6616 return True; 6617 default: 6618 return False; 6619 6620 } 6621 return False; 6622 } 6623 6624 /* A7.4.5 Two registers, miscellaneous */ 6625 static 6626 Bool dis_neon_data_2reg_misc ( UInt theInstr, IRTemp condT ) 6627 { 6628 UInt A = (theInstr >> 16) & 3; 6629 UInt B = (theInstr >> 6) & 0x1f; 6630 UInt Q = (theInstr >> 6) & 1; 6631 UInt U = (theInstr >> 24) & 1; 6632 UInt size = (theInstr >> 18) & 3; 6633 UInt dreg = get_neon_d_regno(theInstr); 6634 UInt mreg = get_neon_m_regno(theInstr); 6635 UInt F = (theInstr >> 10) & 1; 6636 IRTemp arg_d; 6637 IRTemp arg_m; 6638 IRTemp res; 6639 switch (A) { 6640 case 0: 6641 if (Q) { 6642 arg_m = newTemp(Ity_V128); 6643 res = newTemp(Ity_V128); 6644 assign(arg_m, getQReg(mreg)); 6645 } else { 6646 arg_m = newTemp(Ity_I64); 6647 res = newTemp(Ity_I64); 6648 assign(arg_m, getDRegI64(mreg)); 6649 } 6650 switch (B >> 1) { 6651 case 0: { 6652 /* VREV64 */ 6653 IROp op; 6654 switch (size) { 6655 case 0: 6656 op = Q ? Iop_Reverse64_8x16 : Iop_Reverse64_8x8; 6657 break; 6658 case 1: 6659 op = Q ? Iop_Reverse64_16x8 : Iop_Reverse64_16x4; 6660 break; 6661 case 2: 6662 op = Q ? Iop_Reverse64_32x4 : Iop_Reverse64_32x2; 6663 break; 6664 case 3: 6665 return False; 6666 default: 6667 vassert(0); 6668 } 6669 assign(res, unop(op, mkexpr(arg_m))); 6670 DIP("vrev64.%u %c%u, %c%u\n", 8 << size, 6671 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6672 break; 6673 } 6674 case 1: { 6675 /* VREV32 */ 6676 IROp op; 6677 switch (size) { 6678 case 0: 6679 op = Q ? Iop_Reverse32_8x16 : Iop_Reverse32_8x8; 6680 break; 6681 case 1: 6682 op = Q ? Iop_Reverse32_16x8 : Iop_Reverse32_16x4; 6683 break; 6684 case 2: 6685 case 3: 6686 return False; 6687 default: 6688 vassert(0); 6689 } 6690 assign(res, unop(op, mkexpr(arg_m))); 6691 DIP("vrev32.%u %c%u, %c%u\n", 8 << size, 6692 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6693 break; 6694 } 6695 case 2: { 6696 /* VREV16 */ 6697 IROp op; 6698 switch (size) { 6699 case 0: 6700 op = Q ? Iop_Reverse16_8x16 : Iop_Reverse16_8x8; 6701 break; 6702 case 1: 6703 case 2: 6704 case 3: 6705 return False; 6706 default: 6707 vassert(0); 6708 } 6709 assign(res, unop(op, mkexpr(arg_m))); 6710 DIP("vrev16.%u %c%u, %c%u\n", 8 << size, 6711 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6712 break; 6713 } 6714 case 3: 6715 return False; 6716 case 4: 6717 case 5: { 6718 /* VPADDL */ 6719 IROp op; 6720 U = (theInstr >> 7) & 1; 6721 if (Q) { 6722 switch (size) { 6723 case 0: op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16; break; 6724 case 1: op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8; break; 6725 case 2: op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4; break; 6726 case 3: return False; 6727 default: vassert(0); 6728 } 6729 } else { 6730 switch (size) { 6731 case 0: op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8; break; 6732 case 1: op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4; break; 6733 case 2: op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2; break; 6734 case 3: return False; 6735 default: vassert(0); 6736 } 6737 } 6738 assign(res, unop(op, mkexpr(arg_m))); 6739 DIP("vpaddl.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size, 6740 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6741 break; 6742 } 6743 case 6: 6744 case 7: 6745 return False; 6746 case 8: { 6747 /* VCLS */ 6748 IROp op; 6749 switch (size) { 6750 case 0: op = Q ? Iop_Cls8Sx16 : Iop_Cls8Sx8; break; 6751 case 1: op = Q ? Iop_Cls16Sx8 : Iop_Cls16Sx4; break; 6752 case 2: op = Q ? Iop_Cls32Sx4 : Iop_Cls32Sx2; break; 6753 case 3: return False; 6754 default: vassert(0); 6755 } 6756 assign(res, unop(op, mkexpr(arg_m))); 6757 DIP("vcls.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg, 6758 Q ? 'q' : 'd', mreg); 6759 break; 6760 } 6761 case 9: { 6762 /* VCLZ */ 6763 IROp op; 6764 switch (size) { 6765 case 0: op = Q ? Iop_Clz8Sx16 : Iop_Clz8Sx8; break; 6766 case 1: op = Q ? Iop_Clz16Sx8 : Iop_Clz16Sx4; break; 6767 case 2: op = Q ? Iop_Clz32Sx4 : Iop_Clz32Sx2; break; 6768 case 3: return False; 6769 default: vassert(0); 6770 } 6771 assign(res, unop(op, mkexpr(arg_m))); 6772 DIP("vclz.i%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg, 6773 Q ? 'q' : 'd', mreg); 6774 break; 6775 } 6776 case 10: 6777 /* VCNT */ 6778 assign(res, unop(Q ? Iop_Cnt8x16 : Iop_Cnt8x8, mkexpr(arg_m))); 6779 DIP("vcnt.8 %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', 6780 mreg); 6781 break; 6782 case 11: 6783 /* VMVN */ 6784 if (Q) 6785 assign(res, unop(Iop_NotV128, mkexpr(arg_m))); 6786 else 6787 assign(res, unop(Iop_Not64, mkexpr(arg_m))); 6788 DIP("vmvn %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', 6789 mreg); 6790 break; 6791 case 12: 6792 case 13: { 6793 /* VPADAL */ 6794 IROp op, add_op; 6795 U = (theInstr >> 7) & 1; 6796 if (Q) { 6797 switch (size) { 6798 case 0: 6799 op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16; 6800 add_op = Iop_Add16x8; 6801 break; 6802 case 1: 6803 op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8; 6804 add_op = Iop_Add32x4; 6805 break; 6806 case 2: 6807 op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4; 6808 add_op = Iop_Add64x2; 6809 break; 6810 case 3: 6811 return False; 6812 default: 6813 vassert(0); 6814 } 6815 } else { 6816 switch (size) { 6817 case 0: 6818 op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8; 6819 add_op = Iop_Add16x4; 6820 break; 6821 case 1: 6822 op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4; 6823 add_op = Iop_Add32x2; 6824 break; 6825 case 2: 6826 op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2; 6827 add_op = Iop_Add64; 6828 break; 6829 case 3: 6830 return False; 6831 default: 6832 vassert(0); 6833 } 6834 } 6835 if (Q) { 6836 arg_d = newTemp(Ity_V128); 6837 assign(arg_d, getQReg(dreg)); 6838 } else { 6839 arg_d = newTemp(Ity_I64); 6840 assign(arg_d, getDRegI64(dreg)); 6841 } 6842 assign(res, binop(add_op, unop(op, mkexpr(arg_m)), 6843 mkexpr(arg_d))); 6844 DIP("vpadal.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size, 6845 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6846 break; 6847 } 6848 case 14: { 6849 /* VQABS */ 6850 IROp op_sub, op_qsub, op_cmp; 6851 IRTemp mask, tmp; 6852 IRExpr *zero1, *zero2; 6853 IRExpr *neg, *neg2; 6854 if (Q) { 6855 zero1 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 6856 zero2 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 6857 mask = newTemp(Ity_V128); 6858 tmp = newTemp(Ity_V128); 6859 } else { 6860 zero1 = mkU64(0); 6861 zero2 = mkU64(0); 6862 mask = newTemp(Ity_I64); 6863 tmp = newTemp(Ity_I64); 6864 } 6865 switch (size) { 6866 case 0: 6867 op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8; 6868 op_qsub = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8; 6869 op_cmp = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; 6870 break; 6871 case 1: 6872 op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4; 6873 op_qsub = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4; 6874 op_cmp = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; 6875 break; 6876 case 2: 6877 op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2; 6878 op_qsub = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2; 6879 op_cmp = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; 6880 break; 6881 case 3: 6882 return False; 6883 default: 6884 vassert(0); 6885 } 6886 assign(mask, binop(op_cmp, mkexpr(arg_m), zero1)); 6887 neg = binop(op_qsub, zero2, mkexpr(arg_m)); 6888 neg2 = binop(op_sub, zero2, mkexpr(arg_m)); 6889 assign(res, binop(Q ? Iop_OrV128 : Iop_Or64, 6890 binop(Q ? Iop_AndV128 : Iop_And64, 6891 mkexpr(mask), 6892 mkexpr(arg_m)), 6893 binop(Q ? Iop_AndV128 : Iop_And64, 6894 unop(Q ? Iop_NotV128 : Iop_Not64, 6895 mkexpr(mask)), 6896 neg))); 6897 #ifndef DISABLE_QC_FLAG 6898 assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64, 6899 binop(Q ? Iop_AndV128 : Iop_And64, 6900 mkexpr(mask), 6901 mkexpr(arg_m)), 6902 binop(Q ? Iop_AndV128 : Iop_And64, 6903 unop(Q ? Iop_NotV128 : Iop_Not64, 6904 mkexpr(mask)), 6905 neg2))); 6906 setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT); 6907 #endif 6908 DIP("vqabs.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg, 6909 Q ? 'q' : 'd', mreg); 6910 break; 6911 } 6912 case 15: { 6913 /* VQNEG */ 6914 IROp op, op2; 6915 IRExpr *zero; 6916 if (Q) { 6917 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 6918 } else { 6919 zero = mkU64(0); 6920 } 6921 switch (size) { 6922 case 0: 6923 op = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8; 6924 op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8; 6925 break; 6926 case 1: 6927 op = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4; 6928 op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4; 6929 break; 6930 case 2: 6931 op = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2; 6932 op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2; 6933 break; 6934 case 3: 6935 return False; 6936 default: 6937 vassert(0); 6938 } 6939 assign(res, binop(op, zero, mkexpr(arg_m))); 6940 #ifndef DISABLE_QC_FLAG 6941 setFlag_QC(mkexpr(res), binop(op2, zero, mkexpr(arg_m)), 6942 Q, condT); 6943 #endif 6944 DIP("vqneg.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg, 6945 Q ? 'q' : 'd', mreg); 6946 break; 6947 } 6948 default: 6949 vassert(0); 6950 } 6951 if (Q) { 6952 putQReg(dreg, mkexpr(res), condT); 6953 } else { 6954 putDRegI64(dreg, mkexpr(res), condT); 6955 } 6956 return True; 6957 case 1: 6958 if (Q) { 6959 arg_m = newTemp(Ity_V128); 6960 res = newTemp(Ity_V128); 6961 assign(arg_m, getQReg(mreg)); 6962 } else { 6963 arg_m = newTemp(Ity_I64); 6964 res = newTemp(Ity_I64); 6965 assign(arg_m, getDRegI64(mreg)); 6966 } 6967 switch ((B >> 1) & 0x7) { 6968 case 0: { 6969 /* VCGT #0 */ 6970 IRExpr *zero; 6971 IROp op; 6972 if (Q) { 6973 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 6974 } else { 6975 zero = mkU64(0); 6976 } 6977 if (F) { 6978 switch (size) { 6979 case 0: case 1: case 3: return False; 6980 case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break; 6981 default: vassert(0); 6982 } 6983 } else { 6984 switch (size) { 6985 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break; 6986 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break; 6987 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break; 6988 case 3: return False; 6989 default: vassert(0); 6990 } 6991 } 6992 assign(res, binop(op, mkexpr(arg_m), zero)); 6993 DIP("vcgt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size, 6994 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6995 break; 6996 } 6997 case 1: { 6998 /* VCGE #0 */ 6999 IROp op; 7000 IRExpr *zero; 7001 if (Q) { 7002 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 7003 } else { 7004 zero = mkU64(0); 7005 } 7006 if (F) { 7007 switch (size) { 7008 case 0: case 1: case 3: return False; 7009 case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break; 7010 default: vassert(0); 7011 } 7012 assign(res, binop(op, mkexpr(arg_m), zero)); 7013 } else { 7014 switch (size) { 7015 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break; 7016 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break; 7017 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break; 7018 case 3: return False; 7019 default: vassert(0); 7020 } 7021 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64, 7022 binop(op, zero, mkexpr(arg_m)))); 7023 } 7024 DIP("vcge.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size, 7025 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7026 break; 7027 } 7028 case 2: { 7029 /* VCEQ #0 */ 7030 IROp op; 7031 IRExpr *zero; 7032 if (F) { 7033 if (Q) { 7034 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 7035 } else { 7036 zero = mkU64(0); 7037 } 7038 switch (size) { 7039 case 0: case 1: case 3: return False; 7040 case 2: op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2; break; 7041 default: vassert(0); 7042 } 7043 assign(res, binop(op, zero, mkexpr(arg_m))); 7044 } else { 7045 switch (size) { 7046 case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break; 7047 case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break; 7048 case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break; 7049 case 3: return False; 7050 default: vassert(0); 7051 } 7052 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64, 7053 unop(op, mkexpr(arg_m)))); 7054 } 7055 DIP("vceq.%c%u %c%u, %c%u, #0\n", F ? 'f' : 'i', 8 << size, 7056 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7057 break; 7058 } 7059 case 3: { 7060 /* VCLE #0 */ 7061 IRExpr *zero; 7062 IROp op; 7063 if (Q) { 7064 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 7065 } else { 7066 zero = mkU64(0); 7067 } 7068 if (F) { 7069 switch (size) { 7070 case 0: case 1: case 3: return False; 7071 case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break; 7072 default: vassert(0); 7073 } 7074 assign(res, binop(op, zero, mkexpr(arg_m))); 7075 } else { 7076 switch (size) { 7077 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break; 7078 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break; 7079 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break; 7080 case 3: return False; 7081 default: vassert(0); 7082 } 7083 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64, 7084 binop(op, mkexpr(arg_m), zero))); 7085 } 7086 DIP("vcle.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size, 7087 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7088 break; 7089 } 7090 case 4: { 7091 /* VCLT #0 */ 7092 IROp op; 7093 IRExpr *zero; 7094 if (Q) { 7095 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 7096 } else { 7097 zero = mkU64(0); 7098 } 7099 if (F) { 7100 switch (size) { 7101 case 0: case 1: case 3: return False; 7102 case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break; 7103 default: vassert(0); 7104 } 7105 assign(res, binop(op, zero, mkexpr(arg_m))); 7106 } else { 7107 switch (size) { 7108 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break; 7109 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break; 7110 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break; 7111 case 3: return False; 7112 default: vassert(0); 7113 } 7114 assign(res, binop(op, zero, mkexpr(arg_m))); 7115 } 7116 DIP("vclt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size, 7117 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7118 break; 7119 } 7120 case 5: 7121 return False; 7122 case 6: { 7123 /* VABS */ 7124 if (!F) { 7125 IROp op; 7126 switch(size) { 7127 case 0: op = Q ? Iop_Abs8x16 : Iop_Abs8x8; break; 7128 case 1: op = Q ? Iop_Abs16x8 : Iop_Abs16x4; break; 7129 case 2: op = Q ? Iop_Abs32x4 : Iop_Abs32x2; break; 7130 case 3: return False; 7131 default: vassert(0); 7132 } 7133 assign(res, unop(op, mkexpr(arg_m))); 7134 } else { 7135 assign(res, unop(Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2, 7136 mkexpr(arg_m))); 7137 } 7138 DIP("vabs.%c%u %c%u, %c%u\n", 7139 F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg, 7140 Q ? 'q' : 'd', mreg); 7141 break; 7142 } 7143 case 7: { 7144 /* VNEG */ 7145 IROp op; 7146 IRExpr *zero; 7147 if (F) { 7148 switch (size) { 7149 case 0: case 1: case 3: return False; 7150 case 2: op = Q ? Iop_Neg32Fx4 : Iop_Neg32Fx2; break; 7151 default: vassert(0); 7152 } 7153 assign(res, unop(op, mkexpr(arg_m))); 7154 } else { 7155 if (Q) { 7156 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 7157 } else { 7158 zero = mkU64(0); 7159 } 7160 switch (size) { 7161 case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break; 7162 case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break; 7163 case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break; 7164 case 3: return False; 7165 default: vassert(0); 7166 } 7167 assign(res, binop(op, zero, mkexpr(arg_m))); 7168 } 7169 DIP("vneg.%c%u %c%u, %c%u\n", 7170 F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg, 7171 Q ? 'q' : 'd', mreg); 7172 break; 7173 } 7174 default: 7175 vassert(0); 7176 } 7177 if (Q) { 7178 putQReg(dreg, mkexpr(res), condT); 7179 } else { 7180 putDRegI64(dreg, mkexpr(res), condT); 7181 } 7182 return True; 7183 case 2: 7184 if ((B >> 1) == 0) { 7185 /* VSWP */ 7186 if (Q) { 7187 arg_m = newTemp(Ity_V128); 7188 assign(arg_m, getQReg(mreg)); 7189 putQReg(mreg, getQReg(dreg), condT); 7190 putQReg(dreg, mkexpr(arg_m), condT); 7191 } else { 7192 arg_m = newTemp(Ity_I64); 7193 assign(arg_m, getDRegI64(mreg)); 7194 putDRegI64(mreg, getDRegI64(dreg), condT); 7195 putDRegI64(dreg, mkexpr(arg_m), condT); 7196 } 7197 DIP("vswp %c%u, %c%u\n", 7198 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7199 return True; 7200 } else if ((B >> 1) == 1) { 7201 /* VTRN */ 7202 IROp op_lo, op_hi; 7203 IRTemp res1, res2; 7204 if (Q) { 7205 arg_m = newTemp(Ity_V128); 7206 arg_d = newTemp(Ity_V128); 7207 res1 = newTemp(Ity_V128); 7208 res2 = newTemp(Ity_V128); 7209 assign(arg_m, getQReg(mreg)); 7210 assign(arg_d, getQReg(dreg)); 7211 } else { 7212 res1 = newTemp(Ity_I64); 7213 res2 = newTemp(Ity_I64); 7214 arg_m = newTemp(Ity_I64); 7215 arg_d = newTemp(Ity_I64); 7216 assign(arg_m, getDRegI64(mreg)); 7217 assign(arg_d, getDRegI64(dreg)); 7218 } 7219 if (Q) { 7220 switch (size) { 7221 case 0: 7222 op_lo = Iop_InterleaveOddLanes8x16; 7223 op_hi = Iop_InterleaveEvenLanes8x16; 7224 break; 7225 case 1: 7226 op_lo = Iop_InterleaveOddLanes16x8; 7227 op_hi = Iop_InterleaveEvenLanes16x8; 7228 break; 7229 case 2: 7230 op_lo = Iop_InterleaveOddLanes32x4; 7231 op_hi = Iop_InterleaveEvenLanes32x4; 7232 break; 7233 case 3: 7234 return False; 7235 default: 7236 vassert(0); 7237 } 7238 } else { 7239 switch (size) { 7240 case 0: 7241 op_lo = Iop_InterleaveOddLanes8x8; 7242 op_hi = Iop_InterleaveEvenLanes8x8; 7243 break; 7244 case 1: 7245 op_lo = Iop_InterleaveOddLanes16x4; 7246 op_hi = Iop_InterleaveEvenLanes16x4; 7247 break; 7248 case 2: 7249 op_lo = Iop_InterleaveLO32x2; 7250 op_hi = Iop_InterleaveHI32x2; 7251 break; 7252 case 3: 7253 return False; 7254 default: 7255 vassert(0); 7256 } 7257 } 7258 assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d))); 7259 assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d))); 7260 if (Q) { 7261 putQReg(dreg, mkexpr(res1), condT); 7262 putQReg(mreg, mkexpr(res2), condT); 7263 } else { 7264 putDRegI64(dreg, mkexpr(res1), condT); 7265 putDRegI64(mreg, mkexpr(res2), condT); 7266 } 7267 DIP("vtrn.%u %c%u, %c%u\n", 7268 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7269 return True; 7270 } else if ((B >> 1) == 2) { 7271 /* VUZP */ 7272 IROp op_lo, op_hi; 7273 IRTemp res1, res2; 7274 if (!Q && size == 2) 7275 return False; 7276 if (Q) { 7277 arg_m = newTemp(Ity_V128); 7278 arg_d = newTemp(Ity_V128); 7279 res1 = newTemp(Ity_V128); 7280 res2 = newTemp(Ity_V128); 7281 assign(arg_m, getQReg(mreg)); 7282 assign(arg_d, getQReg(dreg)); 7283 } else { 7284 res1 = newTemp(Ity_I64); 7285 res2 = newTemp(Ity_I64); 7286 arg_m = newTemp(Ity_I64); 7287 arg_d = newTemp(Ity_I64); 7288 assign(arg_m, getDRegI64(mreg)); 7289 assign(arg_d, getDRegI64(dreg)); 7290 } 7291 switch (size) { 7292 case 0: 7293 op_lo = Q ? Iop_CatOddLanes8x16 : Iop_CatOddLanes8x8; 7294 op_hi = Q ? Iop_CatEvenLanes8x16 : Iop_CatEvenLanes8x8; 7295 break; 7296 case 1: 7297 op_lo = Q ? Iop_CatOddLanes16x8 : Iop_CatOddLanes16x4; 7298 op_hi = Q ? Iop_CatEvenLanes16x8 : Iop_CatEvenLanes16x4; 7299 break; 7300 case 2: 7301 op_lo = Iop_CatOddLanes32x4; 7302 op_hi = Iop_CatEvenLanes32x4; 7303 break; 7304 case 3: 7305 return False; 7306 default: 7307 vassert(0); 7308 } 7309 assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d))); 7310 assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d))); 7311 if (Q) { 7312 putQReg(dreg, mkexpr(res1), condT); 7313 putQReg(mreg, mkexpr(res2), condT); 7314 } else { 7315 putDRegI64(dreg, mkexpr(res1), condT); 7316 putDRegI64(mreg, mkexpr(res2), condT); 7317 } 7318 DIP("vuzp.%u %c%u, %c%u\n", 7319 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7320 return True; 7321 } else if ((B >> 1) == 3) { 7322 /* VZIP */ 7323 IROp op_lo, op_hi; 7324 IRTemp res1, res2; 7325 if (!Q && size == 2) 7326 return False; 7327 if (Q) { 7328 arg_m = newTemp(Ity_V128); 7329 arg_d = newTemp(Ity_V128); 7330 res1 = newTemp(Ity_V128); 7331 res2 = newTemp(Ity_V128); 7332 assign(arg_m, getQReg(mreg)); 7333 assign(arg_d, getQReg(dreg)); 7334 } else { 7335 res1 = newTemp(Ity_I64); 7336 res2 = newTemp(Ity_I64); 7337 arg_m = newTemp(Ity_I64); 7338 arg_d = newTemp(Ity_I64); 7339 assign(arg_m, getDRegI64(mreg)); 7340 assign(arg_d, getDRegI64(dreg)); 7341 } 7342 switch (size) { 7343 case 0: 7344 op_lo = Q ? Iop_InterleaveHI8x16 : Iop_InterleaveHI8x8; 7345 op_hi = Q ? Iop_InterleaveLO8x16 : Iop_InterleaveLO8x8; 7346 break; 7347 case 1: 7348 op_lo = Q ? Iop_InterleaveHI16x8 : Iop_InterleaveHI16x4; 7349 op_hi = Q ? Iop_InterleaveLO16x8 : Iop_InterleaveLO16x4; 7350 break; 7351 case 2: 7352 op_lo = Iop_InterleaveHI32x4; 7353 op_hi = Iop_InterleaveLO32x4; 7354 break; 7355 case 3: 7356 return False; 7357 default: 7358 vassert(0); 7359 } 7360 assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d))); 7361 assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d))); 7362 if (Q) { 7363 putQReg(dreg, mkexpr(res1), condT); 7364 putQReg(mreg, mkexpr(res2), condT); 7365 } else { 7366 putDRegI64(dreg, mkexpr(res1), condT); 7367 putDRegI64(mreg, mkexpr(res2), condT); 7368 } 7369 DIP("vzip.%u %c%u, %c%u\n", 7370 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7371 return True; 7372 } else if (B == 8) { 7373 /* VMOVN */ 7374 IROp op; 7375 mreg >>= 1; 7376 switch (size) { 7377 case 0: op = Iop_NarrowUn16to8x8; break; 7378 case 1: op = Iop_NarrowUn32to16x4; break; 7379 case 2: op = Iop_NarrowUn64to32x2; break; 7380 case 3: return False; 7381 default: vassert(0); 7382 } 7383 putDRegI64(dreg, unop(op, getQReg(mreg)), condT); 7384 DIP("vmovn.i%u d%u, q%u\n", 16 << size, dreg, mreg); 7385 return True; 7386 } else if (B == 9 || (B >> 1) == 5) { 7387 /* VQMOVN, VQMOVUN */ 7388 IROp op, op2; 7389 IRTemp tmp; 7390 dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF); 7391 mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF); 7392 if (mreg & 1) 7393 return False; 7394 mreg >>= 1; 7395 switch (size) { 7396 case 0: op2 = Iop_NarrowUn16to8x8; break; 7397 case 1: op2 = Iop_NarrowUn32to16x4; break; 7398 case 2: op2 = Iop_NarrowUn64to32x2; break; 7399 case 3: return False; 7400 default: vassert(0); 7401 } 7402 switch (B & 3) { 7403 case 0: 7404 vassert(0); 7405 case 1: 7406 switch (size) { 7407 case 0: op = Iop_QNarrowUn16Sto8Ux8; break; 7408 case 1: op = Iop_QNarrowUn32Sto16Ux4; break; 7409 case 2: op = Iop_QNarrowUn64Sto32Ux2; break; 7410 case 3: return False; 7411 default: vassert(0); 7412 } 7413 DIP("vqmovun.s%u d%u, q%u\n", 16 << size, dreg, mreg); 7414 break; 7415 case 2: 7416 switch (size) { 7417 case 0: op = Iop_QNarrowUn16Sto8Sx8; break; 7418 case 1: op = Iop_QNarrowUn32Sto16Sx4; break; 7419 case 2: op = Iop_QNarrowUn64Sto32Sx2; break; 7420 case 3: return False; 7421 default: vassert(0); 7422 } 7423 DIP("vqmovn.s%u d%u, q%u\n", 16 << size, dreg, mreg); 7424 break; 7425 case 3: 7426 switch (size) { 7427 case 0: op = Iop_QNarrowUn16Uto8Ux8; break; 7428 case 1: op = Iop_QNarrowUn32Uto16Ux4; break; 7429 case 2: op = Iop_QNarrowUn64Uto32Ux2; break; 7430 case 3: return False; 7431 default: vassert(0); 7432 } 7433 DIP("vqmovn.u%u d%u, q%u\n", 16 << size, dreg, mreg); 7434 break; 7435 default: 7436 vassert(0); 7437 } 7438 res = newTemp(Ity_I64); 7439 tmp = newTemp(Ity_I64); 7440 assign(res, unop(op, getQReg(mreg))); 7441 #ifndef DISABLE_QC_FLAG 7442 assign(tmp, unop(op2, getQReg(mreg))); 7443 setFlag_QC(mkexpr(res), mkexpr(tmp), False, condT); 7444 #endif 7445 putDRegI64(dreg, mkexpr(res), condT); 7446 return True; 7447 } else if (B == 12) { 7448 /* VSHLL (maximum shift) */ 7449 IROp op, cvt; 7450 UInt shift_imm; 7451 if (Q) 7452 return False; 7453 if (dreg & 1) 7454 return False; 7455 dreg >>= 1; 7456 shift_imm = 8 << size; 7457 res = newTemp(Ity_V128); 7458 switch (size) { 7459 case 0: op = Iop_ShlN16x8; cvt = Iop_Widen8Uto16x8; break; 7460 case 1: op = Iop_ShlN32x4; cvt = Iop_Widen16Uto32x4; break; 7461 case 2: op = Iop_ShlN64x2; cvt = Iop_Widen32Uto64x2; break; 7462 case 3: return False; 7463 default: vassert(0); 7464 } 7465 assign(res, binop(op, unop(cvt, getDRegI64(mreg)), 7466 mkU8(shift_imm))); 7467 putQReg(dreg, mkexpr(res), condT); 7468 DIP("vshll.i%u q%u, d%u, #%u\n", 8 << size, dreg, mreg, 8 << size); 7469 return True; 7470 } else if ((B >> 3) == 3 && (B & 3) == 0) { 7471 /* VCVT (half<->single) */ 7472 /* Half-precision extensions are needed to run this */ 7473 vassert(0); // ATC 7474 if (((theInstr >> 18) & 3) != 1) 7475 return False; 7476 if ((theInstr >> 8) & 1) { 7477 if (dreg & 1) 7478 return False; 7479 dreg >>= 1; 7480 putQReg(dreg, unop(Iop_F16toF32x4, getDRegI64(mreg)), 7481 condT); 7482 DIP("vcvt.f32.f16 q%u, d%u\n", dreg, mreg); 7483 } else { 7484 if (mreg & 1) 7485 return False; 7486 mreg >>= 1; 7487 putDRegI64(dreg, unop(Iop_F32toF16x4, getQReg(mreg)), 7488 condT); 7489 DIP("vcvt.f16.f32 d%u, q%u\n", dreg, mreg); 7490 } 7491 return True; 7492 } else { 7493 return False; 7494 } 7495 vassert(0); 7496 return True; 7497 case 3: 7498 if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,0)) { 7499 /* VRECPE */ 7500 IROp op; 7501 F = (theInstr >> 8) & 1; 7502 if (size != 2) 7503 return False; 7504 if (Q) { 7505 op = F ? Iop_Recip32Fx4 : Iop_Recip32x4; 7506 putQReg(dreg, unop(op, getQReg(mreg)), condT); 7507 DIP("vrecpe.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg); 7508 } else { 7509 op = F ? Iop_Recip32Fx2 : Iop_Recip32x2; 7510 putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT); 7511 DIP("vrecpe.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg); 7512 } 7513 return True; 7514 } else if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,1)) { 7515 /* VRSQRTE */ 7516 IROp op; 7517 F = (B >> 2) & 1; 7518 if (size != 2) 7519 return False; 7520 if (F) { 7521 /* fp */ 7522 op = Q ? Iop_Rsqrte32Fx4 : Iop_Rsqrte32Fx2; 7523 } else { 7524 /* unsigned int */ 7525 op = Q ? Iop_Rsqrte32x4 : Iop_Rsqrte32x2; 7526 } 7527 if (Q) { 7528 putQReg(dreg, unop(op, getQReg(mreg)), condT); 7529 DIP("vrsqrte.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg); 7530 } else { 7531 putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT); 7532 DIP("vrsqrte.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg); 7533 } 7534 return True; 7535 } else if ((B >> 3) == 3) { 7536 /* VCVT (fp<->integer) */ 7537 IROp op; 7538 if (size != 2) 7539 return False; 7540 switch ((B >> 1) & 3) { 7541 case 0: 7542 op = Q ? Iop_I32StoFx4 : Iop_I32StoFx2; 7543 DIP("vcvt.f32.s32 %c%u, %c%u\n", 7544 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7545 break; 7546 case 1: 7547 op = Q ? Iop_I32UtoFx4 : Iop_I32UtoFx2; 7548 DIP("vcvt.f32.u32 %c%u, %c%u\n", 7549 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7550 break; 7551 case 2: 7552 op = Q ? Iop_FtoI32Sx4_RZ : Iop_FtoI32Sx2_RZ; 7553 DIP("vcvt.s32.f32 %c%u, %c%u\n", 7554 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7555 break; 7556 case 3: 7557 op = Q ? Iop_FtoI32Ux4_RZ : Iop_FtoI32Ux2_RZ; 7558 DIP("vcvt.u32.f32 %c%u, %c%u\n", 7559 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7560 break; 7561 default: 7562 vassert(0); 7563 } 7564 if (Q) { 7565 putQReg(dreg, unop(op, getQReg(mreg)), condT); 7566 } else { 7567 putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT); 7568 } 7569 return True; 7570 } else { 7571 return False; 7572 } 7573 vassert(0); 7574 return True; 7575 default: 7576 vassert(0); 7577 } 7578 return False; 7579 } 7580 7581 /* A7.4.6 One register and a modified immediate value */ 7582 static 7583 void ppNeonImm(UInt imm, UInt cmode, UInt op) 7584 { 7585 int i; 7586 switch (cmode) { 7587 case 0: case 1: case 8: case 9: 7588 vex_printf("0x%x", imm); 7589 break; 7590 case 2: case 3: case 10: case 11: 7591 vex_printf("0x%x00", imm); 7592 break; 7593 case 4: case 5: 7594 vex_printf("0x%x0000", imm); 7595 break; 7596 case 6: case 7: 7597 vex_printf("0x%x000000", imm); 7598 break; 7599 case 12: 7600 vex_printf("0x%xff", imm); 7601 break; 7602 case 13: 7603 vex_printf("0x%xffff", imm); 7604 break; 7605 case 14: 7606 if (op) { 7607 vex_printf("0x"); 7608 for (i = 7; i >= 0; i--) 7609 vex_printf("%s", (imm & (1 << i)) ? "ff" : "00"); 7610 } else { 7611 vex_printf("0x%x", imm); 7612 } 7613 break; 7614 case 15: 7615 vex_printf("0x%x", imm); 7616 break; 7617 } 7618 } 7619 7620 static 7621 const char *ppNeonImmType(UInt cmode, UInt op) 7622 { 7623 switch (cmode) { 7624 case 0 ... 7: 7625 case 12: case 13: 7626 return "i32"; 7627 case 8 ... 11: 7628 return "i16"; 7629 case 14: 7630 if (op) 7631 return "i64"; 7632 else 7633 return "i8"; 7634 case 15: 7635 if (op) 7636 vassert(0); 7637 else 7638 return "f32"; 7639 default: 7640 vassert(0); 7641 } 7642 } 7643 7644 static 7645 void DIPimm(UInt imm, UInt cmode, UInt op, 7646 const char *instr, UInt Q, UInt dreg) 7647 { 7648 if (vex_traceflags & VEX_TRACE_FE) { 7649 vex_printf("%s.%s %c%u, #", instr, 7650 ppNeonImmType(cmode, op), Q ? 'q' : 'd', dreg); 7651 ppNeonImm(imm, cmode, op); 7652 vex_printf("\n"); 7653 } 7654 } 7655 7656 static 7657 Bool dis_neon_data_1reg_and_imm ( UInt theInstr, IRTemp condT ) 7658 { 7659 UInt dreg = get_neon_d_regno(theInstr); 7660 ULong imm_raw = ((theInstr >> 17) & 0x80) | ((theInstr >> 12) & 0x70) | 7661 (theInstr & 0xf); 7662 ULong imm_raw_pp = imm_raw; 7663 UInt cmode = (theInstr >> 8) & 0xf; 7664 UInt op_bit = (theInstr >> 5) & 1; 7665 ULong imm = 0; 7666 UInt Q = (theInstr >> 6) & 1; 7667 int i, j; 7668 UInt tmp; 7669 IRExpr *imm_val; 7670 IRExpr *expr; 7671 IRTemp tmp_var; 7672 switch(cmode) { 7673 case 7: case 6: 7674 imm_raw = imm_raw << 8; 7675 /* fallthrough */ 7676 case 5: case 4: 7677 imm_raw = imm_raw << 8; 7678 /* fallthrough */ 7679 case 3: case 2: 7680 imm_raw = imm_raw << 8; 7681 /* fallthrough */ 7682 case 0: case 1: 7683 imm = (imm_raw << 32) | imm_raw; 7684 break; 7685 case 11: case 10: 7686 imm_raw = imm_raw << 8; 7687 /* fallthrough */ 7688 case 9: case 8: 7689 imm_raw = (imm_raw << 16) | imm_raw; 7690 imm = (imm_raw << 32) | imm_raw; 7691 break; 7692 case 13: 7693 imm_raw = (imm_raw << 8) | 0xff; 7694 /* fallthrough */ 7695 case 12: 7696 imm_raw = (imm_raw << 8) | 0xff; 7697 imm = (imm_raw << 32) | imm_raw; 7698 break; 7699 case 14: 7700 if (! op_bit) { 7701 for(i = 0; i < 8; i++) { 7702 imm = (imm << 8) | imm_raw; 7703 } 7704 } else { 7705 for(i = 7; i >= 0; i--) { 7706 tmp = 0; 7707 for(j = 0; j < 8; j++) { 7708 tmp = (tmp << 1) | ((imm_raw >> i) & 1); 7709 } 7710 imm = (imm << 8) | tmp; 7711 } 7712 } 7713 break; 7714 case 15: 7715 imm = (imm_raw & 0x80) << 5; 7716 imm |= ((~imm_raw & 0x40) << 5); 7717 for(i = 1; i <= 4; i++) 7718 imm |= (imm_raw & 0x40) << i; 7719 imm |= (imm_raw & 0x7f); 7720 imm = imm << 19; 7721 imm = (imm << 32) | imm; 7722 break; 7723 default: 7724 return False; 7725 } 7726 if (Q) { 7727 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)); 7728 } else { 7729 imm_val = mkU64(imm); 7730 } 7731 if (((op_bit == 0) && 7732 (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 12) == 12))) || 7733 ((op_bit == 1) && (cmode == 14))) { 7734 /* VMOV (immediate) */ 7735 if (Q) { 7736 putQReg(dreg, imm_val, condT); 7737 } else { 7738 putDRegI64(dreg, imm_val, condT); 7739 } 7740 DIPimm(imm_raw_pp, cmode, op_bit, "vmov", Q, dreg); 7741 return True; 7742 } 7743 if ((op_bit == 1) && 7744 (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 14) == 12))) { 7745 /* VMVN (immediate) */ 7746 if (Q) { 7747 putQReg(dreg, unop(Iop_NotV128, imm_val), condT); 7748 } else { 7749 putDRegI64(dreg, unop(Iop_Not64, imm_val), condT); 7750 } 7751 DIPimm(imm_raw_pp, cmode, op_bit, "vmvn", Q, dreg); 7752 return True; 7753 } 7754 if (Q) { 7755 tmp_var = newTemp(Ity_V128); 7756 assign(tmp_var, getQReg(dreg)); 7757 } else { 7758 tmp_var = newTemp(Ity_I64); 7759 assign(tmp_var, getDRegI64(dreg)); 7760 } 7761 if ((op_bit == 0) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) { 7762 /* VORR (immediate) */ 7763 if (Q) 7764 expr = binop(Iop_OrV128, mkexpr(tmp_var), imm_val); 7765 else 7766 expr = binop(Iop_Or64, mkexpr(tmp_var), imm_val); 7767 DIPimm(imm_raw_pp, cmode, op_bit, "vorr", Q, dreg); 7768 } else if ((op_bit == 1) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) { 7769 /* VBIC (immediate) */ 7770 if (Q) 7771 expr = binop(Iop_AndV128, mkexpr(tmp_var), 7772 unop(Iop_NotV128, imm_val)); 7773 else 7774 expr = binop(Iop_And64, mkexpr(tmp_var), unop(Iop_Not64, imm_val)); 7775 DIPimm(imm_raw_pp, cmode, op_bit, "vbic", Q, dreg); 7776 } else { 7777 return False; 7778 } 7779 if (Q) 7780 putQReg(dreg, expr, condT); 7781 else 7782 putDRegI64(dreg, expr, condT); 7783 return True; 7784 } 7785 7786 /* A7.4 Advanced SIMD data-processing instructions */ 7787 static 7788 Bool dis_neon_data_processing ( UInt theInstr, IRTemp condT ) 7789 { 7790 UInt A = (theInstr >> 19) & 0x1F; 7791 UInt B = (theInstr >> 8) & 0xF; 7792 UInt C = (theInstr >> 4) & 0xF; 7793 UInt U = (theInstr >> 24) & 0x1; 7794 7795 if (! (A & 0x10)) { 7796 return dis_neon_data_3same(theInstr, condT); 7797 } 7798 if (((A & 0x17) == 0x10) && ((C & 0x9) == 0x1)) { 7799 return dis_neon_data_1reg_and_imm(theInstr, condT); 7800 } 7801 if ((C & 1) == 1) { 7802 return dis_neon_data_2reg_and_shift(theInstr, condT); 7803 } 7804 if (((C & 5) == 0) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) { 7805 return dis_neon_data_3diff(theInstr, condT); 7806 } 7807 if (((C & 5) == 4) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) { 7808 return dis_neon_data_2reg_and_scalar(theInstr, condT); 7809 } 7810 if ((A & 0x16) == 0x16) { 7811 if ((U == 0) && ((C & 1) == 0)) { 7812 return dis_neon_vext(theInstr, condT); 7813 } 7814 if ((U != 1) || ((C & 1) == 1)) 7815 return False; 7816 if ((B & 8) == 0) { 7817 return dis_neon_data_2reg_misc(theInstr, condT); 7818 } 7819 if ((B & 12) == 8) { 7820 return dis_neon_vtb(theInstr, condT); 7821 } 7822 if ((B == 12) && ((C & 9) == 0)) { 7823 return dis_neon_vdup(theInstr, condT); 7824 } 7825 } 7826 return False; 7827 } 7828 7829 7830 /*------------------------------------------------------------*/ 7831 /*--- NEON loads and stores ---*/ 7832 /*------------------------------------------------------------*/ 7833 7834 /* For NEON memory operations, we use the standard scheme to handle 7835 conditionalisation: generate a jump around the instruction if the 7836 condition is false. That's only necessary in Thumb mode, however, 7837 since in ARM mode NEON instructions are unconditional. */ 7838 7839 /* A helper function for what follows. It assumes we already went 7840 uncond as per comments at the top of this section. */ 7841 static 7842 void mk_neon_elem_load_to_one_lane( UInt rD, UInt inc, UInt index, 7843 UInt N, UInt size, IRTemp addr ) 7844 { 7845 UInt i; 7846 switch (size) { 7847 case 0: 7848 putDRegI64(rD, triop(Iop_SetElem8x8, getDRegI64(rD), mkU8(index), 7849 loadLE(Ity_I8, mkexpr(addr))), IRTemp_INVALID); 7850 break; 7851 case 1: 7852 putDRegI64(rD, triop(Iop_SetElem16x4, getDRegI64(rD), mkU8(index), 7853 loadLE(Ity_I16, mkexpr(addr))), IRTemp_INVALID); 7854 break; 7855 case 2: 7856 putDRegI64(rD, triop(Iop_SetElem32x2, getDRegI64(rD), mkU8(index), 7857 loadLE(Ity_I32, mkexpr(addr))), IRTemp_INVALID); 7858 break; 7859 default: 7860 vassert(0); 7861 } 7862 for (i = 1; i <= N; i++) { 7863 switch (size) { 7864 case 0: 7865 putDRegI64(rD + i * inc, 7866 triop(Iop_SetElem8x8, 7867 getDRegI64(rD + i * inc), 7868 mkU8(index), 7869 loadLE(Ity_I8, binop(Iop_Add32, 7870 mkexpr(addr), 7871 mkU32(i * 1)))), 7872 IRTemp_INVALID); 7873 break; 7874 case 1: 7875 putDRegI64(rD + i * inc, 7876 triop(Iop_SetElem16x4, 7877 getDRegI64(rD + i * inc), 7878 mkU8(index), 7879 loadLE(Ity_I16, binop(Iop_Add32, 7880 mkexpr(addr), 7881 mkU32(i * 2)))), 7882 IRTemp_INVALID); 7883 break; 7884 case 2: 7885 putDRegI64(rD + i * inc, 7886 triop(Iop_SetElem32x2, 7887 getDRegI64(rD + i * inc), 7888 mkU8(index), 7889 loadLE(Ity_I32, binop(Iop_Add32, 7890 mkexpr(addr), 7891 mkU32(i * 4)))), 7892 IRTemp_INVALID); 7893 break; 7894 default: 7895 vassert(0); 7896 } 7897 } 7898 } 7899 7900 /* A(nother) helper function for what follows. It assumes we already 7901 went uncond as per comments at the top of this section. */ 7902 static 7903 void mk_neon_elem_store_from_one_lane( UInt rD, UInt inc, UInt index, 7904 UInt N, UInt size, IRTemp addr ) 7905 { 7906 UInt i; 7907 switch (size) { 7908 case 0: 7909 storeLE(mkexpr(addr), 7910 binop(Iop_GetElem8x8, getDRegI64(rD), mkU8(index))); 7911 break; 7912 case 1: 7913 storeLE(mkexpr(addr), 7914 binop(Iop_GetElem16x4, getDRegI64(rD), mkU8(index))); 7915 break; 7916 case 2: 7917 storeLE(mkexpr(addr), 7918 binop(Iop_GetElem32x2, getDRegI64(rD), mkU8(index))); 7919 break; 7920 default: 7921 vassert(0); 7922 } 7923 for (i = 1; i <= N; i++) { 7924 switch (size) { 7925 case 0: 7926 storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 1)), 7927 binop(Iop_GetElem8x8, getDRegI64(rD + i * inc), 7928 mkU8(index))); 7929 break; 7930 case 1: 7931 storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 2)), 7932 binop(Iop_GetElem16x4, getDRegI64(rD + i * inc), 7933 mkU8(index))); 7934 break; 7935 case 2: 7936 storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 4)), 7937 binop(Iop_GetElem32x2, getDRegI64(rD + i * inc), 7938 mkU8(index))); 7939 break; 7940 default: 7941 vassert(0); 7942 } 7943 } 7944 } 7945 7946 /* A7.7 Advanced SIMD element or structure load/store instructions */ 7947 static 7948 Bool dis_neon_load_or_store ( UInt theInstr, 7949 Bool isT, IRTemp condT ) 7950 { 7951 # define INSN(_bMax,_bMin) SLICE_UInt(theInstr, (_bMax), (_bMin)) 7952 UInt bA = INSN(23,23); 7953 UInt fB = INSN(11,8); 7954 UInt bL = INSN(21,21); 7955 UInt rD = (INSN(22,22) << 4) | INSN(15,12); 7956 UInt rN = INSN(19,16); 7957 UInt rM = INSN(3,0); 7958 UInt N, size, i, j; 7959 UInt inc; 7960 UInt regs = 1; 7961 7962 if (isT) { 7963 vassert(condT != IRTemp_INVALID); 7964 } else { 7965 vassert(condT == IRTemp_INVALID); 7966 } 7967 /* So now, if condT is not IRTemp_INVALID, we know we're 7968 dealing with Thumb code. */ 7969 7970 if (INSN(20,20) != 0) 7971 return False; 7972 7973 IRTemp initialRn = newTemp(Ity_I32); 7974 assign(initialRn, isT ? getIRegT(rN) : getIRegA(rN)); 7975 7976 IRTemp initialRm = newTemp(Ity_I32); 7977 assign(initialRm, isT ? getIRegT(rM) : getIRegA(rM)); 7978 7979 /* There are 3 cases: 7980 (1) VSTn / VLDn (n-element structure from/to one lane) 7981 (2) VLDn (single element to all lanes) 7982 (3) VSTn / VLDn (multiple n-element structures) 7983 */ 7984 if (bA) { 7985 N = fB & 3; 7986 if ((fB >> 2) < 3) { 7987 /* ------------ Case (1) ------------ 7988 VSTn / VLDn (n-element structure from/to one lane) */ 7989 7990 size = fB >> 2; 7991 7992 switch (size) { 7993 case 0: i = INSN(7,5); inc = 1; break; 7994 case 1: i = INSN(7,6); inc = INSN(5,5) ? 2 : 1; break; 7995 case 2: i = INSN(7,7); inc = INSN(6,6) ? 2 : 1; break; 7996 case 3: return False; 7997 default: vassert(0); 7998 } 7999 8000 IRTemp addr = newTemp(Ity_I32); 8001 assign(addr, mkexpr(initialRn)); 8002 8003 // go uncond 8004 if (condT != IRTemp_INVALID) 8005 mk_skip_over_T32_if_cond_is_false(condT); 8006 // now uncond 8007 8008 if (bL) 8009 mk_neon_elem_load_to_one_lane(rD, inc, i, N, size, addr); 8010 else 8011 mk_neon_elem_store_from_one_lane(rD, inc, i, N, size, addr); 8012 DIP("v%s%u.%u {", bL ? "ld" : "st", N + 1, 8 << size); 8013 for (j = 0; j <= N; j++) { 8014 if (j) 8015 DIP(", "); 8016 DIP("d%u[%u]", rD + j * inc, i); 8017 } 8018 DIP("}, [r%u]", rN); 8019 if (rM != 13 && rM != 15) { 8020 DIP(", r%u\n", rM); 8021 } else { 8022 DIP("%s\n", (rM != 15) ? "!" : ""); 8023 } 8024 } else { 8025 /* ------------ Case (2) ------------ 8026 VLDn (single element to all lanes) */ 8027 UInt r; 8028 if (bL == 0) 8029 return False; 8030 8031 inc = INSN(5,5) + 1; 8032 size = INSN(7,6); 8033 8034 /* size == 3 and size == 2 cases differ in alignment constraints */ 8035 if (size == 3 && N == 3 && INSN(4,4) == 1) 8036 size = 2; 8037 8038 if (size == 0 && N == 0 && INSN(4,4) == 1) 8039 return False; 8040 if (N == 2 && INSN(4,4) == 1) 8041 return False; 8042 if (size == 3) 8043 return False; 8044 8045 // go uncond 8046 if (condT != IRTemp_INVALID) 8047 mk_skip_over_T32_if_cond_is_false(condT); 8048 // now uncond 8049 8050 IRTemp addr = newTemp(Ity_I32); 8051 assign(addr, mkexpr(initialRn)); 8052 8053 if (N == 0 && INSN(5,5)) 8054 regs = 2; 8055 8056 for (r = 0; r < regs; r++) { 8057 switch (size) { 8058 case 0: 8059 putDRegI64(rD + r, unop(Iop_Dup8x8, 8060 loadLE(Ity_I8, mkexpr(addr))), 8061 IRTemp_INVALID); 8062 break; 8063 case 1: 8064 putDRegI64(rD + r, unop(Iop_Dup16x4, 8065 loadLE(Ity_I16, mkexpr(addr))), 8066 IRTemp_INVALID); 8067 break; 8068 case 2: 8069 putDRegI64(rD + r, unop(Iop_Dup32x2, 8070 loadLE(Ity_I32, mkexpr(addr))), 8071 IRTemp_INVALID); 8072 break; 8073 default: 8074 vassert(0); 8075 } 8076 for (i = 1; i <= N; i++) { 8077 switch (size) { 8078 case 0: 8079 putDRegI64(rD + r + i * inc, 8080 unop(Iop_Dup8x8, 8081 loadLE(Ity_I8, binop(Iop_Add32, 8082 mkexpr(addr), 8083 mkU32(i * 1)))), 8084 IRTemp_INVALID); 8085 break; 8086 case 1: 8087 putDRegI64(rD + r + i * inc, 8088 unop(Iop_Dup16x4, 8089 loadLE(Ity_I16, binop(Iop_Add32, 8090 mkexpr(addr), 8091 mkU32(i * 2)))), 8092 IRTemp_INVALID); 8093 break; 8094 case 2: 8095 putDRegI64(rD + r + i * inc, 8096 unop(Iop_Dup32x2, 8097 loadLE(Ity_I32, binop(Iop_Add32, 8098 mkexpr(addr), 8099 mkU32(i * 4)))), 8100 IRTemp_INVALID); 8101 break; 8102 default: 8103 vassert(0); 8104 } 8105 } 8106 } 8107 DIP("vld%u.%u {", N + 1, 8 << size); 8108 for (r = 0; r < regs; r++) { 8109 for (i = 0; i <= N; i++) { 8110 if (i || r) 8111 DIP(", "); 8112 DIP("d%u[]", rD + r + i * inc); 8113 } 8114 } 8115 DIP("}, [r%u]", rN); 8116 if (rM != 13 && rM != 15) { 8117 DIP(", r%u\n", rM); 8118 } else { 8119 DIP("%s\n", (rM != 15) ? "!" : ""); 8120 } 8121 } 8122 /* Writeback. We're uncond here, so no condT-ing. */ 8123 if (rM != 15) { 8124 if (rM == 13) { 8125 IRExpr* e = binop(Iop_Add32, 8126 mkexpr(initialRn), 8127 mkU32((1 << size) * (N + 1))); 8128 if (isT) 8129 putIRegT(rN, e, IRTemp_INVALID); 8130 else 8131 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring); 8132 } else { 8133 IRExpr* e = binop(Iop_Add32, 8134 mkexpr(initialRn), 8135 mkexpr(initialRm)); 8136 if (isT) 8137 putIRegT(rN, e, IRTemp_INVALID); 8138 else 8139 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring); 8140 } 8141 } 8142 return True; 8143 } else { 8144 /* ------------ Case (3) ------------ 8145 VSTn / VLDn (multiple n-element structures) */ 8146 IRTemp tmp; 8147 UInt r, elems; 8148 if (fB == BITS4(0,0,1,0) || fB == BITS4(0,1,1,0) 8149 || fB == BITS4(0,1,1,1) || fB == BITS4(1,0,1,0)) { 8150 N = 0; 8151 } else if (fB == BITS4(0,0,1,1) || fB == BITS4(1,0,0,0) 8152 || fB == BITS4(1,0,0,1)) { 8153 N = 1; 8154 } else if (fB == BITS4(0,1,0,0) || fB == BITS4(0,1,0,1)) { 8155 N = 2; 8156 } else if (fB == BITS4(0,0,0,0) || fB == BITS4(0,0,0,1)) { 8157 N = 3; 8158 } else { 8159 return False; 8160 } 8161 inc = (fB & 1) + 1; 8162 if (N == 1 && fB == BITS4(0,0,1,1)) { 8163 regs = 2; 8164 } else if (N == 0) { 8165 if (fB == BITS4(1,0,1,0)) { 8166 regs = 2; 8167 } else if (fB == BITS4(0,1,1,0)) { 8168 regs = 3; 8169 } else if (fB == BITS4(0,0,1,0)) { 8170 regs = 4; 8171 } 8172 } 8173 8174 size = INSN(7,6); 8175 if (N == 0 && size == 3) 8176 size = 2; 8177 if (size == 3) 8178 return False; 8179 8180 elems = 8 / (1 << size); 8181 8182 // go uncond 8183 if (condT != IRTemp_INVALID) 8184 mk_skip_over_T32_if_cond_is_false(condT); 8185 // now uncond 8186 8187 IRTemp addr = newTemp(Ity_I32); 8188 assign(addr, mkexpr(initialRn)); 8189 8190 for (r = 0; r < regs; r++) { 8191 for (i = 0; i < elems; i++) { 8192 if (bL) 8193 mk_neon_elem_load_to_one_lane(rD + r, inc, i, N, size, addr); 8194 else 8195 mk_neon_elem_store_from_one_lane(rD + r, inc, i, N, size, addr); 8196 tmp = newTemp(Ity_I32); 8197 assign(tmp, binop(Iop_Add32, mkexpr(addr), 8198 mkU32((1 << size) * (N + 1)))); 8199 addr = tmp; 8200 } 8201 } 8202 /* Writeback */ 8203 if (rM != 15) { 8204 if (rM == 13) { 8205 IRExpr* e = binop(Iop_Add32, 8206 mkexpr(initialRn), 8207 mkU32(8 * (N + 1) * regs)); 8208 if (isT) 8209 putIRegT(rN, e, IRTemp_INVALID); 8210 else 8211 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring); 8212 } else { 8213 IRExpr* e = binop(Iop_Add32, 8214 mkexpr(initialRn), 8215 mkexpr(initialRm)); 8216 if (isT) 8217 putIRegT(rN, e, IRTemp_INVALID); 8218 else 8219 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring); 8220 } 8221 } 8222 DIP("v%s%u.%u {", bL ? "ld" : "st", N + 1, 8 << INSN(7,6)); 8223 if ((inc == 1 && regs * (N + 1) > 1) 8224 || (inc == 2 && regs > 1 && N > 0)) { 8225 DIP("d%u-d%u", rD, rD + regs * (N + 1) - 1); 8226 } else { 8227 for (r = 0; r < regs; r++) { 8228 for (i = 0; i <= N; i++) { 8229 if (i || r) 8230 DIP(", "); 8231 DIP("d%u", rD + r + i * inc); 8232 } 8233 } 8234 } 8235 DIP("}, [r%u]", rN); 8236 if (rM != 13 && rM != 15) { 8237 DIP(", r%u\n", rM); 8238 } else { 8239 DIP("%s\n", (rM != 15) ? "!" : ""); 8240 } 8241 return True; 8242 } 8243 # undef INSN 8244 } 8245 8246 8247 /*------------------------------------------------------------*/ 8248 /*--- NEON, top level control ---*/ 8249 /*------------------------------------------------------------*/ 8250 8251 /* Both ARM and Thumb */ 8252 8253 /* Translate a NEON instruction. If successful, returns 8254 True and *dres may or may not be updated. If failure, returns 8255 False and doesn't change *dres nor create any IR. 8256 8257 The Thumb and ARM encodings are similar for the 24 bottom bits, but 8258 the top 8 bits are slightly different. In both cases, the caller 8259 must pass the entire 32 bits. Callers may pass any instruction; 8260 this ignores non-NEON ones. 8261 8262 Caller must supply an IRTemp 'condT' holding the gating condition, 8263 or IRTemp_INVALID indicating the insn is always executed. In ARM 8264 code, this must always be IRTemp_INVALID because NEON insns are 8265 unconditional for ARM. 8266 8267 Finally, the caller must indicate whether this occurs in ARM or in 8268 Thumb code. 8269 */ 8270 static Bool decode_NEON_instruction ( 8271 /*MOD*/DisResult* dres, 8272 UInt insn32, 8273 IRTemp condT, 8274 Bool isT 8275 ) 8276 { 8277 # define INSN(_bMax,_bMin) SLICE_UInt(insn32, (_bMax), (_bMin)) 8278 8279 /* There are two kinds of instruction to deal with: load/store and 8280 data processing. In each case, in ARM mode we merely identify 8281 the kind, and pass it on to the relevant sub-handler. In Thumb 8282 mode we identify the kind, swizzle the bits around to make it 8283 have the same encoding as in ARM, and hand it on to the 8284 sub-handler. 8285 */ 8286 8287 /* In ARM mode, NEON instructions can't be conditional. */ 8288 if (!isT) 8289 vassert(condT == IRTemp_INVALID); 8290 8291 /* Data processing: 8292 Thumb: 111U 1111 AAAA Axxx xxxx BBBB CCCC xxxx 8293 ARM: 1111 001U AAAA Axxx xxxx BBBB CCCC xxxx 8294 */ 8295 if (!isT && INSN(31,25) == BITS7(1,1,1,1,0,0,1)) { 8296 // ARM, DP 8297 return dis_neon_data_processing(INSN(31,0), condT); 8298 } 8299 if (isT && INSN(31,29) == BITS3(1,1,1) 8300 && INSN(27,24) == BITS4(1,1,1,1)) { 8301 // Thumb, DP 8302 UInt reformatted = INSN(23,0); 8303 reformatted |= (INSN(28,28) << 24); // U bit 8304 reformatted |= (BITS7(1,1,1,1,0,0,1) << 25); 8305 return dis_neon_data_processing(reformatted, condT); 8306 } 8307 8308 /* Load/store: 8309 Thumb: 1111 1001 AxL0 xxxx xxxx BBBB xxxx xxxx 8310 ARM: 1111 0100 AxL0 xxxx xxxx BBBB xxxx xxxx 8311 */ 8312 if (!isT && INSN(31,24) == BITS8(1,1,1,1,0,1,0,0)) { 8313 // ARM, memory 8314 return dis_neon_load_or_store(INSN(31,0), isT, condT); 8315 } 8316 if (isT && INSN(31,24) == BITS8(1,1,1,1,1,0,0,1)) { 8317 UInt reformatted = INSN(23,0); 8318 reformatted |= (BITS8(1,1,1,1,0,1,0,0) << 24); 8319 return dis_neon_load_or_store(reformatted, isT, condT); 8320 } 8321 8322 /* Doesn't match. */ 8323 return False; 8324 8325 # undef INSN 8326 } 8327 8328 8329 /*------------------------------------------------------------*/ 8330 /*--- V6 MEDIA instructions ---*/ 8331 /*------------------------------------------------------------*/ 8332 8333 /* Both ARM and Thumb */ 8334 8335 /* Translate a V6 media instruction. If successful, returns 8336 True and *dres may or may not be updated. If failure, returns 8337 False and doesn't change *dres nor create any IR. 8338 8339 The Thumb and ARM encodings are completely different. In Thumb 8340 mode, the caller must pass the entire 32 bits. In ARM mode it must 8341 pass the lower 28 bits. Apart from that, callers may pass any 8342 instruction; this function ignores anything it doesn't recognise. 8343 8344 Caller must supply an IRTemp 'condT' holding the gating condition, 8345 or IRTemp_INVALID indicating the insn is always executed. 8346 8347 Caller must also supply an ARMCondcode 'cond'. This is only used 8348 for debug printing, no other purpose. For ARM, this is simply the 8349 top 4 bits of the original instruction. For Thumb, the condition 8350 is not (really) known until run time, and so ARMCondAL should be 8351 passed, only so that printing of these instructions does not show 8352 any condition. 8353 8354 Finally, the caller must indicate whether this occurs in ARM or in 8355 Thumb code. 8356 */ 8357 static Bool decode_V6MEDIA_instruction ( 8358 /*MOD*/DisResult* dres, 8359 UInt insnv6m, 8360 IRTemp condT, 8361 ARMCondcode conq, 8362 Bool isT 8363 ) 8364 { 8365 # define INSNA(_bMax,_bMin) SLICE_UInt(insnv6m, (_bMax), (_bMin)) 8366 # define INSNT0(_bMax,_bMin) SLICE_UInt( ((insnv6m >> 16) & 0xFFFF), \ 8367 (_bMax), (_bMin) ) 8368 # define INSNT1(_bMax,_bMin) SLICE_UInt( ((insnv6m >> 0) & 0xFFFF), \ 8369 (_bMax), (_bMin) ) 8370 HChar dis_buf[128]; 8371 dis_buf[0] = 0; 8372 8373 if (isT) { 8374 vassert(conq == ARMCondAL); 8375 } else { 8376 vassert(INSNA(31,28) == BITS4(0,0,0,0)); // caller's obligation 8377 vassert(conq >= ARMCondEQ && conq <= ARMCondAL); 8378 } 8379 8380 /* ----------- smulbb, smulbt, smultb, smultt ----------- */ 8381 { 8382 UInt regD = 99, regM = 99, regN = 99, bitM = 0, bitN = 0; 8383 Bool gate = False; 8384 8385 if (isT) { 8386 if (INSNT0(15,4) == 0xFB1 && INSNT1(15,12) == BITS4(1,1,1,1) 8387 && INSNT1(7,6) == BITS2(0,0)) { 8388 regD = INSNT1(11,8); 8389 regM = INSNT1(3,0); 8390 regN = INSNT0(3,0); 8391 bitM = INSNT1(4,4); 8392 bitN = INSNT1(5,5); 8393 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8394 gate = True; 8395 } 8396 } else { 8397 if (BITS8(0,0,0,1,0,1,1,0) == INSNA(27,20) && 8398 BITS4(0,0,0,0) == INSNA(15,12) && 8399 BITS4(1,0,0,0) == (INSNA(7,4) & BITS4(1,0,0,1)) ) { 8400 regD = INSNA(19,16); 8401 regM = INSNA(11,8); 8402 regN = INSNA(3,0); 8403 bitM = INSNA(6,6); 8404 bitN = INSNA(5,5); 8405 if (regD != 15 && regN != 15 && regM != 15) 8406 gate = True; 8407 } 8408 } 8409 8410 if (gate) { 8411 IRTemp srcN = newTemp(Ity_I32); 8412 IRTemp srcM = newTemp(Ity_I32); 8413 IRTemp res = newTemp(Ity_I32); 8414 8415 assign( srcN, binop(Iop_Sar32, 8416 binop(Iop_Shl32, 8417 isT ? getIRegT(regN) : getIRegA(regN), 8418 mkU8(bitN ? 0 : 16)), mkU8(16)) ); 8419 assign( srcM, binop(Iop_Sar32, 8420 binop(Iop_Shl32, 8421 isT ? getIRegT(regM) : getIRegA(regM), 8422 mkU8(bitM ? 0 : 16)), mkU8(16)) ); 8423 assign( res, binop(Iop_Mul32, mkexpr(srcN), mkexpr(srcM)) ); 8424 8425 if (isT) 8426 putIRegT( regD, mkexpr(res), condT ); 8427 else 8428 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8429 8430 DIP( "smul%c%c%s r%u, r%u, r%u\n", bitN ? 't' : 'b', bitM ? 't' : 'b', 8431 nCC(conq), regD, regN, regM ); 8432 return True; 8433 } 8434 /* fall through */ 8435 } 8436 8437 /* ------------ smulwb<y><c> <Rd>,<Rn>,<Rm> ------------- */ 8438 /* ------------ smulwt<y><c> <Rd>,<Rn>,<Rm> ------------- */ 8439 { 8440 UInt regD = 99, regN = 99, regM = 99, bitM = 0; 8441 Bool gate = False; 8442 8443 if (isT) { 8444 if (INSNT0(15,4) == 0xFB3 && INSNT1(15,12) == BITS4(1,1,1,1) 8445 && INSNT1(7,5) == BITS3(0,0,0)) { 8446 regN = INSNT0(3,0); 8447 regD = INSNT1(11,8); 8448 regM = INSNT1(3,0); 8449 bitM = INSNT1(4,4); 8450 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8451 gate = True; 8452 } 8453 } else { 8454 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) && 8455 INSNA(15,12) == BITS4(0,0,0,0) && 8456 (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,1,0)) { 8457 regD = INSNA(19,16); 8458 regN = INSNA(3,0); 8459 regM = INSNA(11,8); 8460 bitM = INSNA(6,6); 8461 if (regD != 15 && regN != 15 && regM != 15) 8462 gate = True; 8463 } 8464 } 8465 8466 if (gate) { 8467 IRTemp irt_prod = newTemp(Ity_I64); 8468 8469 assign( irt_prod, 8470 binop(Iop_MullS32, 8471 isT ? getIRegT(regN) : getIRegA(regN), 8472 binop(Iop_Sar32, 8473 binop(Iop_Shl32, 8474 isT ? getIRegT(regM) : getIRegA(regM), 8475 mkU8(bitM ? 0 : 16)), 8476 mkU8(16))) ); 8477 8478 IRExpr* ire_result = binop(Iop_Or32, 8479 binop( Iop_Shl32, 8480 unop(Iop_64HIto32, mkexpr(irt_prod)), 8481 mkU8(16) ), 8482 binop( Iop_Shr32, 8483 unop(Iop_64to32, mkexpr(irt_prod)), 8484 mkU8(16) ) ); 8485 8486 if (isT) 8487 putIRegT( regD, ire_result, condT ); 8488 else 8489 putIRegA( regD, ire_result, condT, Ijk_Boring ); 8490 8491 DIP("smulw%c%s r%u, r%u, r%u\n", 8492 bitM ? 't' : 'b', nCC(conq),regD,regN,regM); 8493 return True; 8494 } 8495 /* fall through */ 8496 } 8497 8498 /* ------------ pkhbt<c> Rd, Rn, Rm {,LSL #imm} ------------- */ 8499 /* ------------ pkhtb<c> Rd, Rn, Rm {,ASR #imm} ------------- */ 8500 { 8501 UInt regD = 99, regN = 99, regM = 99, imm5 = 99, shift_type = 99; 8502 Bool tbform = False; 8503 Bool gate = False; 8504 8505 if (isT) { 8506 if (INSNT0(15,4) == 0xEAC 8507 && INSNT1(15,15) == 0 && INSNT1(4,4) == 0) { 8508 regN = INSNT0(3,0); 8509 regD = INSNT1(11,8); 8510 regM = INSNT1(3,0); 8511 imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6); 8512 shift_type = (INSNT1(5,5) << 1) | 0; 8513 tbform = (INSNT1(5,5) == 0) ? False : True; 8514 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8515 gate = True; 8516 } 8517 } else { 8518 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) && 8519 INSNA(5,4) == BITS2(0,1) && 8520 (INSNA(6,6) == 0 || INSNA(6,6) == 1) ) { 8521 regD = INSNA(15,12); 8522 regN = INSNA(19,16); 8523 regM = INSNA(3,0); 8524 imm5 = INSNA(11,7); 8525 shift_type = (INSNA(6,6) << 1) | 0; 8526 tbform = (INSNA(6,6) == 0) ? False : True; 8527 if (regD != 15 && regN != 15 && regM != 15) 8528 gate = True; 8529 } 8530 } 8531 8532 if (gate) { 8533 IRTemp irt_regM = newTemp(Ity_I32); 8534 IRTemp irt_regM_shift = newTemp(Ity_I32); 8535 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) ); 8536 compute_result_and_C_after_shift_by_imm5( 8537 dis_buf, &irt_regM_shift, NULL, irt_regM, shift_type, imm5, regM ); 8538 8539 UInt mask = (tbform == True) ? 0x0000FFFF : 0xFFFF0000; 8540 IRExpr* ire_result 8541 = binop( Iop_Or32, 8542 binop(Iop_And32, mkexpr(irt_regM_shift), mkU32(mask)), 8543 binop(Iop_And32, isT ? getIRegT(regN) : getIRegA(regN), 8544 unop(Iop_Not32, mkU32(mask))) ); 8545 8546 if (isT) 8547 putIRegT( regD, ire_result, condT ); 8548 else 8549 putIRegA( regD, ire_result, condT, Ijk_Boring ); 8550 8551 DIP( "pkh%s%s r%u, r%u, r%u %s\n", tbform ? "tb" : "bt", 8552 nCC(conq), regD, regN, regM, dis_buf ); 8553 8554 return True; 8555 } 8556 /* fall through */ 8557 } 8558 8559 /* ---------- usat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */ 8560 { 8561 UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99; 8562 Bool gate = False; 8563 8564 if (isT) { 8565 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,1,0) 8566 && INSNT0(4,4) == 0 8567 && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) { 8568 regD = INSNT1(11,8); 8569 regN = INSNT0(3,0); 8570 shift_type = (INSNT0(5,5) << 1) | 0; 8571 imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6); 8572 sat_imm = INSNT1(4,0); 8573 if (!isBadRegT(regD) && !isBadRegT(regN)) 8574 gate = True; 8575 if (shift_type == BITS2(1,0) && imm5 == 0) 8576 gate = False; 8577 } 8578 } else { 8579 if (INSNA(27,21) == BITS7(0,1,1,0,1,1,1) && 8580 INSNA(5,4) == BITS2(0,1)) { 8581 regD = INSNA(15,12); 8582 regN = INSNA(3,0); 8583 shift_type = (INSNA(6,6) << 1) | 0; 8584 imm5 = INSNA(11,7); 8585 sat_imm = INSNA(20,16); 8586 if (regD != 15 && regN != 15) 8587 gate = True; 8588 } 8589 } 8590 8591 if (gate) { 8592 IRTemp irt_regN = newTemp(Ity_I32); 8593 IRTemp irt_regN_shift = newTemp(Ity_I32); 8594 IRTemp irt_sat_Q = newTemp(Ity_I32); 8595 IRTemp irt_result = newTemp(Ity_I32); 8596 8597 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 8598 compute_result_and_C_after_shift_by_imm5( 8599 dis_buf, &irt_regN_shift, NULL, 8600 irt_regN, shift_type, imm5, regN ); 8601 8602 armUnsignedSatQ( &irt_result, &irt_sat_Q, irt_regN_shift, sat_imm ); 8603 or_into_QFLAG32( mkexpr(irt_sat_Q), condT ); 8604 8605 if (isT) 8606 putIRegT( regD, mkexpr(irt_result), condT ); 8607 else 8608 putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring ); 8609 8610 DIP("usat%s r%u, #0x%04x, %s\n", 8611 nCC(conq), regD, imm5, dis_buf); 8612 return True; 8613 } 8614 /* fall through */ 8615 } 8616 8617 /* ----------- ssat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */ 8618 { 8619 UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99; 8620 Bool gate = False; 8621 8622 if (isT) { 8623 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0) 8624 && INSNT0(4,4) == 0 8625 && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) { 8626 regD = INSNT1(11,8); 8627 regN = INSNT0(3,0); 8628 shift_type = (INSNT0(5,5) << 1) | 0; 8629 imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6); 8630 sat_imm = INSNT1(4,0) + 1; 8631 if (!isBadRegT(regD) && !isBadRegT(regN)) 8632 gate = True; 8633 if (shift_type == BITS2(1,0) && imm5 == 0) 8634 gate = False; 8635 } 8636 } else { 8637 if (INSNA(27,21) == BITS7(0,1,1,0,1,0,1) && 8638 INSNA(5,4) == BITS2(0,1)) { 8639 regD = INSNA(15,12); 8640 regN = INSNA(3,0); 8641 shift_type = (INSNA(6,6) << 1) | 0; 8642 imm5 = INSNA(11,7); 8643 sat_imm = INSNA(20,16) + 1; 8644 if (regD != 15 && regN != 15) 8645 gate = True; 8646 } 8647 } 8648 8649 if (gate) { 8650 IRTemp irt_regN = newTemp(Ity_I32); 8651 IRTemp irt_regN_shift = newTemp(Ity_I32); 8652 IRTemp irt_sat_Q = newTemp(Ity_I32); 8653 IRTemp irt_result = newTemp(Ity_I32); 8654 8655 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 8656 compute_result_and_C_after_shift_by_imm5( 8657 dis_buf, &irt_regN_shift, NULL, 8658 irt_regN, shift_type, imm5, regN ); 8659 8660 armSignedSatQ( irt_regN_shift, sat_imm, &irt_result, &irt_sat_Q ); 8661 or_into_QFLAG32( mkexpr(irt_sat_Q), condT ); 8662 8663 if (isT) 8664 putIRegT( regD, mkexpr(irt_result), condT ); 8665 else 8666 putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring ); 8667 8668 DIP( "ssat%s r%u, #0x%04x, %s\n", 8669 nCC(conq), regD, imm5, dis_buf); 8670 return True; 8671 } 8672 /* fall through */ 8673 } 8674 8675 /* -------------- usat16<c> <Rd>,#<imm4>,<Rn> --------------- */ 8676 { 8677 UInt regD = 99, regN = 99, sat_imm = 99; 8678 Bool gate = False; 8679 8680 if (isT) { 8681 if (INSNT0(15,4) == 0xF3A && (INSNT1(15,0) & 0xF0F0) == 0x0000) { 8682 regN = INSNT0(3,0); 8683 regD = INSNT1(11,8); 8684 sat_imm = INSNT1(3,0); 8685 if (!isBadRegT(regD) && !isBadRegT(regN)) 8686 gate = True; 8687 } 8688 } else { 8689 if (INSNA(27,20) == BITS8(0,1,1,0,1,1,1,0) && 8690 INSNA(11,8) == BITS4(1,1,1,1) && 8691 INSNA(7,4) == BITS4(0,0,1,1)) { 8692 regD = INSNA(15,12); 8693 regN = INSNA(3,0); 8694 sat_imm = INSNA(19,16); 8695 if (regD != 15 && regN != 15) 8696 gate = True; 8697 } 8698 } 8699 8700 if (gate) { 8701 IRTemp irt_regN = newTemp(Ity_I32); 8702 IRTemp irt_regN_lo = newTemp(Ity_I32); 8703 IRTemp irt_regN_hi = newTemp(Ity_I32); 8704 IRTemp irt_Q_lo = newTemp(Ity_I32); 8705 IRTemp irt_Q_hi = newTemp(Ity_I32); 8706 IRTemp irt_res_lo = newTemp(Ity_I32); 8707 IRTemp irt_res_hi = newTemp(Ity_I32); 8708 8709 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 8710 assign( irt_regN_lo, binop( Iop_Sar32, 8711 binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 8712 mkU8(16)) ); 8713 assign( irt_regN_hi, binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)) ); 8714 8715 armUnsignedSatQ( &irt_res_lo, &irt_Q_lo, irt_regN_lo, sat_imm ); 8716 or_into_QFLAG32( mkexpr(irt_Q_lo), condT ); 8717 8718 armUnsignedSatQ( &irt_res_hi, &irt_Q_hi, irt_regN_hi, sat_imm ); 8719 or_into_QFLAG32( mkexpr(irt_Q_hi), condT ); 8720 8721 IRExpr* ire_result = binop( Iop_Or32, 8722 binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)), 8723 mkexpr(irt_res_lo) ); 8724 8725 if (isT) 8726 putIRegT( regD, ire_result, condT ); 8727 else 8728 putIRegA( regD, ire_result, condT, Ijk_Boring ); 8729 8730 DIP( "usat16%s r%u, #0x%04x, r%u\n", nCC(conq), regD, sat_imm, regN ); 8731 return True; 8732 } 8733 /* fall through */ 8734 } 8735 8736 /* -------------- uadd16<c> <Rd>,<Rn>,<Rm> -------------- */ 8737 { 8738 UInt regD = 99, regN = 99, regM = 99; 8739 Bool gate = False; 8740 8741 if (isT) { 8742 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF040) { 8743 regN = INSNT0(3,0); 8744 regD = INSNT1(11,8); 8745 regM = INSNT1(3,0); 8746 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8747 gate = True; 8748 } 8749 } else { 8750 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) && 8751 INSNA(11,8) == BITS4(1,1,1,1) && 8752 INSNA(7,4) == BITS4(0,0,0,1)) { 8753 regD = INSNA(15,12); 8754 regN = INSNA(19,16); 8755 regM = INSNA(3,0); 8756 if (regD != 15 && regN != 15 && regM != 15) 8757 gate = True; 8758 } 8759 } 8760 8761 if (gate) { 8762 IRTemp rNt = newTemp(Ity_I32); 8763 IRTemp rMt = newTemp(Ity_I32); 8764 IRTemp res = newTemp(Ity_I32); 8765 IRTemp reso = newTemp(Ity_I32); 8766 8767 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 8768 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 8769 8770 assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt))); 8771 if (isT) 8772 putIRegT( regD, mkexpr(res), condT ); 8773 else 8774 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8775 8776 assign(reso, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt))); 8777 set_GE_32_10_from_bits_31_15(reso, condT); 8778 8779 DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 8780 return True; 8781 } 8782 /* fall through */ 8783 } 8784 8785 /* -------------- sadd16<c> <Rd>,<Rn>,<Rm> -------------- */ 8786 { 8787 UInt regD = 99, regN = 99, regM = 99; 8788 Bool gate = False; 8789 8790 if (isT) { 8791 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF000) { 8792 regN = INSNT0(3,0); 8793 regD = INSNT1(11,8); 8794 regM = INSNT1(3,0); 8795 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8796 gate = True; 8797 } 8798 } else { 8799 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 8800 INSNA(11,8) == BITS4(1,1,1,1) && 8801 INSNA(7,4) == BITS4(0,0,0,1)) { 8802 regD = INSNA(15,12); 8803 regN = INSNA(19,16); 8804 regM = INSNA(3,0); 8805 if (regD != 15 && regN != 15 && regM != 15) 8806 gate = True; 8807 } 8808 } 8809 8810 if (gate) { 8811 IRTemp rNt = newTemp(Ity_I32); 8812 IRTemp rMt = newTemp(Ity_I32); 8813 IRTemp res = newTemp(Ity_I32); 8814 IRTemp reso = newTemp(Ity_I32); 8815 8816 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 8817 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 8818 8819 assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt))); 8820 if (isT) 8821 putIRegT( regD, mkexpr(res), condT ); 8822 else 8823 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8824 8825 assign(reso, unop(Iop_Not32, 8826 binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt)))); 8827 set_GE_32_10_from_bits_31_15(reso, condT); 8828 8829 DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 8830 return True; 8831 } 8832 /* fall through */ 8833 } 8834 8835 /* ---------------- usub16<c> <Rd>,<Rn>,<Rm> ---------------- */ 8836 { 8837 UInt regD = 99, regN = 99, regM = 99; 8838 Bool gate = False; 8839 8840 if (isT) { 8841 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF040) { 8842 regN = INSNT0(3,0); 8843 regD = INSNT1(11,8); 8844 regM = INSNT1(3,0); 8845 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8846 gate = True; 8847 } 8848 } else { 8849 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) && 8850 INSNA(11,8) == BITS4(1,1,1,1) && 8851 INSNA(7,4) == BITS4(0,1,1,1)) { 8852 regD = INSNA(15,12); 8853 regN = INSNA(19,16); 8854 regM = INSNA(3,0); 8855 if (regD != 15 && regN != 15 && regM != 15) 8856 gate = True; 8857 } 8858 } 8859 8860 if (gate) { 8861 IRTemp rNt = newTemp(Ity_I32); 8862 IRTemp rMt = newTemp(Ity_I32); 8863 IRTemp res = newTemp(Ity_I32); 8864 IRTemp reso = newTemp(Ity_I32); 8865 8866 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 8867 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 8868 8869 assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt))); 8870 if (isT) 8871 putIRegT( regD, mkexpr(res), condT ); 8872 else 8873 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8874 8875 assign(reso, unop(Iop_Not32, 8876 binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt)))); 8877 set_GE_32_10_from_bits_31_15(reso, condT); 8878 8879 DIP("usub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 8880 return True; 8881 } 8882 /* fall through */ 8883 } 8884 8885 /* -------------- ssub16<c> <Rd>,<Rn>,<Rm> -------------- */ 8886 { 8887 UInt regD = 99, regN = 99, regM = 99; 8888 Bool gate = False; 8889 8890 if (isT) { 8891 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF000) { 8892 regN = INSNT0(3,0); 8893 regD = INSNT1(11,8); 8894 regM = INSNT1(3,0); 8895 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8896 gate = True; 8897 } 8898 } else { 8899 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 8900 INSNA(11,8) == BITS4(1,1,1,1) && 8901 INSNA(7,4) == BITS4(0,1,1,1)) { 8902 regD = INSNA(15,12); 8903 regN = INSNA(19,16); 8904 regM = INSNA(3,0); 8905 if (regD != 15 && regN != 15 && regM != 15) 8906 gate = True; 8907 } 8908 } 8909 8910 if (gate) { 8911 IRTemp rNt = newTemp(Ity_I32); 8912 IRTemp rMt = newTemp(Ity_I32); 8913 IRTemp res = newTemp(Ity_I32); 8914 IRTemp reso = newTemp(Ity_I32); 8915 8916 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 8917 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 8918 8919 assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt))); 8920 if (isT) 8921 putIRegT( regD, mkexpr(res), condT ); 8922 else 8923 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8924 8925 assign(reso, unop(Iop_Not32, 8926 binop(Iop_HSub16Sx2, mkexpr(rNt), mkexpr(rMt)))); 8927 set_GE_32_10_from_bits_31_15(reso, condT); 8928 8929 DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 8930 return True; 8931 } 8932 /* fall through */ 8933 } 8934 8935 /* ----------------- uadd8<c> <Rd>,<Rn>,<Rm> ---------------- */ 8936 { 8937 UInt regD = 99, regN = 99, regM = 99; 8938 Bool gate = False; 8939 8940 if (isT) { 8941 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF040) { 8942 regN = INSNT0(3,0); 8943 regD = INSNT1(11,8); 8944 regM = INSNT1(3,0); 8945 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8946 gate = True; 8947 } 8948 } else { 8949 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) && 8950 INSNA(11,8) == BITS4(1,1,1,1) && 8951 (INSNA(7,4) == BITS4(1,0,0,1))) { 8952 regD = INSNA(15,12); 8953 regN = INSNA(19,16); 8954 regM = INSNA(3,0); 8955 if (regD != 15 && regN != 15 && regM != 15) 8956 gate = True; 8957 } 8958 } 8959 8960 if (gate) { 8961 IRTemp rNt = newTemp(Ity_I32); 8962 IRTemp rMt = newTemp(Ity_I32); 8963 IRTemp res = newTemp(Ity_I32); 8964 IRTemp reso = newTemp(Ity_I32); 8965 8966 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 8967 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 8968 8969 assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt))); 8970 if (isT) 8971 putIRegT( regD, mkexpr(res), condT ); 8972 else 8973 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8974 8975 assign(reso, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt))); 8976 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT); 8977 8978 DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 8979 return True; 8980 } 8981 /* fall through */ 8982 } 8983 8984 /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */ 8985 { 8986 UInt regD = 99, regN = 99, regM = 99; 8987 Bool gate = False; 8988 8989 if (isT) { 8990 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) { 8991 regN = INSNT0(3,0); 8992 regD = INSNT1(11,8); 8993 regM = INSNT1(3,0); 8994 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8995 gate = True; 8996 } 8997 } else { 8998 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 8999 INSNA(11,8) == BITS4(1,1,1,1) && 9000 (INSNA(7,4) == BITS4(1,0,0,1))) { 9001 regD = INSNA(15,12); 9002 regN = INSNA(19,16); 9003 regM = INSNA(3,0); 9004 if (regD != 15 && regN != 15 && regM != 15) 9005 gate = True; 9006 } 9007 } 9008 9009 if (gate) { 9010 IRTemp rNt = newTemp(Ity_I32); 9011 IRTemp rMt = newTemp(Ity_I32); 9012 IRTemp res = newTemp(Ity_I32); 9013 IRTemp reso = newTemp(Ity_I32); 9014 9015 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9016 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9017 9018 assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt))); 9019 if (isT) 9020 putIRegT( regD, mkexpr(res), condT ); 9021 else 9022 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 9023 9024 assign(reso, unop(Iop_Not32, 9025 binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt)))); 9026 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT); 9027 9028 DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9029 return True; 9030 } 9031 /* fall through */ 9032 } 9033 9034 /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */ 9035 { 9036 UInt regD = 99, regN = 99, regM = 99; 9037 Bool gate = False; 9038 9039 if (isT) { 9040 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) { 9041 regN = INSNT0(3,0); 9042 regD = INSNT1(11,8); 9043 regM = INSNT1(3,0); 9044 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9045 gate = True; 9046 } 9047 } else { 9048 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) && 9049 INSNA(11,8) == BITS4(1,1,1,1) && 9050 (INSNA(7,4) == BITS4(1,1,1,1))) { 9051 regD = INSNA(15,12); 9052 regN = INSNA(19,16); 9053 regM = INSNA(3,0); 9054 if (regD != 15 && regN != 15 && regM != 15) 9055 gate = True; 9056 } 9057 } 9058 9059 if (gate) { 9060 IRTemp rNt = newTemp(Ity_I32); 9061 IRTemp rMt = newTemp(Ity_I32); 9062 IRTemp res = newTemp(Ity_I32); 9063 IRTemp reso = newTemp(Ity_I32); 9064 9065 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9066 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9067 9068 assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt))); 9069 if (isT) 9070 putIRegT( regD, mkexpr(res), condT ); 9071 else 9072 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 9073 9074 assign(reso, unop(Iop_Not32, 9075 binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt)))); 9076 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT); 9077 9078 DIP("usub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9079 return True; 9080 } 9081 /* fall through */ 9082 } 9083 9084 /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */ 9085 { 9086 UInt regD = 99, regN = 99, regM = 99; 9087 Bool gate = False; 9088 9089 if (isT) { 9090 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) { 9091 regN = INSNT0(3,0); 9092 regD = INSNT1(11,8); 9093 regM = INSNT1(3,0); 9094 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9095 gate = True; 9096 } 9097 } else { 9098 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 9099 INSNA(11,8) == BITS4(1,1,1,1) && 9100 INSNA(7,4) == BITS4(1,1,1,1)) { 9101 regD = INSNA(15,12); 9102 regN = INSNA(19,16); 9103 regM = INSNA(3,0); 9104 if (regD != 15 && regN != 15 && regM != 15) 9105 gate = True; 9106 } 9107 } 9108 9109 if (gate) { 9110 IRTemp rNt = newTemp(Ity_I32); 9111 IRTemp rMt = newTemp(Ity_I32); 9112 IRTemp res = newTemp(Ity_I32); 9113 IRTemp reso = newTemp(Ity_I32); 9114 9115 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9116 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9117 9118 assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt))); 9119 if (isT) 9120 putIRegT( regD, mkexpr(res), condT ); 9121 else 9122 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 9123 9124 assign(reso, unop(Iop_Not32, 9125 binop(Iop_HSub8Sx4, mkexpr(rNt), mkexpr(rMt)))); 9126 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT); 9127 9128 DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9129 return True; 9130 } 9131 /* fall through */ 9132 } 9133 9134 /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */ 9135 { 9136 UInt regD = 99, regN = 99, regM = 99; 9137 Bool gate = False; 9138 9139 if (isT) { 9140 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9141 regN = INSNT0(3,0); 9142 regD = INSNT1(11,8); 9143 regM = INSNT1(3,0); 9144 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9145 gate = True; 9146 } 9147 } else { 9148 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9149 INSNA(11,8) == BITS4(1,1,1,1) && 9150 INSNA(7,4) == BITS4(1,0,0,1)) { 9151 regD = INSNA(15,12); 9152 regN = INSNA(19,16); 9153 regM = INSNA(3,0); 9154 if (regD != 15 && regN != 15 && regM != 15) 9155 gate = True; 9156 } 9157 } 9158 9159 if (gate) { 9160 IRTemp rNt = newTemp(Ity_I32); 9161 IRTemp rMt = newTemp(Ity_I32); 9162 IRTemp res_q = newTemp(Ity_I32); 9163 9164 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9165 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9166 9167 assign(res_q, binop(Iop_QAdd8Sx4, mkexpr(rNt), mkexpr(rMt))); 9168 if (isT) 9169 putIRegT( regD, mkexpr(res_q), condT ); 9170 else 9171 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9172 9173 DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9174 return True; 9175 } 9176 /* fall through */ 9177 } 9178 9179 /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */ 9180 { 9181 UInt regD = 99, regN = 99, regM = 99; 9182 Bool gate = False; 9183 9184 if (isT) { 9185 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9186 regN = INSNT0(3,0); 9187 regD = INSNT1(11,8); 9188 regM = INSNT1(3,0); 9189 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9190 gate = True; 9191 } 9192 } else { 9193 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9194 INSNA(11,8) == BITS4(1,1,1,1) && 9195 INSNA(7,4) == BITS4(1,1,1,1)) { 9196 regD = INSNA(15,12); 9197 regN = INSNA(19,16); 9198 regM = INSNA(3,0); 9199 if (regD != 15 && regN != 15 && regM != 15) 9200 gate = True; 9201 } 9202 } 9203 9204 if (gate) { 9205 IRTemp rNt = newTemp(Ity_I32); 9206 IRTemp rMt = newTemp(Ity_I32); 9207 IRTemp res_q = newTemp(Ity_I32); 9208 9209 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9210 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9211 9212 assign(res_q, binop(Iop_QSub8Sx4, mkexpr(rNt), mkexpr(rMt))); 9213 if (isT) 9214 putIRegT( regD, mkexpr(res_q), condT ); 9215 else 9216 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9217 9218 DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9219 return True; 9220 } 9221 /* fall through */ 9222 } 9223 9224 /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */ 9225 { 9226 UInt regD = 99, regN = 99, regM = 99; 9227 Bool gate = False; 9228 9229 if (isT) { 9230 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) { 9231 regN = INSNT0(3,0); 9232 regD = INSNT1(11,8); 9233 regM = INSNT1(3,0); 9234 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9235 gate = True; 9236 } 9237 } else { 9238 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) && 9239 INSNA(11,8) == BITS4(1,1,1,1) && 9240 (INSNA(7,4) == BITS4(1,0,0,1))) { 9241 regD = INSNA(15,12); 9242 regN = INSNA(19,16); 9243 regM = INSNA(3,0); 9244 if (regD != 15 && regN != 15 && regM != 15) 9245 gate = True; 9246 } 9247 } 9248 9249 if (gate) { 9250 IRTemp rNt = newTemp(Ity_I32); 9251 IRTemp rMt = newTemp(Ity_I32); 9252 IRTemp res_q = newTemp(Ity_I32); 9253 9254 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9255 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9256 9257 assign(res_q, binop(Iop_QAdd8Ux4, mkexpr(rNt), mkexpr(rMt))); 9258 if (isT) 9259 putIRegT( regD, mkexpr(res_q), condT ); 9260 else 9261 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9262 9263 DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9264 return True; 9265 } 9266 /* fall through */ 9267 } 9268 9269 /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */ 9270 { 9271 UInt regD = 99, regN = 99, regM = 99; 9272 Bool gate = False; 9273 9274 if (isT) { 9275 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) { 9276 regN = INSNT0(3,0); 9277 regD = INSNT1(11,8); 9278 regM = INSNT1(3,0); 9279 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9280 gate = True; 9281 } 9282 } else { 9283 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) && 9284 INSNA(11,8) == BITS4(1,1,1,1) && 9285 (INSNA(7,4) == BITS4(1,1,1,1))) { 9286 regD = INSNA(15,12); 9287 regN = INSNA(19,16); 9288 regM = INSNA(3,0); 9289 if (regD != 15 && regN != 15 && regM != 15) 9290 gate = True; 9291 } 9292 } 9293 9294 if (gate) { 9295 IRTemp rNt = newTemp(Ity_I32); 9296 IRTemp rMt = newTemp(Ity_I32); 9297 IRTemp res_q = newTemp(Ity_I32); 9298 9299 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9300 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9301 9302 assign(res_q, binop(Iop_QSub8Ux4, mkexpr(rNt), mkexpr(rMt))); 9303 if (isT) 9304 putIRegT( regD, mkexpr(res_q), condT ); 9305 else 9306 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9307 9308 DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9309 return True; 9310 } 9311 /* fall through */ 9312 } 9313 9314 /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */ 9315 { 9316 UInt regD = 99, regN = 99, regM = 99; 9317 Bool gate = False; 9318 9319 if (isT) { 9320 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) { 9321 regN = INSNT0(3,0); 9322 regD = INSNT1(11,8); 9323 regM = INSNT1(3,0); 9324 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9325 gate = True; 9326 } 9327 } else { 9328 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) && 9329 INSNA(11,8) == BITS4(1,1,1,1) && 9330 INSNA(7,4) == BITS4(1,0,0,1)) { 9331 regD = INSNA(15,12); 9332 regN = INSNA(19,16); 9333 regM = INSNA(3,0); 9334 if (regD != 15 && regN != 15 && regM != 15) 9335 gate = True; 9336 } 9337 } 9338 9339 if (gate) { 9340 IRTemp rNt = newTemp(Ity_I32); 9341 IRTemp rMt = newTemp(Ity_I32); 9342 IRTemp res_q = newTemp(Ity_I32); 9343 9344 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9345 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9346 9347 assign(res_q, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt))); 9348 if (isT) 9349 putIRegT( regD, mkexpr(res_q), condT ); 9350 else 9351 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9352 9353 DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9354 return True; 9355 } 9356 /* fall through */ 9357 } 9358 9359 /* ----------------- uhadd16<c> <Rd>,<Rn>,<Rm> ------------------- */ 9360 { 9361 UInt regD = 99, regN = 99, regM = 99; 9362 Bool gate = False; 9363 9364 if (isT) { 9365 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF060) { 9366 regN = INSNT0(3,0); 9367 regD = INSNT1(11,8); 9368 regM = INSNT1(3,0); 9369 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9370 gate = True; 9371 } 9372 } else { 9373 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) && 9374 INSNA(11,8) == BITS4(1,1,1,1) && 9375 INSNA(7,4) == BITS4(0,0,0,1)) { 9376 regD = INSNA(15,12); 9377 regN = INSNA(19,16); 9378 regM = INSNA(3,0); 9379 if (regD != 15 && regN != 15 && regM != 15) 9380 gate = True; 9381 } 9382 } 9383 9384 if (gate) { 9385 IRTemp rNt = newTemp(Ity_I32); 9386 IRTemp rMt = newTemp(Ity_I32); 9387 IRTemp res_q = newTemp(Ity_I32); 9388 9389 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9390 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9391 9392 assign(res_q, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt))); 9393 if (isT) 9394 putIRegT( regD, mkexpr(res_q), condT ); 9395 else 9396 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9397 9398 DIP("uhadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9399 return True; 9400 } 9401 /* fall through */ 9402 } 9403 9404 /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */ 9405 { 9406 UInt regD = 99, regN = 99, regM = 99; 9407 Bool gate = False; 9408 9409 if (isT) { 9410 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) { 9411 regN = INSNT0(3,0); 9412 regD = INSNT1(11,8); 9413 regM = INSNT1(3,0); 9414 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9415 gate = True; 9416 } 9417 } else { 9418 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) && 9419 INSNA(11,8) == BITS4(1,1,1,1) && 9420 INSNA(7,4) == BITS4(1,0,0,1)) { 9421 regD = INSNA(15,12); 9422 regN = INSNA(19,16); 9423 regM = INSNA(3,0); 9424 if (regD != 15 && regN != 15 && regM != 15) 9425 gate = True; 9426 } 9427 } 9428 9429 if (gate) { 9430 IRTemp rNt = newTemp(Ity_I32); 9431 IRTemp rMt = newTemp(Ity_I32); 9432 IRTemp res_q = newTemp(Ity_I32); 9433 9434 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9435 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9436 9437 assign(res_q, binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt))); 9438 if (isT) 9439 putIRegT( regD, mkexpr(res_q), condT ); 9440 else 9441 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9442 9443 DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9444 return True; 9445 } 9446 /* fall through */ 9447 } 9448 9449 /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */ 9450 { 9451 UInt regD = 99, regN = 99, regM = 99; 9452 Bool gate = False; 9453 9454 if (isT) { 9455 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9456 regN = INSNT0(3,0); 9457 regD = INSNT1(11,8); 9458 regM = INSNT1(3,0); 9459 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9460 gate = True; 9461 } 9462 } else { 9463 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9464 INSNA(11,8) == BITS4(1,1,1,1) && 9465 INSNA(7,4) == BITS4(0,0,0,1)) { 9466 regD = INSNA(15,12); 9467 regN = INSNA(19,16); 9468 regM = INSNA(3,0); 9469 if (regD != 15 && regN != 15 && regM != 15) 9470 gate = True; 9471 } 9472 } 9473 9474 if (gate) { 9475 IRTemp rNt = newTemp(Ity_I32); 9476 IRTemp rMt = newTemp(Ity_I32); 9477 IRTemp res_q = newTemp(Ity_I32); 9478 9479 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9480 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9481 9482 assign(res_q, binop(Iop_QAdd16Sx2, mkexpr(rNt), mkexpr(rMt))); 9483 if (isT) 9484 putIRegT( regD, mkexpr(res_q), condT ); 9485 else 9486 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9487 9488 DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9489 return True; 9490 } 9491 /* fall through */ 9492 } 9493 9494 /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */ 9495 { 9496 UInt regD = 99, regN = 99, regM = 99; 9497 Bool gate = False; 9498 9499 if (isT) { 9500 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9501 regN = INSNT0(3,0); 9502 regD = INSNT1(11,8); 9503 regM = INSNT1(3,0); 9504 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9505 gate = True; 9506 } 9507 } else { 9508 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9509 INSNA(11,8) == BITS4(1,1,1,1) && 9510 INSNA(7,4) == BITS4(0,1,1,1)) { 9511 regD = INSNA(15,12); 9512 regN = INSNA(19,16); 9513 regM = INSNA(3,0); 9514 if (regD != 15 && regN != 15 && regM != 15) 9515 gate = True; 9516 } 9517 } 9518 9519 if (gate) { 9520 IRTemp rNt = newTemp(Ity_I32); 9521 IRTemp rMt = newTemp(Ity_I32); 9522 IRTemp res_q = newTemp(Ity_I32); 9523 9524 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9525 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9526 9527 assign(res_q, binop(Iop_QSub16Sx2, mkexpr(rNt), mkexpr(rMt))); 9528 if (isT) 9529 putIRegT( regD, mkexpr(res_q), condT ); 9530 else 9531 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9532 9533 DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9534 return True; 9535 } 9536 /* fall through */ 9537 } 9538 9539 ///////////////////////////////////////////////////////////////// 9540 ///////////////////////////////////////////////////////////////// 9541 ///////////////////////////////////////////////////////////////// 9542 ///////////////////////////////////////////////////////////////// 9543 ///////////////////////////////////////////////////////////////// 9544 9545 /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */ 9546 /* note: the hardware seems to construct the result differently 9547 from wot the manual says. */ 9548 { 9549 UInt regD = 99, regN = 99, regM = 99; 9550 Bool gate = False; 9551 9552 if (isT) { 9553 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9554 regN = INSNT0(3,0); 9555 regD = INSNT1(11,8); 9556 regM = INSNT1(3,0); 9557 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9558 gate = True; 9559 } 9560 } else { 9561 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9562 INSNA(11,8) == BITS4(1,1,1,1) && 9563 INSNA(7,4) == BITS4(0,1,0,1)) { 9564 regD = INSNA(15,12); 9565 regN = INSNA(19,16); 9566 regM = INSNA(3,0); 9567 if (regD != 15 && regN != 15 && regM != 15) 9568 gate = True; 9569 } 9570 } 9571 9572 if (gate) { 9573 IRTemp irt_regN = newTemp(Ity_I32); 9574 IRTemp irt_regM = newTemp(Ity_I32); 9575 IRTemp irt_sum = newTemp(Ity_I32); 9576 IRTemp irt_diff = newTemp(Ity_I32); 9577 IRTemp irt_sum_res = newTemp(Ity_I32); 9578 IRTemp irt_diff_res = newTemp(Ity_I32); 9579 9580 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 9581 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) ); 9582 9583 assign( irt_diff, 9584 binop( Iop_Sub32, 9585 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 9586 binop( Iop_Sar32, 9587 binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 9588 mkU8(16) ) ) ); 9589 armSignedSatQ( irt_diff, 0x10, &irt_diff_res, NULL); 9590 9591 assign( irt_sum, 9592 binop( Iop_Add32, 9593 binop( Iop_Sar32, 9594 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 9595 mkU8(16) ), 9596 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) )) ); 9597 armSignedSatQ( irt_sum, 0x10, &irt_sum_res, NULL ); 9598 9599 IRExpr* ire_result = binop( Iop_Or32, 9600 binop( Iop_Shl32, mkexpr(irt_diff_res), 9601 mkU8(16) ), 9602 binop( Iop_And32, mkexpr(irt_sum_res), 9603 mkU32(0xFFFF)) ); 9604 9605 if (isT) 9606 putIRegT( regD, ire_result, condT ); 9607 else 9608 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9609 9610 DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM ); 9611 return True; 9612 } 9613 /* fall through */ 9614 } 9615 9616 /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */ 9617 { 9618 UInt regD = 99, regN = 99, regM = 99; 9619 Bool gate = False; 9620 9621 if (isT) { 9622 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9623 regN = INSNT0(3,0); 9624 regD = INSNT1(11,8); 9625 regM = INSNT1(3,0); 9626 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9627 gate = True; 9628 } 9629 } else { 9630 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9631 INSNA(11,8) == BITS4(1,1,1,1) && 9632 INSNA(7,4) == BITS4(0,0,1,1)) { 9633 regD = INSNA(15,12); 9634 regN = INSNA(19,16); 9635 regM = INSNA(3,0); 9636 if (regD != 15 && regN != 15 && regM != 15) 9637 gate = True; 9638 } 9639 } 9640 9641 if (gate) { 9642 IRTemp irt_regN = newTemp(Ity_I32); 9643 IRTemp irt_regM = newTemp(Ity_I32); 9644 IRTemp irt_sum = newTemp(Ity_I32); 9645 IRTemp irt_diff = newTemp(Ity_I32); 9646 IRTemp irt_res_sum = newTemp(Ity_I32); 9647 IRTemp irt_res_diff = newTemp(Ity_I32); 9648 9649 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 9650 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) ); 9651 9652 assign( irt_diff, 9653 binop( Iop_Sub32, 9654 binop( Iop_Sar32, 9655 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 9656 mkU8(16) ), 9657 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) ); 9658 armSignedSatQ( irt_diff, 0x10, &irt_res_diff, NULL ); 9659 9660 assign( irt_sum, 9661 binop( Iop_Add32, 9662 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 9663 binop( Iop_Sar32, 9664 binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 9665 mkU8(16) ) ) ); 9666 armSignedSatQ( irt_sum, 0x10, &irt_res_sum, NULL ); 9667 9668 IRExpr* ire_result 9669 = binop( Iop_Or32, 9670 binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ), 9671 binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) ); 9672 9673 if (isT) 9674 putIRegT( regD, ire_result, condT ); 9675 else 9676 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9677 9678 DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM ); 9679 return True; 9680 } 9681 /* fall through */ 9682 } 9683 9684 /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */ 9685 { 9686 UInt regD = 99, regN = 99, regM = 99; 9687 Bool gate = False; 9688 9689 if (isT) { 9690 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) { 9691 regN = INSNT0(3,0); 9692 regD = INSNT1(11,8); 9693 regM = INSNT1(3,0); 9694 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9695 gate = True; 9696 } 9697 } else { 9698 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 9699 INSNA(11,8) == BITS4(1,1,1,1) && 9700 INSNA(7,4) == BITS4(0,0,1,1)) { 9701 regD = INSNA(15,12); 9702 regN = INSNA(19,16); 9703 regM = INSNA(3,0); 9704 if (regD != 15 && regN != 15 && regM != 15) 9705 gate = True; 9706 } 9707 } 9708 9709 if (gate) { 9710 IRTemp irt_regN = newTemp(Ity_I32); 9711 IRTemp irt_regM = newTemp(Ity_I32); 9712 IRTemp irt_sum = newTemp(Ity_I32); 9713 IRTemp irt_diff = newTemp(Ity_I32); 9714 9715 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 9716 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) ); 9717 9718 assign( irt_diff, 9719 binop( Iop_Sub32, 9720 binop( Iop_Sar32, 9721 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 9722 mkU8(16) ), 9723 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) ); 9724 9725 assign( irt_sum, 9726 binop( Iop_Add32, 9727 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 9728 binop( Iop_Sar32, 9729 binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 9730 mkU8(16) ) ) ); 9731 9732 IRExpr* ire_result 9733 = binop( Iop_Or32, 9734 binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ), 9735 binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) ); 9736 9737 IRTemp ge10 = newTemp(Ity_I32); 9738 assign(ge10, unop(Iop_Not32, mkexpr(irt_diff))); 9739 put_GEFLAG32( 0, 31, mkexpr(ge10), condT ); 9740 put_GEFLAG32( 1, 31, mkexpr(ge10), condT ); 9741 9742 IRTemp ge32 = newTemp(Ity_I32); 9743 assign(ge32, unop(Iop_Not32, mkexpr(irt_sum))); 9744 put_GEFLAG32( 2, 31, mkexpr(ge32), condT ); 9745 put_GEFLAG32( 3, 31, mkexpr(ge32), condT ); 9746 9747 if (isT) 9748 putIRegT( regD, ire_result, condT ); 9749 else 9750 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9751 9752 DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM ); 9753 return True; 9754 } 9755 /* fall through */ 9756 } 9757 9758 /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */ 9759 /* --------------- smsad, smsadx<c><Rd>,<Rn>,<Rm> --------------- */ 9760 { 9761 UInt regD = 99, regN = 99, regM = 99, bitM = 99; 9762 Bool gate = False, isAD = False; 9763 9764 if (isT) { 9765 if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4) 9766 && (INSNT1(15,0) & 0xF0E0) == 0xF000) { 9767 regN = INSNT0(3,0); 9768 regD = INSNT1(11,8); 9769 regM = INSNT1(3,0); 9770 bitM = INSNT1(4,4); 9771 isAD = INSNT0(15,4) == 0xFB2; 9772 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9773 gate = True; 9774 } 9775 } else { 9776 if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) && 9777 INSNA(15,12) == BITS4(1,1,1,1) && 9778 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1) ) { 9779 regD = INSNA(19,16); 9780 regN = INSNA(3,0); 9781 regM = INSNA(11,8); 9782 bitM = INSNA(5,5); 9783 isAD = INSNA(6,6) == 0; 9784 if (regD != 15 && regN != 15 && regM != 15) 9785 gate = True; 9786 } 9787 } 9788 9789 if (gate) { 9790 IRTemp irt_regN = newTemp(Ity_I32); 9791 IRTemp irt_regM = newTemp(Ity_I32); 9792 IRTemp irt_prod_lo = newTemp(Ity_I32); 9793 IRTemp irt_prod_hi = newTemp(Ity_I32); 9794 IRTemp tmpM = newTemp(Ity_I32); 9795 9796 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 9797 9798 assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) ); 9799 assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) ); 9800 9801 assign( irt_prod_lo, 9802 binop( Iop_Mul32, 9803 binop( Iop_Sar32, 9804 binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 9805 mkU8(16) ), 9806 binop( Iop_Sar32, 9807 binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 9808 mkU8(16) ) ) ); 9809 assign( irt_prod_hi, binop(Iop_Mul32, 9810 binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)), 9811 binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) ); 9812 IRExpr* ire_result 9813 = binop( isAD ? Iop_Add32 : Iop_Sub32, 9814 mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ); 9815 9816 if (isT) 9817 putIRegT( regD, ire_result, condT ); 9818 else 9819 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9820 9821 if (isAD) { 9822 or_into_QFLAG32( 9823 signed_overflow_after_Add32( ire_result, 9824 irt_prod_lo, irt_prod_hi ), 9825 condT 9826 ); 9827 } 9828 9829 DIP("smu%cd%s%s r%u, r%u, r%u\n", 9830 isAD ? 'a' : 's', 9831 bitM ? "x" : "", nCC(conq), regD, regN, regM); 9832 return True; 9833 } 9834 /* fall through */ 9835 } 9836 9837 /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */ 9838 /* --------------- smlsd{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */ 9839 { 9840 UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99; 9841 Bool gate = False, isAD = False; 9842 9843 if (isT) { 9844 if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4) 9845 && INSNT1(7,5) == BITS3(0,0,0)) { 9846 regN = INSNT0(3,0); 9847 regD = INSNT1(11,8); 9848 regM = INSNT1(3,0); 9849 regA = INSNT1(15,12); 9850 bitM = INSNT1(4,4); 9851 isAD = INSNT0(15,4) == 0xFB2; 9852 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM) 9853 && !isBadRegT(regA)) 9854 gate = True; 9855 } 9856 } else { 9857 if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) && 9858 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) { 9859 regD = INSNA(19,16); 9860 regA = INSNA(15,12); 9861 regN = INSNA(3,0); 9862 regM = INSNA(11,8); 9863 bitM = INSNA(5,5); 9864 isAD = INSNA(6,6) == 0; 9865 if (regD != 15 && regN != 15 && regM != 15 && regA != 15) 9866 gate = True; 9867 } 9868 } 9869 9870 if (gate) { 9871 IRTemp irt_regN = newTemp(Ity_I32); 9872 IRTemp irt_regM = newTemp(Ity_I32); 9873 IRTemp irt_regA = newTemp(Ity_I32); 9874 IRTemp irt_prod_lo = newTemp(Ity_I32); 9875 IRTemp irt_prod_hi = newTemp(Ity_I32); 9876 IRTemp irt_sum = newTemp(Ity_I32); 9877 IRTemp tmpM = newTemp(Ity_I32); 9878 9879 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 9880 assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) ); 9881 9882 assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) ); 9883 assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) ); 9884 9885 assign( irt_prod_lo, 9886 binop(Iop_Mul32, 9887 binop(Iop_Sar32, 9888 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 9889 mkU8(16)), 9890 binop(Iop_Sar32, 9891 binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 9892 mkU8(16))) ); 9893 assign( irt_prod_hi, 9894 binop( Iop_Mul32, 9895 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 9896 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) ); 9897 assign( irt_sum, binop( isAD ? Iop_Add32 : Iop_Sub32, 9898 mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ) ); 9899 9900 IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_sum), mkexpr(irt_regA)); 9901 9902 if (isT) 9903 putIRegT( regD, ire_result, condT ); 9904 else 9905 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9906 9907 if (isAD) { 9908 or_into_QFLAG32( 9909 signed_overflow_after_Add32( mkexpr(irt_sum), 9910 irt_prod_lo, irt_prod_hi ), 9911 condT 9912 ); 9913 } 9914 9915 or_into_QFLAG32( 9916 signed_overflow_after_Add32( ire_result, irt_sum, irt_regA ), 9917 condT 9918 ); 9919 9920 DIP("sml%cd%s%s r%u, r%u, r%u, r%u\n", 9921 isAD ? 'a' : 's', 9922 bitM ? "x" : "", nCC(conq), regD, regN, regM, regA); 9923 return True; 9924 } 9925 /* fall through */ 9926 } 9927 9928 /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */ 9929 { 9930 UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99, bitN = 99; 9931 Bool gate = False; 9932 9933 if (isT) { 9934 if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) { 9935 regN = INSNT0(3,0); 9936 regD = INSNT1(11,8); 9937 regM = INSNT1(3,0); 9938 regA = INSNT1(15,12); 9939 bitM = INSNT1(4,4); 9940 bitN = INSNT1(5,5); 9941 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM) 9942 && !isBadRegT(regA)) 9943 gate = True; 9944 } 9945 } else { 9946 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) && 9947 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) { 9948 regD = INSNA(19,16); 9949 regN = INSNA(3,0); 9950 regM = INSNA(11,8); 9951 regA = INSNA(15,12); 9952 bitM = INSNA(6,6); 9953 bitN = INSNA(5,5); 9954 if (regD != 15 && regN != 15 && regM != 15 && regA != 15) 9955 gate = True; 9956 } 9957 } 9958 9959 if (gate) { 9960 IRTemp irt_regA = newTemp(Ity_I32); 9961 IRTemp irt_prod = newTemp(Ity_I32); 9962 9963 assign( irt_prod, 9964 binop(Iop_Mul32, 9965 binop(Iop_Sar32, 9966 binop(Iop_Shl32, 9967 isT ? getIRegT(regN) : getIRegA(regN), 9968 mkU8(bitN ? 0 : 16)), 9969 mkU8(16)), 9970 binop(Iop_Sar32, 9971 binop(Iop_Shl32, 9972 isT ? getIRegT(regM) : getIRegA(regM), 9973 mkU8(bitM ? 0 : 16)), 9974 mkU8(16))) ); 9975 9976 assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) ); 9977 9978 IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_prod), mkexpr(irt_regA)); 9979 9980 if (isT) 9981 putIRegT( regD, ire_result, condT ); 9982 else 9983 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9984 9985 or_into_QFLAG32( 9986 signed_overflow_after_Add32( ire_result, irt_prod, irt_regA ), 9987 condT 9988 ); 9989 9990 DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n", 9991 bitN ? 't' : 'b', bitM ? 't' : 'b', 9992 nCC(conq), regD, regN, regM, regA ); 9993 return True; 9994 } 9995 /* fall through */ 9996 } 9997 9998 /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */ 9999 { 10000 UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99; 10001 Bool gate = False; 10002 10003 if (isT) { 10004 if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) { 10005 regN = INSNT0(3,0); 10006 regD = INSNT1(11,8); 10007 regM = INSNT1(3,0); 10008 regA = INSNT1(15,12); 10009 bitM = INSNT1(4,4); 10010 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM) 10011 && !isBadRegT(regA)) 10012 gate = True; 10013 } 10014 } else { 10015 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) && 10016 (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) { 10017 regD = INSNA(19,16); 10018 regN = INSNA(3,0); 10019 regM = INSNA(11,8); 10020 regA = INSNA(15,12); 10021 bitM = INSNA(6,6); 10022 if (regD != 15 && regN != 15 && regM != 15 && regA != 15) 10023 gate = True; 10024 } 10025 } 10026 10027 if (gate) { 10028 IRTemp irt_regA = newTemp(Ity_I32); 10029 IRTemp irt_prod = newTemp(Ity_I64); 10030 10031 assign( irt_prod, 10032 binop(Iop_MullS32, 10033 isT ? getIRegT(regN) : getIRegA(regN), 10034 binop(Iop_Sar32, 10035 binop(Iop_Shl32, 10036 isT ? getIRegT(regM) : getIRegA(regM), 10037 mkU8(bitM ? 0 : 16)), 10038 mkU8(16))) ); 10039 10040 assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) ); 10041 10042 IRTemp prod32 = newTemp(Ity_I32); 10043 assign(prod32, 10044 binop(Iop_Or32, 10045 binop(Iop_Shl32, unop(Iop_64HIto32, mkexpr(irt_prod)), mkU8(16)), 10046 binop(Iop_Shr32, unop(Iop_64to32, mkexpr(irt_prod)), mkU8(16)) 10047 )); 10048 10049 IRExpr* ire_result = binop(Iop_Add32, mkexpr(prod32), mkexpr(irt_regA)); 10050 10051 if (isT) 10052 putIRegT( regD, ire_result, condT ); 10053 else 10054 putIRegA( regD, ire_result, condT, Ijk_Boring ); 10055 10056 or_into_QFLAG32( 10057 signed_overflow_after_Add32( ire_result, prod32, irt_regA ), 10058 condT 10059 ); 10060 10061 DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n", 10062 bitM ? 't' : 'b', 10063 nCC(conq), regD, regN, regM, regA ); 10064 return True; 10065 } 10066 /* fall through */ 10067 } 10068 10069 /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */ 10070 /* fixme: fix up the test in v6media.c so that we can pass the ge 10071 flags as part of the test. */ 10072 { 10073 UInt regD = 99, regN = 99, regM = 99; 10074 Bool gate = False; 10075 10076 if (isT) { 10077 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) { 10078 regN = INSNT0(3,0); 10079 regD = INSNT1(11,8); 10080 regM = INSNT1(3,0); 10081 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 10082 gate = True; 10083 } 10084 } else { 10085 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) && 10086 INSNA(11,8) == BITS4(1,1,1,1) && 10087 INSNA(7,4) == BITS4(1,0,1,1)) { 10088 regD = INSNA(15,12); 10089 regN = INSNA(19,16); 10090 regM = INSNA(3,0); 10091 if (regD != 15 && regN != 15 && regM != 15) 10092 gate = True; 10093 } 10094 } 10095 10096 if (gate) { 10097 IRTemp irt_ge_flag0 = newTemp(Ity_I32); 10098 IRTemp irt_ge_flag1 = newTemp(Ity_I32); 10099 IRTemp irt_ge_flag2 = newTemp(Ity_I32); 10100 IRTemp irt_ge_flag3 = newTemp(Ity_I32); 10101 10102 assign( irt_ge_flag0, get_GEFLAG32(0) ); 10103 assign( irt_ge_flag1, get_GEFLAG32(1) ); 10104 assign( irt_ge_flag2, get_GEFLAG32(2) ); 10105 assign( irt_ge_flag3, get_GEFLAG32(3) ); 10106 10107 IRExpr* ire_ge_flag0_or 10108 = binop(Iop_Or32, mkexpr(irt_ge_flag0), 10109 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag0))); 10110 IRExpr* ire_ge_flag1_or 10111 = binop(Iop_Or32, mkexpr(irt_ge_flag1), 10112 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag1))); 10113 IRExpr* ire_ge_flag2_or 10114 = binop(Iop_Or32, mkexpr(irt_ge_flag2), 10115 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag2))); 10116 IRExpr* ire_ge_flag3_or 10117 = binop(Iop_Or32, mkexpr(irt_ge_flag3), 10118 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag3))); 10119 10120 IRExpr* ire_ge_flags 10121 = binop( Iop_Or32, 10122 binop(Iop_Or32, 10123 binop(Iop_And32, 10124 binop(Iop_Sar32, ire_ge_flag0_or, mkU8(31)), 10125 mkU32(0x000000ff)), 10126 binop(Iop_And32, 10127 binop(Iop_Sar32, ire_ge_flag1_or, mkU8(31)), 10128 mkU32(0x0000ff00))), 10129 binop(Iop_Or32, 10130 binop(Iop_And32, 10131 binop(Iop_Sar32, ire_ge_flag2_or, mkU8(31)), 10132 mkU32(0x00ff0000)), 10133 binop(Iop_And32, 10134 binop(Iop_Sar32, ire_ge_flag3_or, mkU8(31)), 10135 mkU32(0xff000000))) ); 10136 10137 IRExpr* ire_result 10138 = binop(Iop_Or32, 10139 binop(Iop_And32, 10140 isT ? getIRegT(regN) : getIRegA(regN), 10141 ire_ge_flags ), 10142 binop(Iop_And32, 10143 isT ? getIRegT(regM) : getIRegA(regM), 10144 unop(Iop_Not32, ire_ge_flags))); 10145 10146 if (isT) 10147 putIRegT( regD, ire_result, condT ); 10148 else 10149 putIRegA( regD, ire_result, condT, Ijk_Boring ); 10150 10151 DIP("sel%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM ); 10152 return True; 10153 } 10154 /* fall through */ 10155 } 10156 10157 /* ----------------- uxtab16<c> Rd,Rn,Rm{,rot} ------------------ */ 10158 { 10159 UInt regD = 99, regN = 99, regM = 99, rotate = 99; 10160 Bool gate = False; 10161 10162 if (isT) { 10163 if (INSNT0(15,4) == 0xFA3 && (INSNT1(15,0) & 0xF0C0) == 0xF080) { 10164 regN = INSNT0(3,0); 10165 regD = INSNT1(11,8); 10166 regM = INSNT1(3,0); 10167 rotate = INSNT1(5,4); 10168 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 10169 gate = True; 10170 } 10171 } else { 10172 if (INSNA(27,20) == BITS8(0,1,1,0,1,1,0,0) && 10173 INSNA(9,4) == BITS6(0,0,0,1,1,1) ) { 10174 regD = INSNA(15,12); 10175 regN = INSNA(19,16); 10176 regM = INSNA(3,0); 10177 rotate = INSNA(11,10); 10178 if (regD != 15 && regN != 15 && regM != 15) 10179 gate = True; 10180 } 10181 } 10182 10183 if (gate) { 10184 IRTemp irt_regN = newTemp(Ity_I32); 10185 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 10186 10187 IRTemp irt_regM = newTemp(Ity_I32); 10188 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) ); 10189 10190 IRTemp irt_rot = newTemp(Ity_I32); 10191 assign( irt_rot, binop(Iop_And32, 10192 genROR32(irt_regM, 8 * rotate), 10193 mkU32(0x00FF00FF)) ); 10194 10195 IRExpr* resLo 10196 = binop(Iop_And32, 10197 binop(Iop_Add32, mkexpr(irt_regN), mkexpr(irt_rot)), 10198 mkU32(0x0000FFFF)); 10199 10200 IRExpr* resHi 10201 = binop(Iop_Add32, 10202 binop(Iop_And32, mkexpr(irt_regN), mkU32(0xFFFF0000)), 10203 binop(Iop_And32, mkexpr(irt_rot), mkU32(0xFFFF0000))); 10204 10205 IRExpr* ire_result 10206 = binop( Iop_Or32, resHi, resLo ); 10207 10208 if (isT) 10209 putIRegT( regD, ire_result, condT ); 10210 else 10211 putIRegA( regD, ire_result, condT, Ijk_Boring ); 10212 10213 DIP( "uxtab16%s r%u, r%u, r%u, ROR #%u\n", 10214 nCC(conq), regD, regN, regM, 8 * rotate ); 10215 return True; 10216 } 10217 /* fall through */ 10218 } 10219 10220 /* --------------- usad8 Rd,Rn,Rm ---------------- */ 10221 /* --------------- usada8 Rd,Rn,Rm,Ra ---------------- */ 10222 { 10223 UInt rD = 99, rN = 99, rM = 99, rA = 99; 10224 Bool gate = False; 10225 10226 if (isT) { 10227 if (INSNT0(15,4) == 0xFB7 && INSNT1(7,4) == BITS4(0,0,0,0)) { 10228 rN = INSNT0(3,0); 10229 rA = INSNT1(15,12); 10230 rD = INSNT1(11,8); 10231 rM = INSNT1(3,0); 10232 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && rA != 13) 10233 gate = True; 10234 } 10235 } else { 10236 if (INSNA(27,20) == BITS8(0,1,1,1,1,0,0,0) && 10237 INSNA(7,4) == BITS4(0,0,0,1) ) { 10238 rD = INSNA(19,16); 10239 rA = INSNA(15,12); 10240 rM = INSNA(11,8); 10241 rN = INSNA(3,0); 10242 if (rD != 15 && rN != 15 && rM != 15 /* but rA can be 15 */) 10243 gate = True; 10244 } 10245 } 10246 /* We allow rA == 15, to denote the usad8 (no accumulator) case. */ 10247 10248 if (gate) { 10249 IRExpr* rNe = isT ? getIRegT(rN) : getIRegA(rN); 10250 IRExpr* rMe = isT ? getIRegT(rM) : getIRegA(rM); 10251 IRExpr* rAe = rA == 15 ? mkU32(0) 10252 : (isT ? getIRegT(rA) : getIRegA(rA)); 10253 IRExpr* res = binop(Iop_Add32, 10254 binop(Iop_Sad8Ux4, rNe, rMe), 10255 rAe); 10256 if (isT) 10257 putIRegT( rD, res, condT ); 10258 else 10259 putIRegA( rD, res, condT, Ijk_Boring ); 10260 10261 if (rA == 15) { 10262 DIP( "usad8%s r%u, r%u, r%u\n", 10263 nCC(conq), rD, rN, rM ); 10264 } else { 10265 DIP( "usada8%s r%u, r%u, r%u, r%u\n", 10266 nCC(conq), rD, rN, rM, rA ); 10267 } 10268 return True; 10269 } 10270 /* fall through */ 10271 } 10272 10273 /* ------------------ qadd<c> <Rd>,<Rn>,<Rm> ------------------- */ 10274 { 10275 UInt regD = 99, regN = 99, regM = 99; 10276 Bool gate = False; 10277 10278 if (isT) { 10279 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF080) { 10280 regN = INSNT0(3,0); 10281 regD = INSNT1(11,8); 10282 regM = INSNT1(3,0); 10283 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 10284 gate = True; 10285 } 10286 } else { 10287 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) && 10288 INSNA(11,8) == BITS4(0,0,0,0) && 10289 INSNA(7,4) == BITS4(0,1,0,1)) { 10290 regD = INSNA(15,12); 10291 regN = INSNA(19,16); 10292 regM = INSNA(3,0); 10293 if (regD != 15 && regN != 15 && regM != 15) 10294 gate = True; 10295 } 10296 } 10297 10298 if (gate) { 10299 IRTemp rNt = newTemp(Ity_I32); 10300 IRTemp rMt = newTemp(Ity_I32); 10301 IRTemp res_q = newTemp(Ity_I32); 10302 10303 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 10304 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 10305 10306 assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rNt))); 10307 if (isT) 10308 putIRegT( regD, mkexpr(res_q), condT ); 10309 else 10310 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 10311 10312 or_into_QFLAG32( 10313 signed_overflow_after_Add32( 10314 binop(Iop_Add32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt), 10315 condT 10316 ); 10317 10318 DIP("qadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN); 10319 return True; 10320 } 10321 /* fall through */ 10322 } 10323 10324 /* ------------------ qdadd<c> <Rd>,<Rm>,<Rn> ------------------- */ 10325 { 10326 UInt regD = 99, regN = 99, regM = 99; 10327 Bool gate = False; 10328 10329 if (isT) { 10330 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF090) { 10331 regN = INSNT0(3,0); 10332 regD = INSNT1(11,8); 10333 regM = INSNT1(3,0); 10334 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 10335 gate = True; 10336 } 10337 } else { 10338 if (INSNA(27,20) == BITS8(0,0,0,1,0,1,0,0) && 10339 INSNA(11,8) == BITS4(0,0,0,0) && 10340 INSNA(7,4) == BITS4(0,1,0,1)) { 10341 regD = INSNA(15,12); 10342 regN = INSNA(19,16); 10343 regM = INSNA(3,0); 10344 if (regD != 15 && regN != 15 && regM != 15) 10345 gate = True; 10346 } 10347 } 10348 10349 if (gate) { 10350 IRTemp rNt = newTemp(Ity_I32); 10351 IRTemp rMt = newTemp(Ity_I32); 10352 IRTemp rN_d = newTemp(Ity_I32); 10353 IRTemp res_q = newTemp(Ity_I32); 10354 10355 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 10356 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 10357 10358 or_into_QFLAG32( 10359 signed_overflow_after_Add32( 10360 binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt), 10361 condT 10362 ); 10363 10364 assign(rN_d, binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt))); 10365 assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rN_d))); 10366 if (isT) 10367 putIRegT( regD, mkexpr(res_q), condT ); 10368 else 10369 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 10370 10371 or_into_QFLAG32( 10372 signed_overflow_after_Add32( 10373 binop(Iop_Add32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d), 10374 condT 10375 ); 10376 10377 DIP("qdadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN); 10378 return True; 10379 } 10380 /* fall through */ 10381 } 10382 10383 /* ------------------ qsub<c> <Rd>,<Rn>,<Rm> ------------------- */ 10384 { 10385 UInt regD = 99, regN = 99, regM = 99; 10386 Bool gate = False; 10387 10388 if (isT) { 10389 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0A0) { 10390 regN = INSNT0(3,0); 10391 regD = INSNT1(11,8); 10392 regM = INSNT1(3,0); 10393 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 10394 gate = True; 10395 } 10396 } else { 10397 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) && 10398 INSNA(11,8) == BITS4(0,0,0,0) && 10399 INSNA(7,4) == BITS4(0,1,0,1)) { 10400 regD = INSNA(15,12); 10401 regN = INSNA(19,16); 10402 regM = INSNA(3,0); 10403 if (regD != 15 && regN != 15 && regM != 15) 10404 gate = True; 10405 } 10406 } 10407 10408 if (gate) { 10409 IRTemp rNt = newTemp(Ity_I32); 10410 IRTemp rMt = newTemp(Ity_I32); 10411 IRTemp res_q = newTemp(Ity_I32); 10412 10413 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 10414 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 10415 10416 assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rNt))); 10417 if (isT) 10418 putIRegT( regD, mkexpr(res_q), condT ); 10419 else 10420 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 10421 10422 or_into_QFLAG32( 10423 signed_overflow_after_Sub32( 10424 binop(Iop_Sub32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt), 10425 condT 10426 ); 10427 10428 DIP("qsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN); 10429 return True; 10430 } 10431 /* fall through */ 10432 } 10433 10434 /* ------------------ qdsub<c> <Rd>,<Rm>,<Rn> ------------------- */ 10435 { 10436 UInt regD = 99, regN = 99, regM = 99; 10437 Bool gate = False; 10438 10439 if (isT) { 10440 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0B0) { 10441 regN = INSNT0(3,0); 10442 regD = INSNT1(11,8); 10443 regM = INSNT1(3,0); 10444 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 10445 gate = True; 10446 } 10447 } else { 10448 if (INSNA(27,20) == BITS8(0,0,0,1,0,1,1,0) && 10449 INSNA(11,8) == BITS4(0,0,0,0) && 10450 INSNA(7,4) == BITS4(0,1,0,1)) { 10451 regD = INSNA(15,12); 10452 regN = INSNA(19,16); 10453 regM = INSNA(3,0); 10454 if (regD != 15 && regN != 15 && regM != 15) 10455 gate = True; 10456 } 10457 } 10458 10459 if (gate) { 10460 IRTemp rNt = newTemp(Ity_I32); 10461 IRTemp rMt = newTemp(Ity_I32); 10462 IRTemp rN_d = newTemp(Ity_I32); 10463 IRTemp res_q = newTemp(Ity_I32); 10464 10465 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 10466 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 10467 10468 or_into_QFLAG32( 10469 signed_overflow_after_Add32( 10470 binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt), 10471 condT 10472 ); 10473 10474 assign(rN_d, binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt))); 10475 assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rN_d))); 10476 if (isT) 10477 putIRegT( regD, mkexpr(res_q), condT ); 10478 else 10479 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 10480 10481 or_into_QFLAG32( 10482 signed_overflow_after_Sub32( 10483 binop(Iop_Sub32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d), 10484 condT 10485 ); 10486 10487 DIP("qdsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN); 10488 return True; 10489 } 10490 /* fall through */ 10491 } 10492 10493 /* ------------------ uqsub16<c> <Rd>,<Rn>,<Rm> ------------------ */ 10494 { 10495 UInt regD = 99, regN = 99, regM = 99; 10496 Bool gate = False; 10497 10498 if (isT) { 10499 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF050) { 10500 regN = INSNT0(3,0); 10501 regD = INSNT1(11,8); 10502 regM = INSNT1(3,0); 10503 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 10504 gate = True; 10505 } 10506 } else { 10507 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) && 10508 INSNA(11,8) == BITS4(1,1,1,1) && 10509 INSNA(7,4) == BITS4(0,1,1,1)) { 10510 regD = INSNA(15,12); 10511 regN = INSNA(19,16); 10512 regM = INSNA(3,0); 10513 if (regD != 15 && regN != 15 && regM != 15) 10514 gate = True; 10515 } 10516 } 10517 10518 if (gate) { 10519 IRTemp rNt = newTemp(Ity_I32); 10520 IRTemp rMt = newTemp(Ity_I32); 10521 IRTemp res_q = newTemp(Ity_I32); 10522 10523 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 10524 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 10525 10526 assign(res_q, binop(Iop_QSub16Ux2, mkexpr(rNt), mkexpr(rMt))); 10527 if (isT) 10528 putIRegT( regD, mkexpr(res_q), condT ); 10529 else 10530 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 10531 10532 DIP("uqsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 10533 return True; 10534 } 10535 /* fall through */ 10536 } 10537 10538 /* ----------------- shadd16<c> <Rd>,<Rn>,<Rm> ------------------- */ 10539 { 10540 UInt regD = 99, regN = 99, regM = 99; 10541 Bool gate = False; 10542 10543 if (isT) { 10544 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF020) { 10545 regN = INSNT0(3,0); 10546 regD = INSNT1(11,8); 10547 regM = INSNT1(3,0); 10548 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 10549 gate = True; 10550 } 10551 } else { 10552 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) && 10553 INSNA(11,8) == BITS4(1,1,1,1) && 10554 INSNA(7,4) == BITS4(0,0,0,1)) { 10555 regD = INSNA(15,12); 10556 regN = INSNA(19,16); 10557 regM = INSNA(3,0); 10558 if (regD != 15 && regN != 15 && regM != 15) 10559 gate = True; 10560 } 10561 } 10562 10563 if (gate) { 10564 IRTemp rNt = newTemp(Ity_I32); 10565 IRTemp rMt = newTemp(Ity_I32); 10566 IRTemp res_q = newTemp(Ity_I32); 10567 10568 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 10569 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 10570 10571 assign(res_q, binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt))); 10572 if (isT) 10573 putIRegT( regD, mkexpr(res_q), condT ); 10574 else 10575 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 10576 10577 DIP("shadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 10578 return True; 10579 } 10580 /* fall through */ 10581 } 10582 10583 /* ----------------- uhsub8<c> <Rd>,<Rn>,<Rm> ------------------- */ 10584 { 10585 UInt regD = 99, regN = 99, regM = 99; 10586 Bool gate = False; 10587 10588 if (isT) { 10589 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF060) { 10590 regN = INSNT0(3,0); 10591 regD = INSNT1(11,8); 10592 regM = INSNT1(3,0); 10593 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 10594 gate = True; 10595 } 10596 } else { 10597 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) && 10598 INSNA(11,8) == BITS4(1,1,1,1) && 10599 INSNA(7,4) == BITS4(1,1,1,1)) { 10600 regD = INSNA(15,12); 10601 regN = INSNA(19,16); 10602 regM = INSNA(3,0); 10603 if (regD != 15 && regN != 15 && regM != 15) 10604 gate = True; 10605 } 10606 } 10607 10608 if (gate) { 10609 IRTemp rNt = newTemp(Ity_I32); 10610 IRTemp rMt = newTemp(Ity_I32); 10611 IRTemp res_q = newTemp(Ity_I32); 10612 10613 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 10614 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 10615 10616 assign(res_q, binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt))); 10617 if (isT) 10618 putIRegT( regD, mkexpr(res_q), condT ); 10619 else 10620 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 10621 10622 DIP("uhsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 10623 return True; 10624 } 10625 /* fall through */ 10626 } 10627 10628 /* ----------------- uhsub16<c> <Rd>,<Rn>,<Rm> ------------------- */ 10629 { 10630 UInt regD = 99, regN = 99, regM = 99; 10631 Bool gate = False; 10632 10633 if (isT) { 10634 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF060) { 10635 regN = INSNT0(3,0); 10636 regD = INSNT1(11,8); 10637 regM = INSNT1(3,0); 10638 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 10639 gate = True; 10640 } 10641 } else { 10642 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) && 10643 INSNA(11,8) == BITS4(1,1,1,1) && 10644 INSNA(7,4) == BITS4(0,1,1,1)) { 10645 regD = INSNA(15,12); 10646 regN = INSNA(19,16); 10647 regM = INSNA(3,0); 10648 if (regD != 15 && regN != 15 && regM != 15) 10649 gate = True; 10650 } 10651 } 10652 10653 if (gate) { 10654 IRTemp rNt = newTemp(Ity_I32); 10655 IRTemp rMt = newTemp(Ity_I32); 10656 IRTemp res_q = newTemp(Ity_I32); 10657 10658 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 10659 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 10660 10661 assign(res_q, binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt))); 10662 if (isT) 10663 putIRegT( regD, mkexpr(res_q), condT ); 10664 else 10665 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 10666 10667 DIP("uhsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 10668 return True; 10669 } 10670 /* fall through */ 10671 } 10672 10673 /* ---------- Doesn't match anything. ---------- */ 10674 return False; 10675 10676 # undef INSNA 10677 # undef INSNT0 10678 # undef INSNT1 10679 } 10680 10681 10682 /*------------------------------------------------------------*/ 10683 /*--- LDMxx/STMxx helper (both ARM and Thumb32) ---*/ 10684 /*------------------------------------------------------------*/ 10685 10686 /* Generate IR for LDMxx and STMxx. This is complex. Assumes it's 10687 unconditional, so the caller must produce a jump-around before 10688 calling this, if the insn is to be conditional. Caller is 10689 responsible for all validation of parameters. For LDMxx, if PC is 10690 amongst the values loaded, caller is also responsible for 10691 generating the jump. */ 10692 static void mk_ldm_stm ( Bool arm, /* True: ARM, False: Thumb */ 10693 UInt rN, /* base reg */ 10694 UInt bINC, /* 1: inc, 0: dec */ 10695 UInt bBEFORE, /* 1: inc/dec before, 0: after */ 10696 UInt bW, /* 1: writeback to Rn */ 10697 UInt bL, /* 1: load, 0: store */ 10698 UInt regList ) 10699 { 10700 Int i, r, m, nRegs; 10701 IRTemp jk = Ijk_Boring; 10702 10703 /* Get hold of the old Rn value. We might need to write its value 10704 to memory during a store, and if it's also the writeback 10705 register then we need to get its value now. We can't treat it 10706 exactly like the other registers we're going to transfer, 10707 because for xxMDA and xxMDB writeback forms, the generated IR 10708 updates Rn in the guest state before any transfers take place. 10709 We have to do this as per comments below, in order that if Rn is 10710 the stack pointer then it always has a value is below or equal 10711 to any of the transfer addresses. Ick. */ 10712 IRTemp oldRnT = newTemp(Ity_I32); 10713 assign(oldRnT, arm ? getIRegA(rN) : getIRegT(rN)); 10714 10715 IRTemp anchorT = newTemp(Ity_I32); 10716 /* The old (Addison-Wesley) ARM ARM seems to say that LDMxx/STMxx 10717 ignore the bottom two bits of the address. However, Cortex-A8 10718 doesn't seem to care. Hence: */ 10719 /* No .. don't force alignment .. */ 10720 /* assign(anchorT, binop(Iop_And32, mkexpr(oldRnT), mkU32(~3U))); */ 10721 /* Instead, use the potentially misaligned address directly. */ 10722 assign(anchorT, mkexpr(oldRnT)); 10723 10724 IROp opADDorSUB = bINC ? Iop_Add32 : Iop_Sub32; 10725 // bINC == 1: xxMIA, xxMIB 10726 // bINC == 0: xxMDA, xxMDB 10727 10728 // For xxMDA and xxMDB, update Rn first if necessary. We have 10729 // to do this first so that, for the common idiom of the transfers 10730 // faulting because we're pushing stuff onto a stack and the stack 10731 // is growing down onto allocate-on-fault pages (as Valgrind simulates), 10732 // we need to have the SP up-to-date "covering" (pointing below) the 10733 // transfer area. For the same reason, if we are doing xxMIA or xxMIB, 10734 // do the transfer first, and then update rN afterwards. 10735 nRegs = 0; 10736 for (i = 0; i < 16; i++) { 10737 if ((regList & (1 << i)) != 0) 10738 nRegs++; 10739 } 10740 if (bW == 1 && !bINC) { 10741 IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs)); 10742 if (arm) 10743 putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring ); 10744 else 10745 putIRegT( rN, e, IRTemp_INVALID ); 10746 } 10747 10748 // Make up a list of the registers to transfer, and their offsets 10749 // in memory relative to the anchor. If the base reg (Rn) is part 10750 // of the transfer, then do it last for a load and first for a store. 10751 UInt xReg[16], xOff[16]; 10752 Int nX = 0; 10753 m = 0; 10754 for (i = 0; i < 16; i++) { 10755 r = bINC ? i : (15-i); 10756 if (0 == (regList & (1<<r))) 10757 continue; 10758 if (bBEFORE) 10759 m++; 10760 /* paranoia: check we aren't transferring the writeback 10761 register during a load. Should be assured by decode-point 10762 check above. */ 10763 if (bW == 1 && bL == 1) 10764 vassert(r != rN); 10765 10766 xOff[nX] = 4 * m; 10767 xReg[nX] = r; 10768 nX++; 10769 10770 if (!bBEFORE) 10771 m++; 10772 } 10773 vassert(m == nRegs); 10774 vassert(nX == nRegs); 10775 vassert(nX <= 16); 10776 10777 if (bW == 0 && (regList & (1<<rN)) != 0) { 10778 /* Non-writeback, and basereg is to be transferred. Do its 10779 transfer last for a load and first for a store. Requires 10780 reordering xOff/xReg. */ 10781 if (0) { 10782 vex_printf("\nREG_LIST_PRE: (rN=%d)\n", rN); 10783 for (i = 0; i < nX; i++) 10784 vex_printf("reg %d off %d\n", xReg[i], xOff[i]); 10785 vex_printf("\n"); 10786 } 10787 10788 vassert(nX > 0); 10789 for (i = 0; i < nX; i++) { 10790 if (xReg[i] == rN) 10791 break; 10792 } 10793 vassert(i < nX); /* else we didn't find it! */ 10794 UInt tReg = xReg[i]; 10795 UInt tOff = xOff[i]; 10796 if (bL == 1) { 10797 /* load; make this transfer happen last */ 10798 if (i < nX-1) { 10799 for (m = i+1; m < nX; m++) { 10800 xReg[m-1] = xReg[m]; 10801 xOff[m-1] = xOff[m]; 10802 } 10803 vassert(m == nX); 10804 xReg[m-1] = tReg; 10805 xOff[m-1] = tOff; 10806 } 10807 } else { 10808 /* store; make this transfer happen first */ 10809 if (i > 0) { 10810 for (m = i-1; m >= 0; m--) { 10811 xReg[m+1] = xReg[m]; 10812 xOff[m+1] = xOff[m]; 10813 } 10814 vassert(m == -1); 10815 xReg[0] = tReg; 10816 xOff[0] = tOff; 10817 } 10818 } 10819 10820 if (0) { 10821 vex_printf("REG_LIST_POST:\n"); 10822 for (i = 0; i < nX; i++) 10823 vex_printf("reg %d off %d\n", xReg[i], xOff[i]); 10824 vex_printf("\n"); 10825 } 10826 } 10827 10828 /* According to the Cortex A8 TRM Sec. 5.2.1, LDM(1) with r13 as the base 10829 register and PC in the register list is a return for purposes of branch 10830 prediction. 10831 The ARM ARM Sec. C9.10.1 further specifies that writeback must be enabled 10832 to be counted in event 0x0E (Procedure return).*/ 10833 if (rN == 13 && bL == 1 && bINC && !bBEFORE && bW == 1) { 10834 jk = Ijk_Ret; 10835 } 10836 10837 /* Actually generate the transfers */ 10838 for (i = 0; i < nX; i++) { 10839 r = xReg[i]; 10840 if (bL == 1) { 10841 IRExpr* e = loadLE(Ity_I32, 10842 binop(opADDorSUB, mkexpr(anchorT), 10843 mkU32(xOff[i]))); 10844 if (arm) { 10845 putIRegA( r, e, IRTemp_INVALID, jk ); 10846 } else { 10847 // no: putIRegT( r, e, IRTemp_INVALID ); 10848 // putIRegT refuses to write to R15. But that might happen. 10849 // Since this is uncond, and we need to be able to 10850 // write the PC, just use the low level put: 10851 llPutIReg( r, e ); 10852 } 10853 } else { 10854 /* if we're storing Rn, make sure we use the correct 10855 value, as per extensive comments above */ 10856 storeLE( binop(opADDorSUB, mkexpr(anchorT), mkU32(xOff[i])), 10857 r == rN ? mkexpr(oldRnT) 10858 : (arm ? getIRegA(r) : getIRegT(r) ) ); 10859 } 10860 } 10861 10862 // If we are doing xxMIA or xxMIB, 10863 // do the transfer first, and then update rN afterwards. 10864 if (bW == 1 && bINC) { 10865 IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs)); 10866 if (arm) 10867 putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring ); 10868 else 10869 putIRegT( rN, e, IRTemp_INVALID ); 10870 } 10871 } 10872 10873 10874 /*------------------------------------------------------------*/ 10875 /*--- VFP (CP 10 and 11) instructions ---*/ 10876 /*------------------------------------------------------------*/ 10877 10878 /* Both ARM and Thumb */ 10879 10880 /* Translate a CP10 or CP11 instruction. If successful, returns 10881 True and *dres may or may not be updated. If failure, returns 10882 False and doesn't change *dres nor create any IR. 10883 10884 The ARM and Thumb encodings are identical for the low 28 bits of 10885 the insn (yay!) and that's what the caller must supply, iow, imm28 10886 has the top 4 bits masked out. Caller is responsible for 10887 determining whether the masked-out bits are valid for a CP10/11 10888 insn. The rules for the top 4 bits are: 10889 10890 ARM: 0000 to 1110 allowed, and this is the gating condition. 10891 1111 (NV) is not allowed. 10892 10893 Thumb: must be 1110. The gating condition is taken from 10894 ITSTATE in the normal way. 10895 10896 Conditionalisation: 10897 10898 Caller must supply an IRTemp 'condT' holding the gating condition, 10899 or IRTemp_INVALID indicating the insn is always executed. 10900 10901 Caller must also supply an ARMCondcode 'cond'. This is only used 10902 for debug printing, no other purpose. For ARM, this is simply the 10903 top 4 bits of the original instruction. For Thumb, the condition 10904 is not (really) known until run time, and so ARMCondAL should be 10905 passed, only so that printing of these instructions does not show 10906 any condition. 10907 10908 Finally, the caller must indicate whether this occurs in ARM or 10909 Thumb code. 10910 */ 10911 static Bool decode_CP10_CP11_instruction ( 10912 /*MOD*/DisResult* dres, 10913 UInt insn28, 10914 IRTemp condT, 10915 ARMCondcode conq, 10916 Bool isT 10917 ) 10918 { 10919 # define INSN(_bMax,_bMin) SLICE_UInt(insn28, (_bMax), (_bMin)) 10920 10921 vassert(INSN(31,28) == BITS4(0,0,0,0)); // caller's obligation 10922 10923 if (isT) { 10924 vassert(conq == ARMCondAL); 10925 } else { 10926 vassert(conq >= ARMCondEQ && conq <= ARMCondAL); 10927 } 10928 10929 /* ----------------------------------------------------------- */ 10930 /* -- VFP instructions -- double precision (mostly) -- */ 10931 /* ----------------------------------------------------------- */ 10932 10933 /* --------------------- fldmx, fstmx --------------------- */ 10934 /* 10935 31 27 23 19 15 11 7 0 10936 P U WL 10937 C4-100, C5-26 1 FSTMX cond 1100 1000 Rn Dd 1011 offset 10938 C4-100, C5-28 2 FSTMIAX cond 1100 1010 Rn Dd 1011 offset 10939 C4-100, C5-30 3 FSTMDBX cond 1101 0010 Rn Dd 1011 offset 10940 10941 C4-42, C5-26 1 FLDMX cond 1100 1001 Rn Dd 1011 offset 10942 C4-42, C5-28 2 FLDMIAX cond 1100 1011 Rn Dd 1011 offset 10943 C4-42, C5-30 3 FLDMDBX cond 1101 0011 Rn Dd 1011 offset 10944 10945 Regs transferred: Dd .. D(d + (offset-3)/2) 10946 offset must be odd, must not imply a reg > 15 10947 IA/DB: Rn is changed by (4 + 8 x # regs transferred) 10948 10949 case coding: 10950 1 at-Rn (access at Rn) 10951 2 ia-Rn (access at Rn, then Rn += 4+8n) 10952 3 db-Rn (Rn -= 4+8n, then access at Rn) 10953 */ 10954 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0)) 10955 && INSN(11,8) == BITS4(1,0,1,1)) { 10956 UInt bP = (insn28 >> 24) & 1; 10957 UInt bU = (insn28 >> 23) & 1; 10958 UInt bW = (insn28 >> 21) & 1; 10959 UInt bL = (insn28 >> 20) & 1; 10960 UInt offset = (insn28 >> 0) & 0xFF; 10961 UInt rN = INSN(19,16); 10962 UInt dD = (INSN(22,22) << 4) | INSN(15,12); 10963 UInt nRegs = (offset - 1) / 2; 10964 UInt summary = 0; 10965 Int i; 10966 10967 /**/ if (bP == 0 && bU == 1 && bW == 0) { 10968 summary = 1; 10969 } 10970 else if (bP == 0 && bU == 1 && bW == 1) { 10971 summary = 2; 10972 } 10973 else if (bP == 1 && bU == 0 && bW == 1) { 10974 summary = 3; 10975 } 10976 else goto after_vfp_fldmx_fstmx; 10977 10978 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */ 10979 if (rN == 15 && (summary == 2 || summary == 3 || isT)) 10980 goto after_vfp_fldmx_fstmx; 10981 10982 /* offset must be odd, and specify at least one register */ 10983 if (0 == (offset & 1) || offset < 3) 10984 goto after_vfp_fldmx_fstmx; 10985 10986 /* can't transfer regs after D15 */ 10987 if (dD + nRegs - 1 >= 32) 10988 goto after_vfp_fldmx_fstmx; 10989 10990 /* Now, we can't do a conditional load or store, since that very 10991 likely will generate an exception. So we have to take a side 10992 exit at this point if the condition is false. */ 10993 if (condT != IRTemp_INVALID) { 10994 if (isT) 10995 mk_skip_over_T32_if_cond_is_false( condT ); 10996 else 10997 mk_skip_over_A32_if_cond_is_false( condT ); 10998 condT = IRTemp_INVALID; 10999 } 11000 /* Ok, now we're unconditional. Do the load or store. */ 11001 11002 /* get the old Rn value */ 11003 IRTemp rnT = newTemp(Ity_I32); 11004 assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN), 11005 rN == 15)); 11006 11007 /* make a new value for Rn, post-insn */ 11008 IRTemp rnTnew = IRTemp_INVALID; 11009 if (summary == 2 || summary == 3) { 11010 rnTnew = newTemp(Ity_I32); 11011 assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32, 11012 mkexpr(rnT), 11013 mkU32(4 + 8 * nRegs))); 11014 } 11015 11016 /* decide on the base transfer address */ 11017 IRTemp taT = newTemp(Ity_I32); 11018 assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT)); 11019 11020 /* update Rn if necessary -- in case 3, we're moving it down, so 11021 update before any memory reference, in order to keep Memcheck 11022 and V's stack-extending logic (on linux) happy */ 11023 if (summary == 3) { 11024 if (isT) 11025 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 11026 else 11027 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 11028 } 11029 11030 /* generate the transfers */ 11031 for (i = 0; i < nRegs; i++) { 11032 IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i)); 11033 if (bL) { 11034 putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID); 11035 } else { 11036 storeLE(addr, getDReg(dD + i)); 11037 } 11038 } 11039 11040 /* update Rn if necessary -- in case 2, we're moving it up, so 11041 update after any memory reference, in order to keep Memcheck 11042 and V's stack-extending logic (on linux) happy */ 11043 if (summary == 2) { 11044 if (isT) 11045 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 11046 else 11047 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 11048 } 11049 11050 HChar* nm = bL==1 ? "ld" : "st"; 11051 switch (summary) { 11052 case 1: DIP("f%smx%s r%u, {d%u-d%u}\n", 11053 nm, nCC(conq), rN, dD, dD + nRegs - 1); 11054 break; 11055 case 2: DIP("f%smiax%s r%u!, {d%u-d%u}\n", 11056 nm, nCC(conq), rN, dD, dD + nRegs - 1); 11057 break; 11058 case 3: DIP("f%smdbx%s r%u!, {d%u-d%u}\n", 11059 nm, nCC(conq), rN, dD, dD + nRegs - 1); 11060 break; 11061 default: vassert(0); 11062 } 11063 11064 goto decode_success_vfp; 11065 /* FIXME alignment constraints? */ 11066 } 11067 11068 after_vfp_fldmx_fstmx: 11069 11070 /* --------------------- fldmd, fstmd --------------------- */ 11071 /* 11072 31 27 23 19 15 11 7 0 11073 P U WL 11074 C4-96, C5-26 1 FSTMD cond 1100 1000 Rn Dd 1011 offset 11075 C4-96, C5-28 2 FSTMDIA cond 1100 1010 Rn Dd 1011 offset 11076 C4-96, C5-30 3 FSTMDDB cond 1101 0010 Rn Dd 1011 offset 11077 11078 C4-38, C5-26 1 FLDMD cond 1100 1001 Rn Dd 1011 offset 11079 C4-38, C5-28 2 FLDMIAD cond 1100 1011 Rn Dd 1011 offset 11080 C4-38, C5-30 3 FLDMDBD cond 1101 0011 Rn Dd 1011 offset 11081 11082 Regs transferred: Dd .. D(d + (offset-2)/2) 11083 offset must be even, must not imply a reg > 15 11084 IA/DB: Rn is changed by (8 x # regs transferred) 11085 11086 case coding: 11087 1 at-Rn (access at Rn) 11088 2 ia-Rn (access at Rn, then Rn += 8n) 11089 3 db-Rn (Rn -= 8n, then access at Rn) 11090 */ 11091 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0)) 11092 && INSN(11,8) == BITS4(1,0,1,1)) { 11093 UInt bP = (insn28 >> 24) & 1; 11094 UInt bU = (insn28 >> 23) & 1; 11095 UInt bW = (insn28 >> 21) & 1; 11096 UInt bL = (insn28 >> 20) & 1; 11097 UInt offset = (insn28 >> 0) & 0xFF; 11098 UInt rN = INSN(19,16); 11099 UInt dD = (INSN(22,22) << 4) | INSN(15,12); 11100 UInt nRegs = offset / 2; 11101 UInt summary = 0; 11102 Int i; 11103 11104 /**/ if (bP == 0 && bU == 1 && bW == 0) { 11105 summary = 1; 11106 } 11107 else if (bP == 0 && bU == 1 && bW == 1) { 11108 summary = 2; 11109 } 11110 else if (bP == 1 && bU == 0 && bW == 1) { 11111 summary = 3; 11112 } 11113 else goto after_vfp_fldmd_fstmd; 11114 11115 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */ 11116 if (rN == 15 && (summary == 2 || summary == 3 || isT)) 11117 goto after_vfp_fldmd_fstmd; 11118 11119 /* offset must be even, and specify at least one register */ 11120 if (1 == (offset & 1) || offset < 2) 11121 goto after_vfp_fldmd_fstmd; 11122 11123 /* can't transfer regs after D15 */ 11124 if (dD + nRegs - 1 >= 32) 11125 goto after_vfp_fldmd_fstmd; 11126 11127 /* Now, we can't do a conditional load or store, since that very 11128 likely will generate an exception. So we have to take a side 11129 exit at this point if the condition is false. */ 11130 if (condT != IRTemp_INVALID) { 11131 if (isT) 11132 mk_skip_over_T32_if_cond_is_false( condT ); 11133 else 11134 mk_skip_over_A32_if_cond_is_false( condT ); 11135 condT = IRTemp_INVALID; 11136 } 11137 /* Ok, now we're unconditional. Do the load or store. */ 11138 11139 /* get the old Rn value */ 11140 IRTemp rnT = newTemp(Ity_I32); 11141 assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN), 11142 rN == 15)); 11143 11144 /* make a new value for Rn, post-insn */ 11145 IRTemp rnTnew = IRTemp_INVALID; 11146 if (summary == 2 || summary == 3) { 11147 rnTnew = newTemp(Ity_I32); 11148 assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32, 11149 mkexpr(rnT), 11150 mkU32(8 * nRegs))); 11151 } 11152 11153 /* decide on the base transfer address */ 11154 IRTemp taT = newTemp(Ity_I32); 11155 assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT)); 11156 11157 /* update Rn if necessary -- in case 3, we're moving it down, so 11158 update before any memory reference, in order to keep Memcheck 11159 and V's stack-extending logic (on linux) happy */ 11160 if (summary == 3) { 11161 if (isT) 11162 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 11163 else 11164 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 11165 } 11166 11167 /* generate the transfers */ 11168 for (i = 0; i < nRegs; i++) { 11169 IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i)); 11170 if (bL) { 11171 putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID); 11172 } else { 11173 storeLE(addr, getDReg(dD + i)); 11174 } 11175 } 11176 11177 /* update Rn if necessary -- in case 2, we're moving it up, so 11178 update after any memory reference, in order to keep Memcheck 11179 and V's stack-extending logic (on linux) happy */ 11180 if (summary == 2) { 11181 if (isT) 11182 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 11183 else 11184 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 11185 } 11186 11187 HChar* nm = bL==1 ? "ld" : "st"; 11188 switch (summary) { 11189 case 1: DIP("f%smd%s r%u, {d%u-d%u}\n", 11190 nm, nCC(conq), rN, dD, dD + nRegs - 1); 11191 break; 11192 case 2: DIP("f%smiad%s r%u!, {d%u-d%u}\n", 11193 nm, nCC(conq), rN, dD, dD + nRegs - 1); 11194 break; 11195 case 3: DIP("f%smdbd%s r%u!, {d%u-d%u}\n", 11196 nm, nCC(conq), rN, dD, dD + nRegs - 1); 11197 break; 11198 default: vassert(0); 11199 } 11200 11201 goto decode_success_vfp; 11202 /* FIXME alignment constraints? */ 11203 } 11204 11205 after_vfp_fldmd_fstmd: 11206 11207 /* ------------------- fmrx, fmxr ------------------- */ 11208 if (BITS8(1,1,1,0,1,1,1,1) == INSN(27,20) 11209 && BITS4(1,0,1,0) == INSN(11,8) 11210 && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) { 11211 UInt rD = INSN(15,12); 11212 UInt reg = INSN(19,16); 11213 if (reg == BITS4(0,0,0,1)) { 11214 if (rD == 15) { 11215 IRTemp nzcvT = newTemp(Ity_I32); 11216 /* When rD is 15, we are copying the top 4 bits of FPSCR 11217 into CPSR. That is, set the flags thunk to COPY and 11218 install FPSCR[31:28] as the value to copy. */ 11219 assign(nzcvT, binop(Iop_And32, 11220 IRExpr_Get(OFFB_FPSCR, Ity_I32), 11221 mkU32(0xF0000000))); 11222 setFlags_D1(ARMG_CC_OP_COPY, nzcvT, condT); 11223 DIP("fmstat%s\n", nCC(conq)); 11224 } else { 11225 /* Otherwise, merely transfer FPSCR to r0 .. r14. */ 11226 IRExpr* e = IRExpr_Get(OFFB_FPSCR, Ity_I32); 11227 if (isT) 11228 putIRegT(rD, e, condT); 11229 else 11230 putIRegA(rD, e, condT, Ijk_Boring); 11231 DIP("fmrx%s r%u, fpscr\n", nCC(conq), rD); 11232 } 11233 goto decode_success_vfp; 11234 } 11235 /* fall through */ 11236 } 11237 11238 if (BITS8(1,1,1,0,1,1,1,0) == INSN(27,20) 11239 && BITS4(1,0,1,0) == INSN(11,8) 11240 && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) { 11241 UInt rD = INSN(15,12); 11242 UInt reg = INSN(19,16); 11243 if (reg == BITS4(0,0,0,1)) { 11244 putMiscReg32(OFFB_FPSCR, 11245 isT ? getIRegT(rD) : getIRegA(rD), condT); 11246 DIP("fmxr%s fpscr, r%u\n", nCC(conq), rD); 11247 goto decode_success_vfp; 11248 } 11249 /* fall through */ 11250 } 11251 11252 /* --------------------- vmov --------------------- */ 11253 // VMOV dM, rD, rN 11254 if (0x0C400B10 == (insn28 & 0x0FF00FD0)) { 11255 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 11256 UInt rD = INSN(15,12); /* lo32 */ 11257 UInt rN = INSN(19,16); /* hi32 */ 11258 if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))) { 11259 /* fall through */ 11260 } else { 11261 putDReg(dM, 11262 unop(Iop_ReinterpI64asF64, 11263 binop(Iop_32HLto64, 11264 isT ? getIRegT(rN) : getIRegA(rN), 11265 isT ? getIRegT(rD) : getIRegA(rD))), 11266 condT); 11267 DIP("vmov%s d%u, r%u, r%u\n", nCC(conq), dM, rD, rN); 11268 goto decode_success_vfp; 11269 } 11270 /* fall through */ 11271 } 11272 11273 // VMOV rD, rN, dM 11274 if (0x0C500B10 == (insn28 & 0x0FF00FD0)) { 11275 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 11276 UInt rD = INSN(15,12); /* lo32 */ 11277 UInt rN = INSN(19,16); /* hi32 */ 11278 if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13)) 11279 || rD == rN) { 11280 /* fall through */ 11281 } else { 11282 IRTemp i64 = newTemp(Ity_I64); 11283 assign(i64, unop(Iop_ReinterpF64asI64, getDReg(dM))); 11284 IRExpr* hi32 = unop(Iop_64HIto32, mkexpr(i64)); 11285 IRExpr* lo32 = unop(Iop_64to32, mkexpr(i64)); 11286 if (isT) { 11287 putIRegT(rN, hi32, condT); 11288 putIRegT(rD, lo32, condT); 11289 } else { 11290 putIRegA(rN, hi32, condT, Ijk_Boring); 11291 putIRegA(rD, lo32, condT, Ijk_Boring); 11292 } 11293 DIP("vmov%s r%u, r%u, d%u\n", nCC(conq), rD, rN, dM); 11294 goto decode_success_vfp; 11295 } 11296 /* fall through */ 11297 } 11298 11299 // VMOV sD, sD+1, rN, rM 11300 if (0x0C400A10 == (insn28 & 0x0FF00FD0)) { 11301 UInt sD = (INSN(3,0) << 1) | INSN(5,5); 11302 UInt rN = INSN(15,12); 11303 UInt rM = INSN(19,16); 11304 if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13)) 11305 || sD == 31) { 11306 /* fall through */ 11307 } else { 11308 putFReg(sD, 11309 unop(Iop_ReinterpI32asF32, isT ? getIRegT(rN) : getIRegA(rN)), 11310 condT); 11311 putFReg(sD+1, 11312 unop(Iop_ReinterpI32asF32, isT ? getIRegT(rM) : getIRegA(rM)), 11313 condT); 11314 DIP("vmov%s, s%u, s%u, r%u, r%u\n", 11315 nCC(conq), sD, sD + 1, rN, rM); 11316 goto decode_success_vfp; 11317 } 11318 } 11319 11320 // VMOV rN, rM, sD, sD+1 11321 if (0x0C500A10 == (insn28 & 0x0FF00FD0)) { 11322 UInt sD = (INSN(3,0) << 1) | INSN(5,5); 11323 UInt rN = INSN(15,12); 11324 UInt rM = INSN(19,16); 11325 if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13)) 11326 || sD == 31 || rN == rM) { 11327 /* fall through */ 11328 } else { 11329 IRExpr* res0 = unop(Iop_ReinterpF32asI32, getFReg(sD)); 11330 IRExpr* res1 = unop(Iop_ReinterpF32asI32, getFReg(sD+1)); 11331 if (isT) { 11332 putIRegT(rN, res0, condT); 11333 putIRegT(rM, res1, condT); 11334 } else { 11335 putIRegA(rN, res0, condT, Ijk_Boring); 11336 putIRegA(rM, res1, condT, Ijk_Boring); 11337 } 11338 DIP("vmov%s, r%u, r%u, s%u, s%u\n", 11339 nCC(conq), rN, rM, sD, sD + 1); 11340 goto decode_success_vfp; 11341 } 11342 } 11343 11344 // VMOV rD[x], rT (ARM core register to scalar) 11345 if (0x0E000B10 == (insn28 & 0x0F900F1F)) { 11346 UInt rD = (INSN(7,7) << 4) | INSN(19,16); 11347 UInt rT = INSN(15,12); 11348 UInt opc = (INSN(22,21) << 2) | INSN(6,5); 11349 UInt index; 11350 if (rT == 15 || (isT && rT == 13)) { 11351 /* fall through */ 11352 } else { 11353 if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) { 11354 index = opc & 7; 11355 putDRegI64(rD, triop(Iop_SetElem8x8, 11356 getDRegI64(rD), 11357 mkU8(index), 11358 unop(Iop_32to8, 11359 isT ? getIRegT(rT) : getIRegA(rT))), 11360 condT); 11361 DIP("vmov%s.8 d%u[%u], r%u\n", nCC(conq), rD, index, rT); 11362 goto decode_success_vfp; 11363 } 11364 else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) { 11365 index = (opc >> 1) & 3; 11366 putDRegI64(rD, triop(Iop_SetElem16x4, 11367 getDRegI64(rD), 11368 mkU8(index), 11369 unop(Iop_32to16, 11370 isT ? getIRegT(rT) : getIRegA(rT))), 11371 condT); 11372 DIP("vmov%s.16 d%u[%u], r%u\n", nCC(conq), rD, index, rT); 11373 goto decode_success_vfp; 11374 } 11375 else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0)) { 11376 index = (opc >> 2) & 1; 11377 putDRegI64(rD, triop(Iop_SetElem32x2, 11378 getDRegI64(rD), 11379 mkU8(index), 11380 isT ? getIRegT(rT) : getIRegA(rT)), 11381 condT); 11382 DIP("vmov%s.32 d%u[%u], r%u\n", nCC(conq), rD, index, rT); 11383 goto decode_success_vfp; 11384 } else { 11385 /* fall through */ 11386 } 11387 } 11388 } 11389 11390 // VMOV (scalar to ARM core register) 11391 // VMOV rT, rD[x] 11392 if (0x0E100B10 == (insn28 & 0x0F100F1F)) { 11393 UInt rN = (INSN(7,7) << 4) | INSN(19,16); 11394 UInt rT = INSN(15,12); 11395 UInt U = INSN(23,23); 11396 UInt opc = (INSN(22,21) << 2) | INSN(6,5); 11397 UInt index; 11398 if (rT == 15 || (isT && rT == 13)) { 11399 /* fall through */ 11400 } else { 11401 if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) { 11402 index = opc & 7; 11403 IRExpr* e = unop(U ? Iop_8Uto32 : Iop_8Sto32, 11404 binop(Iop_GetElem8x8, 11405 getDRegI64(rN), 11406 mkU8(index))); 11407 if (isT) 11408 putIRegT(rT, e, condT); 11409 else 11410 putIRegA(rT, e, condT, Ijk_Boring); 11411 DIP("vmov%s.%c8 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's', 11412 rT, rN, index); 11413 goto decode_success_vfp; 11414 } 11415 else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) { 11416 index = (opc >> 1) & 3; 11417 IRExpr* e = unop(U ? Iop_16Uto32 : Iop_16Sto32, 11418 binop(Iop_GetElem16x4, 11419 getDRegI64(rN), 11420 mkU8(index))); 11421 if (isT) 11422 putIRegT(rT, e, condT); 11423 else 11424 putIRegA(rT, e, condT, Ijk_Boring); 11425 DIP("vmov%s.%c16 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's', 11426 rT, rN, index); 11427 goto decode_success_vfp; 11428 } 11429 else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0) && U == 0) { 11430 index = (opc >> 2) & 1; 11431 IRExpr* e = binop(Iop_GetElem32x2, getDRegI64(rN), mkU8(index)); 11432 if (isT) 11433 putIRegT(rT, e, condT); 11434 else 11435 putIRegA(rT, e, condT, Ijk_Boring); 11436 DIP("vmov%s.32 r%u, d%u[%u]\n", nCC(conq), rT, rN, index); 11437 goto decode_success_vfp; 11438 } else { 11439 /* fall through */ 11440 } 11441 } 11442 } 11443 11444 // VMOV.F32 sD, #imm 11445 // FCONSTS sD, #imm 11446 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11447 && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,0)) { 11448 UInt rD = (INSN(15,12) << 1) | INSN(22,22); 11449 UInt imm8 = (INSN(19,16) << 4) | INSN(3,0); 11450 UInt b = (imm8 >> 6) & 1; 11451 UInt imm; 11452 imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,(imm8 >> 5) & 1) << 8) 11453 | ((imm8 & 0x1f) << 3); 11454 imm <<= 16; 11455 putFReg(rD, unop(Iop_ReinterpI32asF32, mkU32(imm)), condT); 11456 DIP("fconsts%s s%u #%u", nCC(conq), rD, imm8); 11457 goto decode_success_vfp; 11458 } 11459 11460 // VMOV.F64 dD, #imm 11461 // FCONSTD dD, #imm 11462 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11463 && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,1)) { 11464 UInt rD = INSN(15,12) | (INSN(22,22) << 4); 11465 UInt imm8 = (INSN(19,16) << 4) | INSN(3,0); 11466 UInt b = (imm8 >> 6) & 1; 11467 ULong imm; 11468 imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,b) << 8) 11469 | BITS8(b,b,0,0,0,0,0,0) | (imm8 & 0x3f); 11470 imm <<= 48; 11471 putDReg(rD, unop(Iop_ReinterpI64asF64, mkU64(imm)), condT); 11472 DIP("fconstd%s d%u #%u", nCC(conq), rD, imm8); 11473 goto decode_success_vfp; 11474 } 11475 11476 /* ---------------------- vdup ------------------------- */ 11477 // VDUP dD, rT 11478 // VDUP qD, rT 11479 if (BITS8(1,1,1,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,1)) 11480 && BITS4(1,0,1,1) == INSN(11,8) && INSN(6,6) == 0 && INSN(4,4) == 1) { 11481 UInt rD = (INSN(7,7) << 4) | INSN(19,16); 11482 UInt rT = INSN(15,12); 11483 UInt Q = INSN(21,21); 11484 UInt size = (INSN(22,22) << 1) | INSN(5,5); 11485 if (rT == 15 || (isT && rT == 13) || size == 3 || (Q && (rD & 1))) { 11486 /* fall through */ 11487 } else { 11488 IRExpr* e = isT ? getIRegT(rT) : getIRegA(rT); 11489 if (Q) { 11490 rD >>= 1; 11491 switch (size) { 11492 case 0: 11493 putQReg(rD, unop(Iop_Dup32x4, e), condT); 11494 break; 11495 case 1: 11496 putQReg(rD, unop(Iop_Dup16x8, unop(Iop_32to16, e)), 11497 condT); 11498 break; 11499 case 2: 11500 putQReg(rD, unop(Iop_Dup8x16, unop(Iop_32to8, e)), 11501 condT); 11502 break; 11503 default: 11504 vassert(0); 11505 } 11506 DIP("vdup.%u q%u, r%u\n", 32 / (1<<size), rD, rT); 11507 } else { 11508 switch (size) { 11509 case 0: 11510 putDRegI64(rD, unop(Iop_Dup32x2, e), condT); 11511 break; 11512 case 1: 11513 putDRegI64(rD, unop(Iop_Dup16x4, unop(Iop_32to16, e)), 11514 condT); 11515 break; 11516 case 2: 11517 putDRegI64(rD, unop(Iop_Dup8x8, unop(Iop_32to8, e)), 11518 condT); 11519 break; 11520 default: 11521 vassert(0); 11522 } 11523 DIP("vdup.%u d%u, r%u\n", 32 / (1<<size), rD, rT); 11524 } 11525 goto decode_success_vfp; 11526 } 11527 } 11528 11529 /* --------------------- f{ld,st}d --------------------- */ 11530 // FLDD, FSTD 11531 if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0)) 11532 && BITS4(1,0,1,1) == INSN(11,8)) { 11533 UInt dD = INSN(15,12) | (INSN(22,22) << 4); 11534 UInt rN = INSN(19,16); 11535 UInt offset = (insn28 & 0xFF) << 2; 11536 UInt bU = (insn28 >> 23) & 1; /* 1: +offset 0: -offset */ 11537 UInt bL = (insn28 >> 20) & 1; /* 1: load 0: store */ 11538 /* make unconditional */ 11539 if (condT != IRTemp_INVALID) { 11540 if (isT) 11541 mk_skip_over_T32_if_cond_is_false( condT ); 11542 else 11543 mk_skip_over_A32_if_cond_is_false( condT ); 11544 condT = IRTemp_INVALID; 11545 } 11546 IRTemp ea = newTemp(Ity_I32); 11547 assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32, 11548 align4if(isT ? getIRegT(rN) : getIRegA(rN), 11549 rN == 15), 11550 mkU32(offset))); 11551 if (bL) { 11552 putDReg(dD, loadLE(Ity_F64,mkexpr(ea)), IRTemp_INVALID); 11553 } else { 11554 storeLE(mkexpr(ea), getDReg(dD)); 11555 } 11556 DIP("f%sd%s d%u, [r%u, %c#%u]\n", 11557 bL ? "ld" : "st", nCC(conq), dD, rN, 11558 bU ? '+' : '-', offset); 11559 goto decode_success_vfp; 11560 } 11561 11562 /* --------------------- dp insns (D) --------------------- */ 11563 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0)) 11564 && BITS4(1,0,1,1) == INSN(11,8) 11565 && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) { 11566 UInt dM = INSN(3,0) | (INSN(5,5) << 4); /* argR */ 11567 UInt dD = INSN(15,12) | (INSN(22,22) << 4); /* dst/acc */ 11568 UInt dN = INSN(19,16) | (INSN(7,7) << 4); /* argL */ 11569 UInt bP = (insn28 >> 23) & 1; 11570 UInt bQ = (insn28 >> 21) & 1; 11571 UInt bR = (insn28 >> 20) & 1; 11572 UInt bS = (insn28 >> 6) & 1; 11573 UInt opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS; 11574 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */ 11575 switch (opc) { 11576 case BITS4(0,0,0,0): /* MAC: d + n * m */ 11577 putDReg(dD, triop(Iop_AddF64, rm, 11578 getDReg(dD), 11579 triop(Iop_MulF64, rm, getDReg(dN), 11580 getDReg(dM))), 11581 condT); 11582 DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11583 goto decode_success_vfp; 11584 case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */ 11585 putDReg(dD, triop(Iop_AddF64, rm, 11586 getDReg(dD), 11587 unop(Iop_NegF64, 11588 triop(Iop_MulF64, rm, getDReg(dN), 11589 getDReg(dM)))), 11590 condT); 11591 DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11592 goto decode_success_vfp; 11593 case BITS4(0,0,1,0): /* MSC: - d + n * m */ 11594 putDReg(dD, triop(Iop_AddF64, rm, 11595 unop(Iop_NegF64, getDReg(dD)), 11596 triop(Iop_MulF64, rm, getDReg(dN), 11597 getDReg(dM))), 11598 condT); 11599 DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11600 goto decode_success_vfp; 11601 case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */ 11602 putDReg(dD, triop(Iop_AddF64, rm, 11603 unop(Iop_NegF64, getDReg(dD)), 11604 unop(Iop_NegF64, 11605 triop(Iop_MulF64, rm, getDReg(dN), 11606 getDReg(dM)))), 11607 condT); 11608 DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11609 goto decode_success_vfp; 11610 case BITS4(0,1,0,0): /* MUL: n * m */ 11611 putDReg(dD, triop(Iop_MulF64, rm, getDReg(dN), getDReg(dM)), 11612 condT); 11613 DIP("fmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11614 goto decode_success_vfp; 11615 case BITS4(0,1,0,1): /* NMUL: - n * m */ 11616 putDReg(dD, unop(Iop_NegF64, 11617 triop(Iop_MulF64, rm, getDReg(dN), 11618 getDReg(dM))), 11619 condT); 11620 DIP("fnmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11621 goto decode_success_vfp; 11622 case BITS4(0,1,1,0): /* ADD: n + m */ 11623 putDReg(dD, triop(Iop_AddF64, rm, getDReg(dN), getDReg(dM)), 11624 condT); 11625 DIP("faddd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11626 goto decode_success_vfp; 11627 case BITS4(0,1,1,1): /* SUB: n - m */ 11628 putDReg(dD, triop(Iop_SubF64, rm, getDReg(dN), getDReg(dM)), 11629 condT); 11630 DIP("fsubd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11631 goto decode_success_vfp; 11632 case BITS4(1,0,0,0): /* DIV: n / m */ 11633 putDReg(dD, triop(Iop_DivF64, rm, getDReg(dN), getDReg(dM)), 11634 condT); 11635 DIP("fdivd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11636 goto decode_success_vfp; 11637 default: 11638 break; 11639 } 11640 } 11641 11642 /* --------------------- compares (D) --------------------- */ 11643 /* 31 27 23 19 15 11 7 3 11644 28 24 20 16 12 8 4 0 11645 FCMPD cond 1110 1D11 0100 Dd 1011 0100 Dm 11646 FCMPED cond 1110 1D11 0100 Dd 1011 1100 Dm 11647 FCMPZD cond 1110 1D11 0101 Dd 1011 0100 0000 11648 FCMPZED cond 1110 1D11 0101 Dd 1011 1100 0000 11649 Z N 11650 11651 Z=0 Compare Dd vs Dm and set FPSCR 31:28 accordingly 11652 Z=1 Compare Dd vs zero 11653 11654 N=1 generates Invalid Operation exn if either arg is any kind of NaN 11655 N=0 generates Invalid Operation exn if either arg is a signalling NaN 11656 (Not that we pay any attention to N here) 11657 */ 11658 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11659 && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 11660 && BITS4(1,0,1,1) == INSN(11,8) 11661 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11662 UInt bZ = (insn28 >> 16) & 1; 11663 UInt bN = (insn28 >> 7) & 1; 11664 UInt dD = INSN(15,12) | (INSN(22,22) << 4); 11665 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 11666 if (bZ && INSN(3,0) != 0) { 11667 /* does not decode; fall through */ 11668 } else { 11669 IRTemp argL = newTemp(Ity_F64); 11670 IRTemp argR = newTemp(Ity_F64); 11671 IRTemp irRes = newTemp(Ity_I32); 11672 assign(argL, getDReg(dD)); 11673 assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0)) : getDReg(dM)); 11674 assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR))); 11675 11676 IRTemp nzcv = IRTemp_INVALID; 11677 IRTemp oldFPSCR = newTemp(Ity_I32); 11678 IRTemp newFPSCR = newTemp(Ity_I32); 11679 11680 /* This is where the fun starts. We have to convert 'irRes' 11681 from an IR-convention return result (IRCmpF64Result) to an 11682 ARM-encoded (N,Z,C,V) group. The final result is in the 11683 bottom 4 bits of 'nzcv'. */ 11684 /* Map compare result from IR to ARM(nzcv) */ 11685 /* 11686 FP cmp result | IR | ARM(nzcv) 11687 -------------------------------- 11688 UN 0x45 0011 11689 LT 0x01 1000 11690 GT 0x00 0010 11691 EQ 0x40 0110 11692 */ 11693 nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes); 11694 11695 /* And update FPSCR accordingly */ 11696 assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32)); 11697 assign(newFPSCR, 11698 binop(Iop_Or32, 11699 binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)), 11700 binop(Iop_Shl32, mkexpr(nzcv), mkU8(28)))); 11701 11702 putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT); 11703 11704 if (bZ) { 11705 DIP("fcmpz%sd%s d%u\n", bN ? "e" : "", nCC(conq), dD); 11706 } else { 11707 DIP("fcmp%sd%s d%u, d%u\n", bN ? "e" : "", nCC(conq), dD, dM); 11708 } 11709 goto decode_success_vfp; 11710 } 11711 /* fall through */ 11712 } 11713 11714 /* --------------------- unary (D) --------------------- */ 11715 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11716 && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 11717 && BITS4(1,0,1,1) == INSN(11,8) 11718 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11719 UInt dD = INSN(15,12) | (INSN(22,22) << 4); 11720 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 11721 UInt b16 = (insn28 >> 16) & 1; 11722 UInt b7 = (insn28 >> 7) & 1; 11723 /**/ if (b16 == 0 && b7 == 0) { 11724 // FCPYD 11725 putDReg(dD, getDReg(dM), condT); 11726 DIP("fcpyd%s d%u, d%u\n", nCC(conq), dD, dM); 11727 goto decode_success_vfp; 11728 } 11729 else if (b16 == 0 && b7 == 1) { 11730 // FABSD 11731 putDReg(dD, unop(Iop_AbsF64, getDReg(dM)), condT); 11732 DIP("fabsd%s d%u, d%u\n", nCC(conq), dD, dM); 11733 goto decode_success_vfp; 11734 } 11735 else if (b16 == 1 && b7 == 0) { 11736 // FNEGD 11737 putDReg(dD, unop(Iop_NegF64, getDReg(dM)), condT); 11738 DIP("fnegd%s d%u, d%u\n", nCC(conq), dD, dM); 11739 goto decode_success_vfp; 11740 } 11741 else if (b16 == 1 && b7 == 1) { 11742 // FSQRTD 11743 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */ 11744 putDReg(dD, binop(Iop_SqrtF64, rm, getDReg(dM)), condT); 11745 DIP("fsqrtd%s d%u, d%u\n", nCC(conq), dD, dM); 11746 goto decode_success_vfp; 11747 } 11748 else 11749 vassert(0); 11750 11751 /* fall through */ 11752 } 11753 11754 /* ----------------- I <-> D conversions ----------------- */ 11755 11756 // F{S,U}ITOD dD, fM 11757 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11758 && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1)) 11759 && BITS4(1,0,1,1) == INSN(11,8) 11760 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11761 UInt bM = (insn28 >> 5) & 1; 11762 UInt fM = (INSN(3,0) << 1) | bM; 11763 UInt dD = INSN(15,12) | (INSN(22,22) << 4); 11764 UInt syned = (insn28 >> 7) & 1; 11765 if (syned) { 11766 // FSITOD 11767 putDReg(dD, unop(Iop_I32StoF64, 11768 unop(Iop_ReinterpF32asI32, getFReg(fM))), 11769 condT); 11770 DIP("fsitod%s d%u, s%u\n", nCC(conq), dD, fM); 11771 } else { 11772 // FUITOD 11773 putDReg(dD, unop(Iop_I32UtoF64, 11774 unop(Iop_ReinterpF32asI32, getFReg(fM))), 11775 condT); 11776 DIP("fuitod%s d%u, s%u\n", nCC(conq), dD, fM); 11777 } 11778 goto decode_success_vfp; 11779 } 11780 11781 // FTO{S,U}ID fD, dM 11782 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11783 && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 11784 && BITS4(1,0,1,1) == INSN(11,8) 11785 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11786 UInt bD = (insn28 >> 22) & 1; 11787 UInt fD = (INSN(15,12) << 1) | bD; 11788 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 11789 UInt bZ = (insn28 >> 7) & 1; 11790 UInt syned = (insn28 >> 16) & 1; 11791 IRTemp rmode = newTemp(Ity_I32); 11792 assign(rmode, bZ ? mkU32(Irrm_ZERO) 11793 : mkexpr(mk_get_IR_rounding_mode())); 11794 if (syned) { 11795 // FTOSID 11796 putFReg(fD, unop(Iop_ReinterpI32asF32, 11797 binop(Iop_F64toI32S, mkexpr(rmode), 11798 getDReg(dM))), 11799 condT); 11800 DIP("ftosi%sd%s s%u, d%u\n", bZ ? "z" : "", 11801 nCC(conq), fD, dM); 11802 } else { 11803 // FTOUID 11804 putFReg(fD, unop(Iop_ReinterpI32asF32, 11805 binop(Iop_F64toI32U, mkexpr(rmode), 11806 getDReg(dM))), 11807 condT); 11808 DIP("ftoui%sd%s s%u, d%u\n", bZ ? "z" : "", 11809 nCC(conq), fD, dM); 11810 } 11811 goto decode_success_vfp; 11812 } 11813 11814 /* ----------------------------------------------------------- */ 11815 /* -- VFP instructions -- single precision -- */ 11816 /* ----------------------------------------------------------- */ 11817 11818 /* --------------------- fldms, fstms --------------------- */ 11819 /* 11820 31 27 23 19 15 11 7 0 11821 P UDWL 11822 C4-98, C5-26 1 FSTMD cond 1100 1x00 Rn Fd 1010 offset 11823 C4-98, C5-28 2 FSTMDIA cond 1100 1x10 Rn Fd 1010 offset 11824 C4-98, C5-30 3 FSTMDDB cond 1101 0x10 Rn Fd 1010 offset 11825 11826 C4-40, C5-26 1 FLDMD cond 1100 1x01 Rn Fd 1010 offset 11827 C4-40, C5-26 2 FLDMIAD cond 1100 1x11 Rn Fd 1010 offset 11828 C4-40, C5-26 3 FLDMDBD cond 1101 0x11 Rn Fd 1010 offset 11829 11830 Regs transferred: F(Fd:D) .. F(Fd:d + offset) 11831 offset must not imply a reg > 15 11832 IA/DB: Rn is changed by (4 x # regs transferred) 11833 11834 case coding: 11835 1 at-Rn (access at Rn) 11836 2 ia-Rn (access at Rn, then Rn += 4n) 11837 3 db-Rn (Rn -= 4n, then access at Rn) 11838 */ 11839 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0)) 11840 && INSN(11,8) == BITS4(1,0,1,0)) { 11841 UInt bP = (insn28 >> 24) & 1; 11842 UInt bU = (insn28 >> 23) & 1; 11843 UInt bW = (insn28 >> 21) & 1; 11844 UInt bL = (insn28 >> 20) & 1; 11845 UInt bD = (insn28 >> 22) & 1; 11846 UInt offset = (insn28 >> 0) & 0xFF; 11847 UInt rN = INSN(19,16); 11848 UInt fD = (INSN(15,12) << 1) | bD; 11849 UInt nRegs = offset; 11850 UInt summary = 0; 11851 Int i; 11852 11853 /**/ if (bP == 0 && bU == 1 && bW == 0) { 11854 summary = 1; 11855 } 11856 else if (bP == 0 && bU == 1 && bW == 1) { 11857 summary = 2; 11858 } 11859 else if (bP == 1 && bU == 0 && bW == 1) { 11860 summary = 3; 11861 } 11862 else goto after_vfp_fldms_fstms; 11863 11864 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */ 11865 if (rN == 15 && (summary == 2 || summary == 3 || isT)) 11866 goto after_vfp_fldms_fstms; 11867 11868 /* offset must specify at least one register */ 11869 if (offset < 1) 11870 goto after_vfp_fldms_fstms; 11871 11872 /* can't transfer regs after S31 */ 11873 if (fD + nRegs - 1 >= 32) 11874 goto after_vfp_fldms_fstms; 11875 11876 /* Now, we can't do a conditional load or store, since that very 11877 likely will generate an exception. So we have to take a side 11878 exit at this point if the condition is false. */ 11879 if (condT != IRTemp_INVALID) { 11880 if (isT) 11881 mk_skip_over_T32_if_cond_is_false( condT ); 11882 else 11883 mk_skip_over_A32_if_cond_is_false( condT ); 11884 condT = IRTemp_INVALID; 11885 } 11886 /* Ok, now we're unconditional. Do the load or store. */ 11887 11888 /* get the old Rn value */ 11889 IRTemp rnT = newTemp(Ity_I32); 11890 assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN), 11891 rN == 15)); 11892 11893 /* make a new value for Rn, post-insn */ 11894 IRTemp rnTnew = IRTemp_INVALID; 11895 if (summary == 2 || summary == 3) { 11896 rnTnew = newTemp(Ity_I32); 11897 assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32, 11898 mkexpr(rnT), 11899 mkU32(4 * nRegs))); 11900 } 11901 11902 /* decide on the base transfer address */ 11903 IRTemp taT = newTemp(Ity_I32); 11904 assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT)); 11905 11906 /* update Rn if necessary -- in case 3, we're moving it down, so 11907 update before any memory reference, in order to keep Memcheck 11908 and V's stack-extending logic (on linux) happy */ 11909 if (summary == 3) { 11910 if (isT) 11911 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 11912 else 11913 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 11914 } 11915 11916 /* generate the transfers */ 11917 for (i = 0; i < nRegs; i++) { 11918 IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(4*i)); 11919 if (bL) { 11920 putFReg(fD + i, loadLE(Ity_F32, addr), IRTemp_INVALID); 11921 } else { 11922 storeLE(addr, getFReg(fD + i)); 11923 } 11924 } 11925 11926 /* update Rn if necessary -- in case 2, we're moving it up, so 11927 update after any memory reference, in order to keep Memcheck 11928 and V's stack-extending logic (on linux) happy */ 11929 if (summary == 2) { 11930 if (isT) 11931 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 11932 else 11933 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 11934 } 11935 11936 HChar* nm = bL==1 ? "ld" : "st"; 11937 switch (summary) { 11938 case 1: DIP("f%sms%s r%u, {s%u-s%u}\n", 11939 nm, nCC(conq), rN, fD, fD + nRegs - 1); 11940 break; 11941 case 2: DIP("f%smias%s r%u!, {s%u-s%u}\n", 11942 nm, nCC(conq), rN, fD, fD + nRegs - 1); 11943 break; 11944 case 3: DIP("f%smdbs%s r%u!, {s%u-s%u}\n", 11945 nm, nCC(conq), rN, fD, fD + nRegs - 1); 11946 break; 11947 default: vassert(0); 11948 } 11949 11950 goto decode_success_vfp; 11951 /* FIXME alignment constraints? */ 11952 } 11953 11954 after_vfp_fldms_fstms: 11955 11956 /* --------------------- fmsr, fmrs --------------------- */ 11957 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0)) 11958 && BITS4(1,0,1,0) == INSN(11,8) 11959 && BITS4(0,0,0,0) == INSN(3,0) 11960 && BITS4(0,0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) { 11961 UInt rD = INSN(15,12); 11962 UInt b7 = (insn28 >> 7) & 1; 11963 UInt fN = (INSN(19,16) << 1) | b7; 11964 UInt b20 = (insn28 >> 20) & 1; 11965 if (rD == 15) { 11966 /* fall through */ 11967 /* Let's assume that no sane person would want to do 11968 floating-point transfers to or from the program counter, 11969 and simply decline to decode the instruction. The ARM ARM 11970 doesn't seem to explicitly disallow this case, though. */ 11971 } else { 11972 if (b20) { 11973 IRExpr* res = unop(Iop_ReinterpF32asI32, getFReg(fN)); 11974 if (isT) 11975 putIRegT(rD, res, condT); 11976 else 11977 putIRegA(rD, res, condT, Ijk_Boring); 11978 DIP("fmrs%s r%u, s%u\n", nCC(conq), rD, fN); 11979 } else { 11980 putFReg(fN, unop(Iop_ReinterpI32asF32, 11981 isT ? getIRegT(rD) : getIRegA(rD)), 11982 condT); 11983 DIP("fmsr%s s%u, r%u\n", nCC(conq), fN, rD); 11984 } 11985 goto decode_success_vfp; 11986 } 11987 /* fall through */ 11988 } 11989 11990 /* --------------------- f{ld,st}s --------------------- */ 11991 // FLDS, FSTS 11992 if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0)) 11993 && BITS4(1,0,1,0) == INSN(11,8)) { 11994 UInt bD = (insn28 >> 22) & 1; 11995 UInt fD = (INSN(15,12) << 1) | bD; 11996 UInt rN = INSN(19,16); 11997 UInt offset = (insn28 & 0xFF) << 2; 11998 UInt bU = (insn28 >> 23) & 1; /* 1: +offset 0: -offset */ 11999 UInt bL = (insn28 >> 20) & 1; /* 1: load 0: store */ 12000 /* make unconditional */ 12001 if (condT != IRTemp_INVALID) { 12002 if (isT) 12003 mk_skip_over_T32_if_cond_is_false( condT ); 12004 else 12005 mk_skip_over_A32_if_cond_is_false( condT ); 12006 condT = IRTemp_INVALID; 12007 } 12008 IRTemp ea = newTemp(Ity_I32); 12009 assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32, 12010 align4if(isT ? getIRegT(rN) : getIRegA(rN), 12011 rN == 15), 12012 mkU32(offset))); 12013 if (bL) { 12014 putFReg(fD, loadLE(Ity_F32,mkexpr(ea)), IRTemp_INVALID); 12015 } else { 12016 storeLE(mkexpr(ea), getFReg(fD)); 12017 } 12018 DIP("f%ss%s s%u, [r%u, %c#%u]\n", 12019 bL ? "ld" : "st", nCC(conq), fD, rN, 12020 bU ? '+' : '-', offset); 12021 goto decode_success_vfp; 12022 } 12023 12024 /* --------------------- dp insns (F) --------------------- */ 12025 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0)) 12026 && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0)) 12027 && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) { 12028 UInt bM = (insn28 >> 5) & 1; 12029 UInt bD = (insn28 >> 22) & 1; 12030 UInt bN = (insn28 >> 7) & 1; 12031 UInt fM = (INSN(3,0) << 1) | bM; /* argR */ 12032 UInt fD = (INSN(15,12) << 1) | bD; /* dst/acc */ 12033 UInt fN = (INSN(19,16) << 1) | bN; /* argL */ 12034 UInt bP = (insn28 >> 23) & 1; 12035 UInt bQ = (insn28 >> 21) & 1; 12036 UInt bR = (insn28 >> 20) & 1; 12037 UInt bS = (insn28 >> 6) & 1; 12038 UInt opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS; 12039 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */ 12040 switch (opc) { 12041 case BITS4(0,0,0,0): /* MAC: d + n * m */ 12042 putFReg(fD, triop(Iop_AddF32, rm, 12043 getFReg(fD), 12044 triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))), 12045 condT); 12046 DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 12047 goto decode_success_vfp; 12048 case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */ 12049 putFReg(fD, triop(Iop_AddF32, rm, 12050 getFReg(fD), 12051 unop(Iop_NegF32, 12052 triop(Iop_MulF32, rm, getFReg(fN), 12053 getFReg(fM)))), 12054 condT); 12055 DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 12056 goto decode_success_vfp; 12057 case BITS4(0,0,1,0): /* MSC: - d + n * m */ 12058 putFReg(fD, triop(Iop_AddF32, rm, 12059 unop(Iop_NegF32, getFReg(fD)), 12060 triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))), 12061 condT); 12062 DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 12063 goto decode_success_vfp; 12064 case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */ 12065 putFReg(fD, triop(Iop_AddF32, rm, 12066 unop(Iop_NegF32, getFReg(fD)), 12067 unop(Iop_NegF32, 12068 triop(Iop_MulF32, rm, 12069 getFReg(fN), 12070 getFReg(fM)))), 12071 condT); 12072 DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 12073 goto decode_success_vfp; 12074 case BITS4(0,1,0,0): /* MUL: n * m */ 12075 putFReg(fD, triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM)), 12076 condT); 12077 DIP("fmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 12078 goto decode_success_vfp; 12079 case BITS4(0,1,0,1): /* NMUL: - n * m */ 12080 putFReg(fD, unop(Iop_NegF32, 12081 triop(Iop_MulF32, rm, getFReg(fN), 12082 getFReg(fM))), 12083 condT); 12084 DIP("fnmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 12085 goto decode_success_vfp; 12086 case BITS4(0,1,1,0): /* ADD: n + m */ 12087 putFReg(fD, triop(Iop_AddF32, rm, getFReg(fN), getFReg(fM)), 12088 condT); 12089 DIP("fadds%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 12090 goto decode_success_vfp; 12091 case BITS4(0,1,1,1): /* SUB: n - m */ 12092 putFReg(fD, triop(Iop_SubF32, rm, getFReg(fN), getFReg(fM)), 12093 condT); 12094 DIP("fsubs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 12095 goto decode_success_vfp; 12096 case BITS4(1,0,0,0): /* DIV: n / m */ 12097 putFReg(fD, triop(Iop_DivF32, rm, getFReg(fN), getFReg(fM)), 12098 condT); 12099 DIP("fdivs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 12100 goto decode_success_vfp; 12101 default: 12102 break; 12103 } 12104 } 12105 12106 /* --------------------- compares (S) --------------------- */ 12107 /* 31 27 23 19 15 11 7 3 12108 28 24 20 16 12 8 4 0 12109 FCMPS cond 1110 1D11 0100 Fd 1010 01M0 Fm 12110 FCMPES cond 1110 1D11 0100 Fd 1010 11M0 Fm 12111 FCMPZS cond 1110 1D11 0101 Fd 1010 0100 0000 12112 FCMPZED cond 1110 1D11 0101 Fd 1010 1100 0000 12113 Z N 12114 12115 Z=0 Compare Fd:D vs Fm:M and set FPSCR 31:28 accordingly 12116 Z=1 Compare Fd:D vs zero 12117 12118 N=1 generates Invalid Operation exn if either arg is any kind of NaN 12119 N=0 generates Invalid Operation exn if either arg is a signalling NaN 12120 (Not that we pay any attention to N here) 12121 */ 12122 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 12123 && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 12124 && BITS4(1,0,1,0) == INSN(11,8) 12125 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 12126 UInt bZ = (insn28 >> 16) & 1; 12127 UInt bN = (insn28 >> 7) & 1; 12128 UInt bD = (insn28 >> 22) & 1; 12129 UInt bM = (insn28 >> 5) & 1; 12130 UInt fD = (INSN(15,12) << 1) | bD; 12131 UInt fM = (INSN(3,0) << 1) | bM; 12132 if (bZ && (INSN(3,0) != 0 || (INSN(7,4) & 3) != 0)) { 12133 /* does not decode; fall through */ 12134 } else { 12135 IRTemp argL = newTemp(Ity_F64); 12136 IRTemp argR = newTemp(Ity_F64); 12137 IRTemp irRes = newTemp(Ity_I32); 12138 12139 assign(argL, unop(Iop_F32toF64, getFReg(fD))); 12140 assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0)) 12141 : unop(Iop_F32toF64, getFReg(fM))); 12142 assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR))); 12143 12144 IRTemp nzcv = IRTemp_INVALID; 12145 IRTemp oldFPSCR = newTemp(Ity_I32); 12146 IRTemp newFPSCR = newTemp(Ity_I32); 12147 12148 /* This is where the fun starts. We have to convert 'irRes' 12149 from an IR-convention return result (IRCmpF64Result) to an 12150 ARM-encoded (N,Z,C,V) group. The final result is in the 12151 bottom 4 bits of 'nzcv'. */ 12152 /* Map compare result from IR to ARM(nzcv) */ 12153 /* 12154 FP cmp result | IR | ARM(nzcv) 12155 -------------------------------- 12156 UN 0x45 0011 12157 LT 0x01 1000 12158 GT 0x00 0010 12159 EQ 0x40 0110 12160 */ 12161 nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes); 12162 12163 /* And update FPSCR accordingly */ 12164 assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32)); 12165 assign(newFPSCR, 12166 binop(Iop_Or32, 12167 binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)), 12168 binop(Iop_Shl32, mkexpr(nzcv), mkU8(28)))); 12169 12170 putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT); 12171 12172 if (bZ) { 12173 DIP("fcmpz%ss%s s%u\n", bN ? "e" : "", nCC(conq), fD); 12174 } else { 12175 DIP("fcmp%ss%s s%u, s%u\n", bN ? "e" : "", 12176 nCC(conq), fD, fM); 12177 } 12178 goto decode_success_vfp; 12179 } 12180 /* fall through */ 12181 } 12182 12183 /* --------------------- unary (S) --------------------- */ 12184 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 12185 && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 12186 && BITS4(1,0,1,0) == INSN(11,8) 12187 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 12188 UInt bD = (insn28 >> 22) & 1; 12189 UInt bM = (insn28 >> 5) & 1; 12190 UInt fD = (INSN(15,12) << 1) | bD; 12191 UInt fM = (INSN(3,0) << 1) | bM; 12192 UInt b16 = (insn28 >> 16) & 1; 12193 UInt b7 = (insn28 >> 7) & 1; 12194 /**/ if (b16 == 0 && b7 == 0) { 12195 // FCPYS 12196 putFReg(fD, getFReg(fM), condT); 12197 DIP("fcpys%s s%u, s%u\n", nCC(conq), fD, fM); 12198 goto decode_success_vfp; 12199 } 12200 else if (b16 == 0 && b7 == 1) { 12201 // FABSS 12202 putFReg(fD, unop(Iop_AbsF32, getFReg(fM)), condT); 12203 DIP("fabss%s s%u, s%u\n", nCC(conq), fD, fM); 12204 goto decode_success_vfp; 12205 } 12206 else if (b16 == 1 && b7 == 0) { 12207 // FNEGS 12208 putFReg(fD, unop(Iop_NegF32, getFReg(fM)), condT); 12209 DIP("fnegs%s s%u, s%u\n", nCC(conq), fD, fM); 12210 goto decode_success_vfp; 12211 } 12212 else if (b16 == 1 && b7 == 1) { 12213 // FSQRTS 12214 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */ 12215 putFReg(fD, binop(Iop_SqrtF32, rm, getFReg(fM)), condT); 12216 DIP("fsqrts%s s%u, s%u\n", nCC(conq), fD, fM); 12217 goto decode_success_vfp; 12218 } 12219 else 12220 vassert(0); 12221 12222 /* fall through */ 12223 } 12224 12225 /* ----------------- I <-> S conversions ----------------- */ 12226 12227 // F{S,U}ITOS fD, fM 12228 /* These are more complex than FSITOD/FUITOD. In the D cases, a 32 12229 bit int will always fit within the 53 bit mantissa, so there's 12230 no possibility of a loss of precision, but that's obviously not 12231 the case here. Hence this case possibly requires rounding, and 12232 so it drags in the current rounding mode. */ 12233 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 12234 && BITS4(1,0,0,0) == INSN(19,16) 12235 && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0)) 12236 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 12237 UInt bM = (insn28 >> 5) & 1; 12238 UInt bD = (insn28 >> 22) & 1; 12239 UInt fM = (INSN(3,0) << 1) | bM; 12240 UInt fD = (INSN(15,12) << 1) | bD; 12241 UInt syned = (insn28 >> 7) & 1; 12242 IRTemp rmode = newTemp(Ity_I32); 12243 assign(rmode, mkexpr(mk_get_IR_rounding_mode())); 12244 if (syned) { 12245 // FSITOS 12246 putFReg(fD, binop(Iop_F64toF32, 12247 mkexpr(rmode), 12248 unop(Iop_I32StoF64, 12249 unop(Iop_ReinterpF32asI32, getFReg(fM)))), 12250 condT); 12251 DIP("fsitos%s s%u, s%u\n", nCC(conq), fD, fM); 12252 } else { 12253 // FUITOS 12254 putFReg(fD, binop(Iop_F64toF32, 12255 mkexpr(rmode), 12256 unop(Iop_I32UtoF64, 12257 unop(Iop_ReinterpF32asI32, getFReg(fM)))), 12258 condT); 12259 DIP("fuitos%s s%u, s%u\n", nCC(conq), fD, fM); 12260 } 12261 goto decode_success_vfp; 12262 } 12263 12264 // FTO{S,U}IS fD, fM 12265 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 12266 && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 12267 && BITS4(1,0,1,0) == INSN(11,8) 12268 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 12269 UInt bM = (insn28 >> 5) & 1; 12270 UInt bD = (insn28 >> 22) & 1; 12271 UInt fD = (INSN(15,12) << 1) | bD; 12272 UInt fM = (INSN(3,0) << 1) | bM; 12273 UInt bZ = (insn28 >> 7) & 1; 12274 UInt syned = (insn28 >> 16) & 1; 12275 IRTemp rmode = newTemp(Ity_I32); 12276 assign(rmode, bZ ? mkU32(Irrm_ZERO) 12277 : mkexpr(mk_get_IR_rounding_mode())); 12278 if (syned) { 12279 // FTOSIS 12280 putFReg(fD, unop(Iop_ReinterpI32asF32, 12281 binop(Iop_F64toI32S, mkexpr(rmode), 12282 unop(Iop_F32toF64, getFReg(fM)))), 12283 condT); 12284 DIP("ftosi%ss%s s%u, d%u\n", bZ ? "z" : "", 12285 nCC(conq), fD, fM); 12286 goto decode_success_vfp; 12287 } else { 12288 // FTOUIS 12289 putFReg(fD, unop(Iop_ReinterpI32asF32, 12290 binop(Iop_F64toI32U, mkexpr(rmode), 12291 unop(Iop_F32toF64, getFReg(fM)))), 12292 condT); 12293 DIP("ftoui%ss%s s%u, d%u\n", bZ ? "z" : "", 12294 nCC(conq), fD, fM); 12295 goto decode_success_vfp; 12296 } 12297 } 12298 12299 /* ----------------- S <-> D conversions ----------------- */ 12300 12301 // FCVTDS 12302 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 12303 && BITS4(0,1,1,1) == INSN(19,16) 12304 && BITS4(1,0,1,0) == INSN(11,8) 12305 && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) { 12306 UInt dD = INSN(15,12) | (INSN(22,22) << 4); 12307 UInt bM = (insn28 >> 5) & 1; 12308 UInt fM = (INSN(3,0) << 1) | bM; 12309 putDReg(dD, unop(Iop_F32toF64, getFReg(fM)), condT); 12310 DIP("fcvtds%s d%u, s%u\n", nCC(conq), dD, fM); 12311 goto decode_success_vfp; 12312 } 12313 12314 // FCVTSD 12315 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 12316 && BITS4(0,1,1,1) == INSN(19,16) 12317 && BITS4(1,0,1,1) == INSN(11,8) 12318 && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) { 12319 UInt bD = (insn28 >> 22) & 1; 12320 UInt fD = (INSN(15,12) << 1) | bD; 12321 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 12322 IRTemp rmode = newTemp(Ity_I32); 12323 assign(rmode, mkexpr(mk_get_IR_rounding_mode())); 12324 putFReg(fD, binop(Iop_F64toF32, mkexpr(rmode), getDReg(dM)), 12325 condT); 12326 DIP("fcvtsd%s s%u, d%u\n", nCC(conq), fD, dM); 12327 goto decode_success_vfp; 12328 } 12329 12330 /* --------------- VCVT fixed<->floating, VFP --------------- */ 12331 /* 31 27 23 19 15 11 7 3 12332 28 24 20 16 12 8 4 0 12333 12334 cond 1110 1D11 1p1U Vd 101f x1i0 imm4 12335 12336 VCVT<c>.<Td>.F64 <Dd>, <Dd>, #fbits 12337 VCVT<c>.<Td>.F32 <Dd>, <Dd>, #fbits 12338 VCVT<c>.F64.<Td> <Dd>, <Dd>, #fbits 12339 VCVT<c>.F32.<Td> <Dd>, <Dd>, #fbits 12340 are of this form. We only handle a subset of the cases though. 12341 */ 12342 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 12343 && BITS4(1,0,1,0) == (INSN(19,16) & BITS4(1,0,1,0)) 12344 && BITS3(1,0,1) == INSN(11,9) 12345 && BITS3(1,0,0) == (INSN(6,4) & BITS3(1,0,1))) { 12346 UInt bD = INSN(22,22); 12347 UInt bOP = INSN(18,18); 12348 UInt bU = INSN(16,16); 12349 UInt Vd = INSN(15,12); 12350 UInt bSF = INSN(8,8); 12351 UInt bSX = INSN(7,7); 12352 UInt bI = INSN(5,5); 12353 UInt imm4 = INSN(3,0); 12354 Bool to_fixed = bOP == 1; 12355 Bool dp_op = bSF == 1; 12356 Bool unsyned = bU == 1; 12357 UInt size = bSX == 0 ? 16 : 32; 12358 Int frac_bits = size - ((imm4 << 1) | bI); 12359 UInt d = dp_op ? ((bD << 4) | Vd) : ((Vd << 1) | bD); 12360 if (frac_bits >= 1 && frac_bits <= 32 && !to_fixed && size == 32) { 12361 /* dp_op == 0 : VCVT.F32.{S,U}32 S[d], S[d], #frac_bits */ 12362 /* dp_op == 1 : VCVT.F64.{S,U}32 D[d], D[d], #frac_bits */ 12363 /* This generates really horrible code. We could potentially 12364 do much better. */ 12365 IRTemp rmode = newTemp(Ity_I32); 12366 assign(rmode, mkU32(Irrm_NEAREST)); // rmode that this insn is defd to use 12367 IRTemp src32 = newTemp(Ity_I32); 12368 if (dp_op == 0) { 12369 assign(src32, unop(Iop_ReinterpF32asI32, getFReg(d))); 12370 } else { 12371 /* Example code sequence of using vcvt.f64.s32. The s32 value is 12372 initialized in s14 but loaded via d7 (s14 is the low half of 12373 d7), so we need to decode the register using getDReg instead of 12374 getFReg. Since the conversion size is from s32 to f64, we also 12375 need to explicitly extract the low half of i64 here. 12376 12377 81a0: ee07 2a10 vmov s14, r2 12378 81a4: eeba 7bef vcvt.f64.s32 d7, d7, #1 12379 */ 12380 IRTemp src64 = newTemp(Ity_I64); 12381 assign(src64, unop(Iop_ReinterpF64asI64, getDReg(d))); 12382 assign(src32, unop(Iop_64to32, mkexpr(src64))); 12383 } 12384 IRExpr* as_F64 = unop( unsyned ? Iop_I32UtoF64 : Iop_I32StoF64, 12385 mkexpr(src32 ) ); 12386 IRTemp scale = newTemp(Ity_F64); 12387 assign(scale, unop(Iop_I32UtoF64, mkU32( 1 << (frac_bits-1) ))); 12388 IRExpr* rm = mkU32(Irrm_NEAREST); 12389 IRExpr* resF64 = triop(Iop_DivF64, 12390 rm, as_F64, 12391 triop(Iop_AddF64, rm, mkexpr(scale), mkexpr(scale))); 12392 if (dp_op == 0) { 12393 IRExpr* resF32 = binop(Iop_F64toF32, mkexpr(rmode), resF64); 12394 putFReg(d, resF32, condT); 12395 DIP("vcvt.f32.%c32, s%u, s%u, #%d\n", 12396 unsyned ? 'u' : 's', d, d, frac_bits); 12397 } else { 12398 putDReg(d, resF64, condT); 12399 DIP("vcvt.f64.%c32, d%u, d%u, #%d\n", 12400 unsyned ? 'u' : 's', d, d, frac_bits); 12401 } 12402 goto decode_success_vfp; 12403 } 12404 /* fall through */ 12405 } 12406 12407 /* FAILURE */ 12408 return False; 12409 12410 decode_success_vfp: 12411 /* Check that any accepted insn really is a CP10 or CP11 insn, iow, 12412 assert that we aren't accepting, in this fn, insns that actually 12413 should be handled somewhere else. */ 12414 vassert(INSN(11,9) == BITS3(1,0,1)); // 11:8 = 1010 or 1011 12415 return True; 12416 12417 # undef INSN 12418 } 12419 12420 12421 /*------------------------------------------------------------*/ 12422 /*--- Instructions in NV (never) space ---*/ 12423 /*------------------------------------------------------------*/ 12424 12425 /* ARM only */ 12426 /* Translate a NV space instruction. If successful, returns True and 12427 *dres may or may not be updated. If failure, returns False and 12428 doesn't change *dres nor create any IR. 12429 12430 Note that all NEON instructions (in ARM mode) are handled through 12431 here, since they are all in NV space. 12432 */ 12433 static Bool decode_NV_instruction ( /*MOD*/DisResult* dres, 12434 VexArchInfo* archinfo, 12435 UInt insn ) 12436 { 12437 # define INSN(_bMax,_bMin) SLICE_UInt(insn, (_bMax), (_bMin)) 12438 # define INSN_COND SLICE_UInt(insn, 31, 28) 12439 12440 HChar dis_buf[128]; 12441 12442 // Should only be called for NV instructions 12443 vassert(BITS4(1,1,1,1) == INSN_COND); 12444 12445 /* ------------------------ pld ------------------------ */ 12446 if (BITS8(0,1,0,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) 12447 && BITS4(1,1,1,1) == INSN(15,12)) { 12448 UInt rN = INSN(19,16); 12449 UInt imm12 = INSN(11,0); 12450 UInt bU = INSN(23,23); 12451 DIP("pld [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12); 12452 return True; 12453 } 12454 12455 if (BITS8(0,1,1,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) 12456 && BITS4(1,1,1,1) == INSN(15,12) 12457 && 0 == INSN(4,4)) { 12458 UInt rN = INSN(19,16); 12459 UInt rM = INSN(3,0); 12460 UInt imm5 = INSN(11,7); 12461 UInt sh2 = INSN(6,5); 12462 UInt bU = INSN(23,23); 12463 if (rM != 15) { 12464 IRExpr* eaE = mk_EA_reg_plusminus_shifted_reg(rN, bU, rM, 12465 sh2, imm5, dis_buf); 12466 IRTemp eaT = newTemp(Ity_I32); 12467 /* Bind eaE to a temp merely for debugging-vex purposes, so we 12468 can check it's a plausible decoding. It will get removed 12469 by iropt a little later on. */ 12470 vassert(eaE); 12471 assign(eaT, eaE); 12472 DIP("pld %s\n", dis_buf); 12473 return True; 12474 } 12475 /* fall through */ 12476 } 12477 12478 /* ------------------------ pli ------------------------ */ 12479 if (BITS8(0,1,0,0, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) 12480 && BITS4(1,1,1,1) == INSN(15,12)) { 12481 UInt rN = INSN(19,16); 12482 UInt imm12 = INSN(11,0); 12483 UInt bU = INSN(23,23); 12484 DIP("pli [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12); 12485 return True; 12486 } 12487 12488 /* --------------------- Interworking branches --------------------- */ 12489 12490 // BLX (1), viz, unconditional branch and link to R15+simm24 12491 // and set CPSR.T = 1, that is, switch to Thumb mode 12492 if (INSN(31,25) == BITS7(1,1,1,1,1,0,1)) { 12493 UInt bitH = INSN(24,24); 12494 Int uimm24 = INSN(23,0); 12495 Int simm24 = (((uimm24 << 8) >> 8) << 2) + (bitH << 1); 12496 /* Now this is a bit tricky. Since we're decoding an ARM insn, 12497 it is implies that CPSR.T == 0. Hence the current insn's 12498 address is guaranteed to be of the form X--(30)--X00. So, no 12499 need to mask any bits off it. But need to set the lowest bit 12500 to 1 to denote we're in Thumb mode after this, since 12501 guest_R15T has CPSR.T as the lowest bit. And we can't chase 12502 into the call, so end the block at this point. */ 12503 UInt dst = guest_R15_curr_instr_notENC + 8 + (simm24 | 1); 12504 putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4), 12505 IRTemp_INVALID/*because AL*/, Ijk_Boring ); 12506 llPutIReg(15, mkU32(dst)); 12507 dres->jk_StopHere = Ijk_Call; 12508 dres->whatNext = Dis_StopHere; 12509 DIP("blx 0x%x (and switch to Thumb mode)\n", dst - 1); 12510 return True; 12511 } 12512 12513 /* ------------------- v7 barrier insns ------------------- */ 12514 switch (insn) { 12515 case 0xF57FF06F: /* ISB */ 12516 stmt( IRStmt_MBE(Imbe_Fence) ); 12517 DIP("ISB\n"); 12518 return True; 12519 case 0xF57FF04F: /* DSB sy */ 12520 case 0xF57FF04E: /* DSB st */ 12521 case 0xF57FF04B: /* DSB ish */ 12522 case 0xF57FF04A: /* DSB ishst */ 12523 case 0xF57FF047: /* DSB nsh */ 12524 case 0xF57FF046: /* DSB nshst */ 12525 case 0xF57FF043: /* DSB osh */ 12526 case 0xF57FF042: /* DSB oshst */ 12527 stmt( IRStmt_MBE(Imbe_Fence) ); 12528 DIP("DSB\n"); 12529 return True; 12530 case 0xF57FF05F: /* DMB sy */ 12531 case 0xF57FF05E: /* DMB st */ 12532 case 0xF57FF05B: /* DMB ish */ 12533 case 0xF57FF05A: /* DMB ishst */ 12534 case 0xF57FF057: /* DMB nsh */ 12535 case 0xF57FF056: /* DMB nshst */ 12536 case 0xF57FF053: /* DMB osh */ 12537 case 0xF57FF052: /* DMB oshst */ 12538 stmt( IRStmt_MBE(Imbe_Fence) ); 12539 DIP("DMB\n"); 12540 return True; 12541 default: 12542 break; 12543 } 12544 12545 /* ------------------- CLREX ------------------ */ 12546 if (insn == 0xF57FF01F) { 12547 /* AFAICS, this simply cancels a (all?) reservations made by a 12548 (any?) preceding LDREX(es). Arrange to hand it through to 12549 the back end. */ 12550 stmt( IRStmt_MBE(Imbe_CancelReservation) ); 12551 DIP("clrex\n"); 12552 return True; 12553 } 12554 12555 /* ------------------- NEON ------------------- */ 12556 if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) { 12557 Bool ok_neon = decode_NEON_instruction( 12558 dres, insn, IRTemp_INVALID/*unconditional*/, 12559 False/*!isT*/ 12560 ); 12561 if (ok_neon) 12562 return True; 12563 } 12564 12565 // unrecognised 12566 return False; 12567 12568 # undef INSN_COND 12569 # undef INSN 12570 } 12571 12572 12573 /*------------------------------------------------------------*/ 12574 /*--- Disassemble a single ARM instruction ---*/ 12575 /*------------------------------------------------------------*/ 12576 12577 /* Disassemble a single ARM instruction into IR. The instruction is 12578 located in host memory at guest_instr, and has (decoded) guest IP 12579 of guest_R15_curr_instr_notENC, which will have been set before the 12580 call here. */ 12581 12582 static 12583 DisResult disInstr_ARM_WRK ( 12584 Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ), 12585 Bool resteerCisOk, 12586 void* callback_opaque, 12587 UChar* guest_instr, 12588 VexArchInfo* archinfo, 12589 VexAbiInfo* abiinfo 12590 ) 12591 { 12592 // A macro to fish bits out of 'insn'. 12593 # define INSN(_bMax,_bMin) SLICE_UInt(insn, (_bMax), (_bMin)) 12594 # define INSN_COND SLICE_UInt(insn, 31, 28) 12595 12596 DisResult dres; 12597 UInt insn; 12598 //Bool allow_VFP = False; 12599 //UInt hwcaps = archinfo->hwcaps; 12600 IRTemp condT; /* :: Ity_I32 */ 12601 UInt summary; 12602 HChar dis_buf[128]; // big enough to hold LDMIA etc text 12603 12604 /* What insn variants are we supporting today? */ 12605 //allow_VFP = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP)); 12606 // etc etc 12607 12608 /* Set result defaults. */ 12609 dres.whatNext = Dis_Continue; 12610 dres.len = 4; 12611 dres.continueAt = 0; 12612 dres.jk_StopHere = Ijk_INVALID; 12613 12614 /* Set default actions for post-insn handling of writes to r15, if 12615 required. */ 12616 r15written = False; 12617 r15guard = IRTemp_INVALID; /* unconditional */ 12618 r15kind = Ijk_Boring; 12619 12620 /* At least this is simple on ARM: insns are all 4 bytes long, and 12621 4-aligned. So just fish the whole thing out of memory right now 12622 and have done. */ 12623 insn = getUIntLittleEndianly( guest_instr ); 12624 12625 if (0) vex_printf("insn: 0x%x\n", insn); 12626 12627 DIP("\t(arm) 0x%x: ", (UInt)guest_R15_curr_instr_notENC); 12628 12629 vassert(0 == (guest_R15_curr_instr_notENC & 3)); 12630 12631 /* ----------------------------------------------------------- */ 12632 12633 /* Spot "Special" instructions (see comment at top of file). */ 12634 { 12635 UChar* code = (UChar*)guest_instr; 12636 /* Spot the 16-byte preamble: 12637 12638 e1a0c1ec mov r12, r12, ROR #3 12639 e1a0c6ec mov r12, r12, ROR #13 12640 e1a0ceec mov r12, r12, ROR #29 12641 e1a0c9ec mov r12, r12, ROR #19 12642 */ 12643 UInt word1 = 0xE1A0C1EC; 12644 UInt word2 = 0xE1A0C6EC; 12645 UInt word3 = 0xE1A0CEEC; 12646 UInt word4 = 0xE1A0C9EC; 12647 if (getUIntLittleEndianly(code+ 0) == word1 && 12648 getUIntLittleEndianly(code+ 4) == word2 && 12649 getUIntLittleEndianly(code+ 8) == word3 && 12650 getUIntLittleEndianly(code+12) == word4) { 12651 /* Got a "Special" instruction preamble. Which one is it? */ 12652 if (getUIntLittleEndianly(code+16) == 0xE18AA00A 12653 /* orr r10,r10,r10 */) { 12654 /* R3 = client_request ( R4 ) */ 12655 DIP("r3 = client_request ( %%r4 )\n"); 12656 llPutIReg(15, mkU32( guest_R15_curr_instr_notENC + 20 )); 12657 dres.jk_StopHere = Ijk_ClientReq; 12658 dres.whatNext = Dis_StopHere; 12659 goto decode_success; 12660 } 12661 else 12662 if (getUIntLittleEndianly(code+16) == 0xE18BB00B 12663 /* orr r11,r11,r11 */) { 12664 /* R3 = guest_NRADDR */ 12665 DIP("r3 = guest_NRADDR\n"); 12666 dres.len = 20; 12667 llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 )); 12668 goto decode_success; 12669 } 12670 else 12671 if (getUIntLittleEndianly(code+16) == 0xE18CC00C 12672 /* orr r12,r12,r12 */) { 12673 /* branch-and-link-to-noredir R4 */ 12674 DIP("branch-and-link-to-noredir r4\n"); 12675 llPutIReg(14, mkU32( guest_R15_curr_instr_notENC + 20) ); 12676 llPutIReg(15, llGetIReg(4)); 12677 dres.jk_StopHere = Ijk_NoRedir; 12678 dres.whatNext = Dis_StopHere; 12679 goto decode_success; 12680 } 12681 /* We don't know what it is. Set opc1/opc2 so decode_failure 12682 can print the insn following the Special-insn preamble. */ 12683 insn = getUIntLittleEndianly(code+16); 12684 goto decode_failure; 12685 /*NOTREACHED*/ 12686 } 12687 12688 } 12689 12690 /* ----------------------------------------------------------- */ 12691 12692 /* Main ARM instruction decoder starts here. */ 12693 12694 /* Deal with the condition. Strategy is to merely generate a 12695 condition temporary at this point (or IRTemp_INVALID, meaning 12696 unconditional). We leave it to lower-level instruction decoders 12697 to decide whether they can generate straight-line code, or 12698 whether they must generate a side exit before the instruction. 12699 condT :: Ity_I32 and is always either zero or one. */ 12700 condT = IRTemp_INVALID; 12701 switch ( (ARMCondcode)INSN_COND ) { 12702 case ARMCondNV: { 12703 // Illegal instruction prior to v5 (see ARM ARM A3-5), but 12704 // some cases are acceptable 12705 Bool ok = decode_NV_instruction(&dres, archinfo, insn); 12706 if (ok) 12707 goto decode_success; 12708 else 12709 goto decode_failure; 12710 } 12711 case ARMCondAL: // Always executed 12712 break; 12713 case ARMCondEQ: case ARMCondNE: case ARMCondHS: case ARMCondLO: 12714 case ARMCondMI: case ARMCondPL: case ARMCondVS: case ARMCondVC: 12715 case ARMCondHI: case ARMCondLS: case ARMCondGE: case ARMCondLT: 12716 case ARMCondGT: case ARMCondLE: 12717 condT = newTemp(Ity_I32); 12718 assign( condT, mk_armg_calculate_condition( INSN_COND )); 12719 break; 12720 } 12721 12722 /* ----------------------------------------------------------- */ 12723 /* -- ARMv5 integer instructions -- */ 12724 /* ----------------------------------------------------------- */ 12725 12726 /* ---------------- Data processing ops ------------------- */ 12727 12728 if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) 12729 && !(INSN(25,25) == 0 && INSN(7,7) == 1 && INSN(4,4) == 1)) { 12730 IRTemp shop = IRTemp_INVALID; /* shifter operand */ 12731 IRTemp shco = IRTemp_INVALID; /* shifter carry out */ 12732 UInt rD = (insn >> 12) & 0xF; /* 15:12 */ 12733 UInt rN = (insn >> 16) & 0xF; /* 19:16 */ 12734 UInt bitS = (insn >> 20) & 1; /* 20:20 */ 12735 IRTemp rNt = IRTemp_INVALID; 12736 IRTemp res = IRTemp_INVALID; 12737 IRTemp oldV = IRTemp_INVALID; 12738 IRTemp oldC = IRTemp_INVALID; 12739 HChar* name = NULL; 12740 IROp op = Iop_INVALID; 12741 Bool ok; 12742 12743 switch (INSN(24,21)) { 12744 12745 /* --------- ADD, SUB, AND, OR --------- */ 12746 case BITS4(0,1,0,0): /* ADD: Rd = Rn + shifter_operand */ 12747 name = "add"; op = Iop_Add32; goto rd_eq_rn_op_SO; 12748 case BITS4(0,0,1,0): /* SUB: Rd = Rn - shifter_operand */ 12749 name = "sub"; op = Iop_Sub32; goto rd_eq_rn_op_SO; 12750 case BITS4(0,0,1,1): /* RSB: Rd = shifter_operand - Rn */ 12751 name = "rsb"; op = Iop_Sub32; goto rd_eq_rn_op_SO; 12752 case BITS4(0,0,0,0): /* AND: Rd = Rn & shifter_operand */ 12753 name = "and"; op = Iop_And32; goto rd_eq_rn_op_SO; 12754 case BITS4(1,1,0,0): /* OR: Rd = Rn | shifter_operand */ 12755 name = "orr"; op = Iop_Or32; goto rd_eq_rn_op_SO; 12756 case BITS4(0,0,0,1): /* EOR: Rd = Rn ^ shifter_operand */ 12757 name = "eor"; op = Iop_Xor32; goto rd_eq_rn_op_SO; 12758 case BITS4(1,1,1,0): /* BIC: Rd = Rn & ~shifter_operand */ 12759 name = "bic"; op = Iop_And32; goto rd_eq_rn_op_SO; 12760 rd_eq_rn_op_SO: { 12761 Bool isRSB = False; 12762 Bool isBIC = False; 12763 switch (INSN(24,21)) { 12764 case BITS4(0,0,1,1): 12765 vassert(op == Iop_Sub32); isRSB = True; break; 12766 case BITS4(1,1,1,0): 12767 vassert(op == Iop_And32); isBIC = True; break; 12768 default: 12769 break; 12770 } 12771 rNt = newTemp(Ity_I32); 12772 assign(rNt, getIRegA(rN)); 12773 ok = mk_shifter_operand( 12774 INSN(25,25), INSN(11,0), 12775 &shop, bitS ? &shco : NULL, dis_buf 12776 ); 12777 if (!ok) 12778 break; 12779 res = newTemp(Ity_I32); 12780 // compute the main result 12781 if (isRSB) { 12782 // reverse-subtract: shifter_operand - Rn 12783 vassert(op == Iop_Sub32); 12784 assign(res, binop(op, mkexpr(shop), mkexpr(rNt)) ); 12785 } else if (isBIC) { 12786 // andn: shifter_operand & ~Rn 12787 vassert(op == Iop_And32); 12788 assign(res, binop(op, mkexpr(rNt), 12789 unop(Iop_Not32, mkexpr(shop))) ); 12790 } else { 12791 // normal: Rn op shifter_operand 12792 assign(res, binop(op, mkexpr(rNt), mkexpr(shop)) ); 12793 } 12794 // but don't commit it until after we've finished 12795 // all necessary reads from the guest state 12796 if (bitS 12797 && (op == Iop_And32 || op == Iop_Or32 || op == Iop_Xor32)) { 12798 oldV = newTemp(Ity_I32); 12799 assign( oldV, mk_armg_calculate_flag_v() ); 12800 } 12801 // can't safely read guest state after here 12802 // now safe to put the main result 12803 putIRegA( rD, mkexpr(res), condT, Ijk_Boring ); 12804 // XXXX!! not safe to read any guest state after 12805 // this point (I think the code below doesn't do that). 12806 if (!bitS) 12807 vassert(shco == IRTemp_INVALID); 12808 /* Update the flags thunk if necessary */ 12809 if (bitS) { 12810 vassert(shco != IRTemp_INVALID); 12811 switch (op) { 12812 case Iop_Add32: 12813 setFlags_D1_D2( ARMG_CC_OP_ADD, rNt, shop, condT ); 12814 break; 12815 case Iop_Sub32: 12816 if (isRSB) { 12817 setFlags_D1_D2( ARMG_CC_OP_SUB, shop, rNt, condT ); 12818 } else { 12819 setFlags_D1_D2( ARMG_CC_OP_SUB, rNt, shop, condT ); 12820 } 12821 break; 12822 case Iop_And32: /* BIC and AND set the flags the same */ 12823 case Iop_Or32: 12824 case Iop_Xor32: 12825 // oldV has been read just above 12826 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, 12827 res, shco, oldV, condT ); 12828 break; 12829 default: 12830 vassert(0); 12831 } 12832 } 12833 DIP("%s%s%s r%u, r%u, %s\n", 12834 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf ); 12835 goto decode_success; 12836 } 12837 12838 /* --------- MOV, MVN --------- */ 12839 case BITS4(1,1,0,1): /* MOV: Rd = shifter_operand */ 12840 case BITS4(1,1,1,1): { /* MVN: Rd = not(shifter_operand) */ 12841 Bool isMVN = INSN(24,21) == BITS4(1,1,1,1); 12842 IRTemp jk = Ijk_Boring; 12843 if (rN != 0) 12844 break; /* rN must be zero */ 12845 ok = mk_shifter_operand( 12846 INSN(25,25), INSN(11,0), 12847 &shop, bitS ? &shco : NULL, dis_buf 12848 ); 12849 if (!ok) 12850 break; 12851 res = newTemp(Ity_I32); 12852 assign( res, isMVN ? unop(Iop_Not32, mkexpr(shop)) 12853 : mkexpr(shop) ); 12854 if (bitS) { 12855 vassert(shco != IRTemp_INVALID); 12856 oldV = newTemp(Ity_I32); 12857 assign( oldV, mk_armg_calculate_flag_v() ); 12858 } else { 12859 vassert(shco == IRTemp_INVALID); 12860 } 12861 /* According to the Cortex A8 TRM Sec. 5.2.1, MOV PC, r14 is a 12862 return for purposes of branch prediction. */ 12863 if (!isMVN && INSN(11,0) == 14) { 12864 jk = Ijk_Ret; 12865 } 12866 // can't safely read guest state after here 12867 putIRegA( rD, mkexpr(res), condT, jk ); 12868 /* Update the flags thunk if necessary */ 12869 if (bitS) { 12870 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, 12871 res, shco, oldV, condT ); 12872 } 12873 DIP("%s%s%s r%u, %s\n", 12874 isMVN ? "mvn" : "mov", 12875 nCC(INSN_COND), bitS ? "s" : "", rD, dis_buf ); 12876 goto decode_success; 12877 } 12878 12879 /* --------- CMP --------- */ 12880 case BITS4(1,0,1,0): /* CMP: (void) Rn - shifter_operand */ 12881 case BITS4(1,0,1,1): { /* CMN: (void) Rn + shifter_operand */ 12882 Bool isCMN = INSN(24,21) == BITS4(1,0,1,1); 12883 if (rD != 0) 12884 break; /* rD must be zero */ 12885 if (bitS == 0) 12886 break; /* if S (bit 20) is not set, it's not CMP/CMN */ 12887 rNt = newTemp(Ity_I32); 12888 assign(rNt, getIRegA(rN)); 12889 ok = mk_shifter_operand( 12890 INSN(25,25), INSN(11,0), 12891 &shop, NULL, dis_buf 12892 ); 12893 if (!ok) 12894 break; 12895 // can't safely read guest state after here 12896 /* Update the flags thunk. */ 12897 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB, 12898 rNt, shop, condT ); 12899 DIP("%s%s r%u, %s\n", 12900 isCMN ? "cmn" : "cmp", 12901 nCC(INSN_COND), rN, dis_buf ); 12902 goto decode_success; 12903 } 12904 12905 /* --------- TST --------- */ 12906 case BITS4(1,0,0,0): /* TST: (void) Rn & shifter_operand */ 12907 case BITS4(1,0,0,1): { /* TEQ: (void) Rn ^ shifter_operand */ 12908 Bool isTEQ = INSN(24,21) == BITS4(1,0,0,1); 12909 if (rD != 0) 12910 break; /* rD must be zero */ 12911 if (bitS == 0) 12912 break; /* if S (bit 20) is not set, it's not TST/TEQ */ 12913 rNt = newTemp(Ity_I32); 12914 assign(rNt, getIRegA(rN)); 12915 ok = mk_shifter_operand( 12916 INSN(25,25), INSN(11,0), 12917 &shop, &shco, dis_buf 12918 ); 12919 if (!ok) 12920 break; 12921 /* Update the flags thunk. */ 12922 res = newTemp(Ity_I32); 12923 assign( res, binop(isTEQ ? Iop_Xor32 : Iop_And32, 12924 mkexpr(rNt), mkexpr(shop)) ); 12925 oldV = newTemp(Ity_I32); 12926 assign( oldV, mk_armg_calculate_flag_v() ); 12927 // can't safely read guest state after here 12928 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, 12929 res, shco, oldV, condT ); 12930 DIP("%s%s r%u, %s\n", 12931 isTEQ ? "teq" : "tst", 12932 nCC(INSN_COND), rN, dis_buf ); 12933 goto decode_success; 12934 } 12935 12936 /* --------- ADC, SBC, RSC --------- */ 12937 case BITS4(0,1,0,1): /* ADC: Rd = Rn + shifter_operand + oldC */ 12938 name = "adc"; goto rd_eq_rn_op_SO_op_oldC; 12939 case BITS4(0,1,1,0): /* SBC: Rd = Rn - shifter_operand - (oldC ^ 1) */ 12940 name = "sbc"; goto rd_eq_rn_op_SO_op_oldC; 12941 case BITS4(0,1,1,1): /* RSC: Rd = shifter_operand - Rn - (oldC ^ 1) */ 12942 name = "rsc"; goto rd_eq_rn_op_SO_op_oldC; 12943 rd_eq_rn_op_SO_op_oldC: { 12944 // FIXME: shco isn't used for anything. Get rid of it. 12945 rNt = newTemp(Ity_I32); 12946 assign(rNt, getIRegA(rN)); 12947 ok = mk_shifter_operand( 12948 INSN(25,25), INSN(11,0), 12949 &shop, bitS ? &shco : NULL, dis_buf 12950 ); 12951 if (!ok) 12952 break; 12953 oldC = newTemp(Ity_I32); 12954 assign( oldC, mk_armg_calculate_flag_c() ); 12955 res = newTemp(Ity_I32); 12956 // compute the main result 12957 switch (INSN(24,21)) { 12958 case BITS4(0,1,0,1): /* ADC */ 12959 assign(res, 12960 binop(Iop_Add32, 12961 binop(Iop_Add32, mkexpr(rNt), mkexpr(shop)), 12962 mkexpr(oldC) )); 12963 break; 12964 case BITS4(0,1,1,0): /* SBC */ 12965 assign(res, 12966 binop(Iop_Sub32, 12967 binop(Iop_Sub32, mkexpr(rNt), mkexpr(shop)), 12968 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) )); 12969 break; 12970 case BITS4(0,1,1,1): /* RSC */ 12971 assign(res, 12972 binop(Iop_Sub32, 12973 binop(Iop_Sub32, mkexpr(shop), mkexpr(rNt)), 12974 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) )); 12975 break; 12976 default: 12977 vassert(0); 12978 } 12979 // but don't commit it until after we've finished 12980 // all necessary reads from the guest state 12981 // now safe to put the main result 12982 putIRegA( rD, mkexpr(res), condT, Ijk_Boring ); 12983 // XXXX!! not safe to read any guest state after 12984 // this point (I think the code below doesn't do that). 12985 if (!bitS) 12986 vassert(shco == IRTemp_INVALID); 12987 /* Update the flags thunk if necessary */ 12988 if (bitS) { 12989 vassert(shco != IRTemp_INVALID); 12990 switch (INSN(24,21)) { 12991 case BITS4(0,1,0,1): /* ADC */ 12992 setFlags_D1_D2_ND( ARMG_CC_OP_ADC, 12993 rNt, shop, oldC, condT ); 12994 break; 12995 case BITS4(0,1,1,0): /* SBC */ 12996 setFlags_D1_D2_ND( ARMG_CC_OP_SBB, 12997 rNt, shop, oldC, condT ); 12998 break; 12999 case BITS4(0,1,1,1): /* RSC */ 13000 setFlags_D1_D2_ND( ARMG_CC_OP_SBB, 13001 shop, rNt, oldC, condT ); 13002 break; 13003 default: 13004 vassert(0); 13005 } 13006 } 13007 DIP("%s%s%s r%u, r%u, %s\n", 13008 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf ); 13009 goto decode_success; 13010 } 13011 13012 /* --------- ??? --------- */ 13013 default: 13014 break; 13015 } 13016 } /* if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) */ 13017 13018 /* --------------------- Load/store (ubyte & word) -------- */ 13019 // LDR STR LDRB STRB 13020 /* 31 27 23 19 15 11 6 4 3 # highest bit 13021 28 24 20 16 12 13022 A5-20 1 | 16 cond 0101 UB0L Rn Rd imm12 13023 A5-22 1 | 32 cond 0111 UBOL Rn Rd imm5 sh2 0 Rm 13024 A5-24 2 | 16 cond 0101 UB1L Rn Rd imm12 13025 A5-26 2 | 32 cond 0111 UB1L Rn Rd imm5 sh2 0 Rm 13026 A5-28 3 | 16 cond 0100 UB0L Rn Rd imm12 13027 A5-32 3 | 32 cond 0110 UB0L Rn Rd imm5 sh2 0 Rm 13028 */ 13029 /* case coding: 13030 1 at-ea (access at ea) 13031 2 at-ea-then-upd (access at ea, then Rn = ea) 13032 3 at-Rn-then-upd (access at Rn, then Rn = ea) 13033 ea coding 13034 16 Rn +/- imm12 13035 32 Rn +/- Rm sh2 imm5 13036 */ 13037 /* Quickly skip over all of this for hopefully most instructions */ 13038 if ((INSN(27,24) & BITS4(1,1,0,0)) != BITS4(0,1,0,0)) 13039 goto after_load_store_ubyte_or_word; 13040 13041 summary = 0; 13042 13043 /**/ if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 0) { 13044 summary = 1 | 16; 13045 } 13046 else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 0 13047 && INSN(4,4) == 0) { 13048 summary = 1 | 32; 13049 } 13050 else if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 1) { 13051 summary = 2 | 16; 13052 } 13053 else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 1 13054 && INSN(4,4) == 0) { 13055 summary = 2 | 32; 13056 } 13057 else if (INSN(27,24) == BITS4(0,1,0,0) && INSN(21,21) == 0) { 13058 summary = 3 | 16; 13059 } 13060 else if (INSN(27,24) == BITS4(0,1,1,0) && INSN(21,21) == 0 13061 && INSN(4,4) == 0) { 13062 summary = 3 | 32; 13063 } 13064 else goto after_load_store_ubyte_or_word; 13065 13066 { UInt rN = (insn >> 16) & 0xF; /* 19:16 */ 13067 UInt rD = (insn >> 12) & 0xF; /* 15:12 */ 13068 UInt rM = (insn >> 0) & 0xF; /* 3:0 */ 13069 UInt bU = (insn >> 23) & 1; /* 23 */ 13070 UInt bB = (insn >> 22) & 1; /* 22 */ 13071 UInt bL = (insn >> 20) & 1; /* 20 */ 13072 UInt imm12 = (insn >> 0) & 0xFFF; /* 11:0 */ 13073 UInt imm5 = (insn >> 7) & 0x1F; /* 11:7 */ 13074 UInt sh2 = (insn >> 5) & 3; /* 6:5 */ 13075 13076 /* Skip some invalid cases, which would lead to two competing 13077 updates to the same register, or which are otherwise 13078 disallowed by the spec. */ 13079 switch (summary) { 13080 case 1 | 16: 13081 break; 13082 case 1 | 32: 13083 if (rM == 15) goto after_load_store_ubyte_or_word; 13084 break; 13085 case 2 | 16: case 3 | 16: 13086 if (rN == 15) goto after_load_store_ubyte_or_word; 13087 if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word; 13088 break; 13089 case 2 | 32: case 3 | 32: 13090 if (rM == 15) goto after_load_store_ubyte_or_word; 13091 if (rN == 15) goto after_load_store_ubyte_or_word; 13092 if (rN == rM) goto after_load_store_ubyte_or_word; 13093 if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word; 13094 break; 13095 default: 13096 vassert(0); 13097 } 13098 13099 /* Now, we can't do a conditional load or store, since that very 13100 likely will generate an exception. So we have to take a side 13101 exit at this point if the condition is false. */ 13102 if (condT != IRTemp_INVALID) { 13103 mk_skip_over_A32_if_cond_is_false( condT ); 13104 condT = IRTemp_INVALID; 13105 } 13106 /* Ok, now we're unconditional. Do the load or store. */ 13107 13108 /* compute the effective address. Bind it to a tmp since we 13109 may need to use it twice. */ 13110 IRExpr* eaE = NULL; 13111 switch (summary & 0xF0) { 13112 case 16: 13113 eaE = mk_EA_reg_plusminus_imm12( rN, bU, imm12, dis_buf ); 13114 break; 13115 case 32: 13116 eaE = mk_EA_reg_plusminus_shifted_reg( rN, bU, rM, sh2, imm5, 13117 dis_buf ); 13118 break; 13119 } 13120 vassert(eaE); 13121 IRTemp eaT = newTemp(Ity_I32); 13122 assign(eaT, eaE); 13123 13124 /* get the old Rn value */ 13125 IRTemp rnT = newTemp(Ity_I32); 13126 assign(rnT, getIRegA(rN)); 13127 13128 /* decide on the transfer address */ 13129 IRTemp taT = IRTemp_INVALID; 13130 switch (summary & 0x0F) { 13131 case 1: case 2: taT = eaT; break; 13132 case 3: taT = rnT; break; 13133 } 13134 vassert(taT != IRTemp_INVALID); 13135 13136 if (bL == 0) { 13137 /* Store. If necessary, update the base register before the 13138 store itself, so that the common idiom of "str rX, [sp, 13139 #-4]!" (store rX at sp-4, then do new sp = sp-4, a.k.a "push 13140 rX") doesn't cause Memcheck to complain that the access is 13141 below the stack pointer. Also, not updating sp before the 13142 store confuses Valgrind's dynamic stack-extending logic. So 13143 do it before the store. Hence we need to snarf the store 13144 data before doing the basereg update. */ 13145 13146 /* get hold of the data to be stored */ 13147 IRTemp rDt = newTemp(Ity_I32); 13148 assign(rDt, getIRegA(rD)); 13149 13150 /* Update Rn if necessary. */ 13151 switch (summary & 0x0F) { 13152 case 2: case 3: 13153 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring ); 13154 break; 13155 } 13156 13157 /* generate the transfer */ 13158 if (bB == 0) { // word store 13159 storeLE( mkexpr(taT), mkexpr(rDt) ); 13160 } else { // byte store 13161 vassert(bB == 1); 13162 storeLE( mkexpr(taT), unop(Iop_32to8, mkexpr(rDt)) ); 13163 } 13164 13165 } else { 13166 /* Load */ 13167 vassert(bL == 1); 13168 13169 /* generate the transfer */ 13170 if (bB == 0) { // word load 13171 IRTemp jk = Ijk_Boring; 13172 /* According to the Cortex A8 TRM Sec. 5.2.1, LDR(1) with r13 as the 13173 base register and PC as the destination register is a return for 13174 purposes of branch prediction. 13175 The ARM ARM Sec. C9.10.1 further specifies that it must use a 13176 post-increment by immediate addressing mode to be counted in 13177 event 0x0E (Procedure return).*/ 13178 if (rN == 13 && summary == (3 | 16) && bB == 0) { 13179 jk = Ijk_Ret; 13180 } 13181 putIRegA( rD, loadLE(Ity_I32, mkexpr(taT)), 13182 IRTemp_INVALID, jk ); 13183 } else { // byte load 13184 vassert(bB == 1); 13185 putIRegA( rD, unop(Iop_8Uto32, loadLE(Ity_I8, mkexpr(taT))), 13186 IRTemp_INVALID, Ijk_Boring ); 13187 } 13188 13189 /* Update Rn if necessary. */ 13190 switch (summary & 0x0F) { 13191 case 2: case 3: 13192 // should be assured by logic above: 13193 if (bL == 1) 13194 vassert(rD != rN); /* since we just wrote rD */ 13195 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring ); 13196 break; 13197 } 13198 } 13199 13200 switch (summary & 0x0F) { 13201 case 1: DIP("%sr%s%s r%u, %s\n", 13202 bL == 0 ? "st" : "ld", 13203 bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf); 13204 break; 13205 case 2: DIP("%sr%s%s r%u, %s! (at-EA-then-Rn=EA)\n", 13206 bL == 0 ? "st" : "ld", 13207 bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf); 13208 break; 13209 case 3: DIP("%sr%s%s r%u, %s! (at-Rn-then-Rn=EA)\n", 13210 bL == 0 ? "st" : "ld", 13211 bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf); 13212 break; 13213 default: vassert(0); 13214 } 13215 13216 /* XXX deal with alignment constraints */ 13217 13218 goto decode_success; 13219 13220 /* Complications: 13221 13222 For all loads: if the Amode specifies base register 13223 writeback, and the same register is specified for Rd and Rn, 13224 the results are UNPREDICTABLE. 13225 13226 For all loads and stores: if R15 is written, branch to 13227 that address afterwards. 13228 13229 STRB: straightforward 13230 LDRB: loaded data is zero extended 13231 STR: lowest 2 bits of address are ignored 13232 LDR: if the lowest 2 bits of the address are nonzero 13233 then the loaded value is rotated right by 8 * the lowest 2 bits 13234 */ 13235 } 13236 13237 after_load_store_ubyte_or_word: 13238 13239 /* --------------------- Load/store (sbyte & hword) -------- */ 13240 // LDRH LDRSH STRH LDRSB 13241 /* 31 27 23 19 15 11 7 3 # highest bit 13242 28 24 20 16 12 8 4 0 13243 A5-36 1 | 16 cond 0001 U10L Rn Rd im4h 1SH1 im4l 13244 A5-38 1 | 32 cond 0001 U00L Rn Rd 0000 1SH1 Rm 13245 A5-40 2 | 16 cond 0001 U11L Rn Rd im4h 1SH1 im4l 13246 A5-42 2 | 32 cond 0001 U01L Rn Rd 0000 1SH1 Rm 13247 A5-44 3 | 16 cond 0000 U10L Rn Rd im4h 1SH1 im4l 13248 A5-46 3 | 32 cond 0000 U00L Rn Rd 0000 1SH1 Rm 13249 */ 13250 /* case coding: 13251 1 at-ea (access at ea) 13252 2 at-ea-then-upd (access at ea, then Rn = ea) 13253 3 at-Rn-then-upd (access at Rn, then Rn = ea) 13254 ea coding 13255 16 Rn +/- imm8 13256 32 Rn +/- Rm 13257 */ 13258 /* Quickly skip over all of this for hopefully most instructions */ 13259 if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0)) 13260 goto after_load_store_sbyte_or_hword; 13261 13262 /* Check the "1SH1" thing. */ 13263 if ((INSN(7,4) & BITS4(1,0,0,1)) != BITS4(1,0,0,1)) 13264 goto after_load_store_sbyte_or_hword; 13265 13266 summary = 0; 13267 13268 /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,0)) { 13269 summary = 1 | 16; 13270 } 13271 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,0)) { 13272 summary = 1 | 32; 13273 } 13274 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,1)) { 13275 summary = 2 | 16; 13276 } 13277 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,1)) { 13278 summary = 2 | 32; 13279 } 13280 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(1,0)) { 13281 summary = 3 | 16; 13282 } 13283 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(0,0)) { 13284 summary = 3 | 32; 13285 } 13286 else goto after_load_store_sbyte_or_hword; 13287 13288 { UInt rN = (insn >> 16) & 0xF; /* 19:16 */ 13289 UInt rD = (insn >> 12) & 0xF; /* 15:12 */ 13290 UInt rM = (insn >> 0) & 0xF; /* 3:0 */ 13291 UInt bU = (insn >> 23) & 1; /* 23 U=1 offset+, U=0 offset- */ 13292 UInt bL = (insn >> 20) & 1; /* 20 L=1 load, L=0 store */ 13293 UInt bH = (insn >> 5) & 1; /* H=1 halfword, H=0 byte */ 13294 UInt bS = (insn >> 6) & 1; /* S=1 signed, S=0 unsigned */ 13295 UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */ 13296 13297 /* Skip combinations that are either meaningless or already 13298 handled by main word-or-unsigned-byte load-store 13299 instructions. */ 13300 if (bS == 0 && bH == 0) /* "unsigned byte" */ 13301 goto after_load_store_sbyte_or_hword; 13302 if (bS == 1 && bL == 0) /* "signed store" */ 13303 goto after_load_store_sbyte_or_hword; 13304 13305 /* Require 11:8 == 0 for Rn +/- Rm cases */ 13306 if ((summary & 32) != 0 && (imm8 & 0xF0) != 0) 13307 goto after_load_store_sbyte_or_hword; 13308 13309 /* Skip some invalid cases, which would lead to two competing 13310 updates to the same register, or which are otherwise 13311 disallowed by the spec. */ 13312 switch (summary) { 13313 case 1 | 16: 13314 break; 13315 case 1 | 32: 13316 if (rM == 15) goto after_load_store_sbyte_or_hword; 13317 break; 13318 case 2 | 16: case 3 | 16: 13319 if (rN == 15) goto after_load_store_sbyte_or_hword; 13320 if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword; 13321 break; 13322 case 2 | 32: case 3 | 32: 13323 if (rM == 15) goto after_load_store_sbyte_or_hword; 13324 if (rN == 15) goto after_load_store_sbyte_or_hword; 13325 if (rN == rM) goto after_load_store_sbyte_or_hword; 13326 if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword; 13327 break; 13328 default: 13329 vassert(0); 13330 } 13331 13332 /* Now, we can't do a conditional load or store, since that very 13333 likely will generate an exception. So we have to take a side 13334 exit at this point if the condition is false. */ 13335 if (condT != IRTemp_INVALID) { 13336 mk_skip_over_A32_if_cond_is_false( condT ); 13337 condT = IRTemp_INVALID; 13338 } 13339 /* Ok, now we're unconditional. Do the load or store. */ 13340 13341 /* compute the effective address. Bind it to a tmp since we 13342 may need to use it twice. */ 13343 IRExpr* eaE = NULL; 13344 switch (summary & 0xF0) { 13345 case 16: 13346 eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf ); 13347 break; 13348 case 32: 13349 eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf ); 13350 break; 13351 } 13352 vassert(eaE); 13353 IRTemp eaT = newTemp(Ity_I32); 13354 assign(eaT, eaE); 13355 13356 /* get the old Rn value */ 13357 IRTemp rnT = newTemp(Ity_I32); 13358 assign(rnT, getIRegA(rN)); 13359 13360 /* decide on the transfer address */ 13361 IRTemp taT = IRTemp_INVALID; 13362 switch (summary & 0x0F) { 13363 case 1: case 2: taT = eaT; break; 13364 case 3: taT = rnT; break; 13365 } 13366 vassert(taT != IRTemp_INVALID); 13367 13368 /* halfword store H 1 L 0 S 0 13369 uhalf load H 1 L 1 S 0 13370 shalf load H 1 L 1 S 1 13371 sbyte load H 0 L 1 S 1 13372 */ 13373 HChar* name = NULL; 13374 /* generate the transfer */ 13375 /**/ if (bH == 1 && bL == 0 && bS == 0) { // halfword store 13376 storeLE( mkexpr(taT), unop(Iop_32to16, getIRegA(rD)) ); 13377 name = "strh"; 13378 } 13379 else if (bH == 1 && bL == 1 && bS == 0) { // uhalf load 13380 putIRegA( rD, unop(Iop_16Uto32, loadLE(Ity_I16, mkexpr(taT))), 13381 IRTemp_INVALID, Ijk_Boring ); 13382 name = "ldrh"; 13383 } 13384 else if (bH == 1 && bL == 1 && bS == 1) { // shalf load 13385 putIRegA( rD, unop(Iop_16Sto32, loadLE(Ity_I16, mkexpr(taT))), 13386 IRTemp_INVALID, Ijk_Boring ); 13387 name = "ldrsh"; 13388 } 13389 else if (bH == 0 && bL == 1 && bS == 1) { // sbyte load 13390 putIRegA( rD, unop(Iop_8Sto32, loadLE(Ity_I8, mkexpr(taT))), 13391 IRTemp_INVALID, Ijk_Boring ); 13392 name = "ldrsb"; 13393 } 13394 else 13395 vassert(0); // should be assured by logic above 13396 13397 /* Update Rn if necessary. */ 13398 switch (summary & 0x0F) { 13399 case 2: case 3: 13400 // should be assured by logic above: 13401 if (bL == 1) 13402 vassert(rD != rN); /* since we just wrote rD */ 13403 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring ); 13404 break; 13405 } 13406 13407 switch (summary & 0x0F) { 13408 case 1: DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf); 13409 break; 13410 case 2: DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n", 13411 name, nCC(INSN_COND), rD, dis_buf); 13412 break; 13413 case 3: DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n", 13414 name, nCC(INSN_COND), rD, dis_buf); 13415 break; 13416 default: vassert(0); 13417 } 13418 13419 /* XXX deal with alignment constraints */ 13420 13421 goto decode_success; 13422 13423 /* Complications: 13424 13425 For all loads: if the Amode specifies base register 13426 writeback, and the same register is specified for Rd and Rn, 13427 the results are UNPREDICTABLE. 13428 13429 For all loads and stores: if R15 is written, branch to 13430 that address afterwards. 13431 13432 Misaligned halfword stores => Unpredictable 13433 Misaligned halfword loads => Unpredictable 13434 */ 13435 } 13436 13437 after_load_store_sbyte_or_hword: 13438 13439 /* --------------------- Load/store multiple -------------- */ 13440 // LD/STMIA LD/STMIB LD/STMDA LD/STMDB 13441 // Remarkably complex and difficult to get right 13442 // match 27:20 as 100XX0WL 13443 if (BITS8(1,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,1,0,0))) { 13444 // A5-50 LD/STMIA cond 1000 10WL Rn RegList 13445 // A5-51 LD/STMIB cond 1001 10WL Rn RegList 13446 // A5-53 LD/STMDA cond 1000 00WL Rn RegList 13447 // A5-53 LD/STMDB cond 1001 00WL Rn RegList 13448 // 28 24 20 16 0 13449 13450 UInt bINC = (insn >> 23) & 1; 13451 UInt bBEFORE = (insn >> 24) & 1; 13452 13453 UInt bL = (insn >> 20) & 1; /* load=1, store=0 */ 13454 UInt bW = (insn >> 21) & 1; /* Rn wback=1, no wback=0 */ 13455 UInt rN = (insn >> 16) & 0xF; 13456 UInt regList = insn & 0xFFFF; 13457 /* Skip some invalid cases, which would lead to two competing 13458 updates to the same register, or which are otherwise 13459 disallowed by the spec. Note the test above has required 13460 that S == 0, since that looks like a kernel-mode only thing. 13461 Done by forcing the real pattern, viz 100XXSWL to actually be 13462 100XX0WL. */ 13463 if (rN == 15) goto after_load_store_multiple; 13464 // reglist can't be empty 13465 if (regList == 0) goto after_load_store_multiple; 13466 // if requested to writeback Rn, and this is a load instruction, 13467 // then Rn can't appear in RegList, since we'd have two competing 13468 // new values for Rn. We do however accept this case for store 13469 // instructions. 13470 if (bW == 1 && bL == 1 && ((1 << rN) & regList) > 0) 13471 goto after_load_store_multiple; 13472 13473 /* Now, we can't do a conditional load or store, since that very 13474 likely will generate an exception. So we have to take a side 13475 exit at this point if the condition is false. */ 13476 if (condT != IRTemp_INVALID) { 13477 mk_skip_over_A32_if_cond_is_false( condT ); 13478 condT = IRTemp_INVALID; 13479 } 13480 13481 /* Ok, now we're unconditional. Generate the IR. */ 13482 mk_ldm_stm( True/*arm*/, rN, bINC, bBEFORE, bW, bL, regList ); 13483 13484 DIP("%sm%c%c%s r%u%s, {0x%04x}\n", 13485 bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a', 13486 nCC(INSN_COND), 13487 rN, bW ? "!" : "", regList); 13488 13489 goto decode_success; 13490 } 13491 13492 after_load_store_multiple: 13493 13494 /* --------------------- Control flow --------------------- */ 13495 // B, BL (Branch, or Branch-and-Link, to immediate offset) 13496 // 13497 if (BITS8(1,0,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))) { 13498 UInt link = (insn >> 24) & 1; 13499 UInt uimm24 = insn & ((1<<24)-1); 13500 Int simm24 = (Int)uimm24; 13501 UInt dst = guest_R15_curr_instr_notENC + 8 13502 + (((simm24 << 8) >> 8) << 2); 13503 IRJumpKind jk = link ? Ijk_Call : Ijk_Boring; 13504 if (link) { 13505 putIRegA(14, mkU32(guest_R15_curr_instr_notENC + 4), 13506 condT, Ijk_Boring); 13507 } 13508 if (condT == IRTemp_INVALID) { 13509 /* unconditional transfer to 'dst'. See if we can simply 13510 continue tracing at the destination. */ 13511 if (resteerOkFn( callback_opaque, (Addr64)dst )) { 13512 /* yes */ 13513 dres.whatNext = Dis_ResteerU; 13514 dres.continueAt = (Addr64)dst; 13515 } else { 13516 /* no; terminate the SB at this point. */ 13517 llPutIReg(15, mkU32(dst)); 13518 dres.jk_StopHere = jk; 13519 dres.whatNext = Dis_StopHere; 13520 } 13521 DIP("b%s 0x%x\n", link ? "l" : "", dst); 13522 } else { 13523 /* conditional transfer to 'dst' */ 13524 HChar* comment = ""; 13525 13526 /* First see if we can do some speculative chasing into one 13527 arm or the other. Be conservative and only chase if 13528 !link, that is, this is a normal conditional branch to a 13529 known destination. */ 13530 if (!link 13531 && resteerCisOk 13532 && vex_control.guest_chase_cond 13533 && dst < guest_R15_curr_instr_notENC 13534 && resteerOkFn( callback_opaque, (Addr64)(Addr32)dst) ) { 13535 /* Speculation: assume this backward branch is taken. So 13536 we need to emit a side-exit to the insn following this 13537 one, on the negation of the condition, and continue at 13538 the branch target address (dst). */ 13539 stmt( IRStmt_Exit( unop(Iop_Not1, 13540 unop(Iop_32to1, mkexpr(condT))), 13541 Ijk_Boring, 13542 IRConst_U32(guest_R15_curr_instr_notENC+4), 13543 OFFB_R15T )); 13544 dres.whatNext = Dis_ResteerC; 13545 dres.continueAt = (Addr64)(Addr32)dst; 13546 comment = "(assumed taken)"; 13547 } 13548 else 13549 if (!link 13550 && resteerCisOk 13551 && vex_control.guest_chase_cond 13552 && dst >= guest_R15_curr_instr_notENC 13553 && resteerOkFn( callback_opaque, 13554 (Addr64)(Addr32) 13555 (guest_R15_curr_instr_notENC+4)) ) { 13556 /* Speculation: assume this forward branch is not taken. 13557 So we need to emit a side-exit to dst (the dest) and 13558 continue disassembling at the insn immediately 13559 following this one. */ 13560 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)), 13561 Ijk_Boring, 13562 IRConst_U32(dst), 13563 OFFB_R15T )); 13564 dres.whatNext = Dis_ResteerC; 13565 dres.continueAt = (Addr64)(Addr32) 13566 (guest_R15_curr_instr_notENC+4); 13567 comment = "(assumed not taken)"; 13568 } 13569 else { 13570 /* Conservative default translation - end the block at 13571 this point. */ 13572 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)), 13573 jk, IRConst_U32(dst), OFFB_R15T )); 13574 llPutIReg(15, mkU32(guest_R15_curr_instr_notENC + 4)); 13575 dres.jk_StopHere = Ijk_Boring; 13576 dres.whatNext = Dis_StopHere; 13577 } 13578 DIP("b%s%s 0x%x %s\n", link ? "l" : "", nCC(INSN_COND), 13579 dst, comment); 13580 } 13581 goto decode_success; 13582 } 13583 13584 // B, BL (Branch, or Branch-and-Link, to a register) 13585 // NB: interworking branch 13586 if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0) 13587 && INSN(19,12) == BITS8(1,1,1,1,1,1,1,1) 13588 && (INSN(11,4) == BITS8(1,1,1,1,0,0,1,1) 13589 || INSN(11,4) == BITS8(1,1,1,1,0,0,0,1))) { 13590 IRTemp dst = newTemp(Ity_I32); 13591 UInt link = (INSN(11,4) >> 1) & 1; 13592 UInt rM = INSN(3,0); 13593 // we don't decode the case (link && rM == 15), as that's 13594 // Unpredictable. 13595 if (!(link && rM == 15)) { 13596 if (condT != IRTemp_INVALID) { 13597 mk_skip_over_A32_if_cond_is_false( condT ); 13598 } 13599 // rM contains an interworking address exactly as we require 13600 // (with continuation CPSR.T in bit 0), so we can use it 13601 // as-is, with no masking. 13602 assign( dst, getIRegA(rM) ); 13603 if (link) { 13604 putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4), 13605 IRTemp_INVALID/*because AL*/, Ijk_Boring ); 13606 } 13607 llPutIReg(15, mkexpr(dst)); 13608 dres.jk_StopHere = link ? Ijk_Call 13609 : (rM == 14 ? Ijk_Ret : Ijk_Boring); 13610 dres.whatNext = Dis_StopHere; 13611 if (condT == IRTemp_INVALID) { 13612 DIP("b%sx r%u\n", link ? "l" : "", rM); 13613 } else { 13614 DIP("b%sx%s r%u\n", link ? "l" : "", nCC(INSN_COND), rM); 13615 } 13616 goto decode_success; 13617 } 13618 /* else: (link && rM == 15): just fall through */ 13619 } 13620 13621 /* --- NB: ARM interworking branches are in NV space, hence 13622 are handled elsewhere by decode_NV_instruction. 13623 --- 13624 */ 13625 13626 /* --------------------- Clz --------------------- */ 13627 // CLZ 13628 if (INSN(27,20) == BITS8(0,0,0,1,0,1,1,0) 13629 && INSN(19,16) == BITS4(1,1,1,1) 13630 && INSN(11,4) == BITS8(1,1,1,1,0,0,0,1)) { 13631 UInt rD = INSN(15,12); 13632 UInt rM = INSN(3,0); 13633 IRTemp arg = newTemp(Ity_I32); 13634 IRTemp res = newTemp(Ity_I32); 13635 assign(arg, getIRegA(rM)); 13636 assign(res, IRExpr_Mux0X( 13637 unop(Iop_1Uto8,binop(Iop_CmpEQ32, mkexpr(arg), 13638 mkU32(0))), 13639 unop(Iop_Clz32, mkexpr(arg)), 13640 mkU32(32) 13641 )); 13642 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 13643 DIP("clz%s r%u, r%u\n", nCC(INSN_COND), rD, rM); 13644 goto decode_success; 13645 } 13646 13647 /* --------------------- Mul etc --------------------- */ 13648 // MUL 13649 if (BITS8(0,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0)) 13650 && INSN(15,12) == BITS4(0,0,0,0) 13651 && INSN(7,4) == BITS4(1,0,0,1)) { 13652 UInt bitS = (insn >> 20) & 1; /* 20:20 */ 13653 UInt rD = INSN(19,16); 13654 UInt rS = INSN(11,8); 13655 UInt rM = INSN(3,0); 13656 if (rD == 15 || rM == 15 || rS == 15) { 13657 /* Unpredictable; don't decode; fall through */ 13658 } else { 13659 IRTemp argL = newTemp(Ity_I32); 13660 IRTemp argR = newTemp(Ity_I32); 13661 IRTemp res = newTemp(Ity_I32); 13662 IRTemp oldC = IRTemp_INVALID; 13663 IRTemp oldV = IRTemp_INVALID; 13664 assign( argL, getIRegA(rM)); 13665 assign( argR, getIRegA(rS)); 13666 assign( res, binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) ); 13667 if (bitS) { 13668 oldC = newTemp(Ity_I32); 13669 assign(oldC, mk_armg_calculate_flag_c()); 13670 oldV = newTemp(Ity_I32); 13671 assign(oldV, mk_armg_calculate_flag_v()); 13672 } 13673 // now update guest state 13674 putIRegA( rD, mkexpr(res), condT, Ijk_Boring ); 13675 if (bitS) { 13676 IRTemp pair = newTemp(Ity_I32); 13677 assign( pair, binop(Iop_Or32, 13678 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)), 13679 mkexpr(oldV)) ); 13680 setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT ); 13681 } 13682 DIP("mul%c%s r%u, r%u, r%u\n", 13683 bitS ? 's' : ' ', nCC(INSN_COND), rD, rM, rS); 13684 goto decode_success; 13685 } 13686 /* fall through */ 13687 } 13688 13689 /* --------------------- Integer Divides --------------------- */ 13690 // SDIV 13691 if (BITS8(0,1,1,1,0,0,0,1) == INSN(27,20) 13692 && INSN(15,12) == BITS4(1,1,1,1) 13693 && INSN(7,4) == BITS4(0,0,0,1)) { 13694 UInt rD = INSN(19,16); 13695 UInt rM = INSN(11,8); 13696 UInt rN = INSN(3,0); 13697 if (rD == 15 || rM == 15 || rN == 15) { 13698 /* Unpredictable; don't decode; fall through */ 13699 } else { 13700 IRTemp res = newTemp(Ity_I32); 13701 IRTemp argL = newTemp(Ity_I32); 13702 IRTemp argR = newTemp(Ity_I32); 13703 assign(argL, getIRegA(rN)); 13704 assign(argR, getIRegA(rM)); 13705 assign(res, binop(Iop_DivS32, mkexpr(argL), mkexpr(argR))); 13706 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 13707 DIP("sdiv r%u, r%u, r%u\n", rD, rN, rM); 13708 goto decode_success; 13709 } 13710 } 13711 13712 // UDIV 13713 if (BITS8(0,1,1,1,0,0,1,1) == INSN(27,20) 13714 && INSN(15,12) == BITS4(1,1,1,1) 13715 && INSN(7,4) == BITS4(0,0,0,1)) { 13716 UInt rD = INSN(19,16); 13717 UInt rM = INSN(11,8); 13718 UInt rN = INSN(3,0); 13719 if (rD == 15 || rM == 15 || rN == 15) { 13720 /* Unpredictable; don't decode; fall through */ 13721 } else { 13722 IRTemp res = newTemp(Ity_I32); 13723 IRTemp argL = newTemp(Ity_I32); 13724 IRTemp argR = newTemp(Ity_I32); 13725 assign(argL, getIRegA(rN)); 13726 assign(argR, getIRegA(rM)); 13727 assign(res, binop(Iop_DivU32, mkexpr(argL), mkexpr(argR))); 13728 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 13729 DIP("udiv r%u, r%u, r%u\n", rD, rN, rM); 13730 goto decode_success; 13731 } 13732 } 13733 13734 // MLA, MLS 13735 if (BITS8(0,0,0,0,0,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0)) 13736 && INSN(7,4) == BITS4(1,0,0,1)) { 13737 UInt bitS = (insn >> 20) & 1; /* 20:20 */ 13738 UInt isMLS = (insn >> 22) & 1; /* 22:22 */ 13739 UInt rD = INSN(19,16); 13740 UInt rN = INSN(15,12); 13741 UInt rS = INSN(11,8); 13742 UInt rM = INSN(3,0); 13743 if (bitS == 1 && isMLS == 1) { 13744 /* This isn't allowed (MLS that sets flags). don't decode; 13745 fall through */ 13746 } 13747 else 13748 if (rD == 15 || rM == 15 || rS == 15 || rN == 15) { 13749 /* Unpredictable; don't decode; fall through */ 13750 } else { 13751 IRTemp argL = newTemp(Ity_I32); 13752 IRTemp argR = newTemp(Ity_I32); 13753 IRTemp argP = newTemp(Ity_I32); 13754 IRTemp res = newTemp(Ity_I32); 13755 IRTemp oldC = IRTemp_INVALID; 13756 IRTemp oldV = IRTemp_INVALID; 13757 assign( argL, getIRegA(rM)); 13758 assign( argR, getIRegA(rS)); 13759 assign( argP, getIRegA(rN)); 13760 assign( res, binop(isMLS ? Iop_Sub32 : Iop_Add32, 13761 mkexpr(argP), 13762 binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) )); 13763 if (bitS) { 13764 vassert(!isMLS); // guaranteed above 13765 oldC = newTemp(Ity_I32); 13766 assign(oldC, mk_armg_calculate_flag_c()); 13767 oldV = newTemp(Ity_I32); 13768 assign(oldV, mk_armg_calculate_flag_v()); 13769 } 13770 // now update guest state 13771 putIRegA( rD, mkexpr(res), condT, Ijk_Boring ); 13772 if (bitS) { 13773 IRTemp pair = newTemp(Ity_I32); 13774 assign( pair, binop(Iop_Or32, 13775 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)), 13776 mkexpr(oldV)) ); 13777 setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT ); 13778 } 13779 DIP("ml%c%c%s r%u, r%u, r%u, r%u\n", 13780 isMLS ? 's' : 'a', bitS ? 's' : ' ', 13781 nCC(INSN_COND), rD, rM, rS, rN); 13782 goto decode_success; 13783 } 13784 /* fall through */ 13785 } 13786 13787 // SMULL, UMULL 13788 if (BITS8(0,0,0,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0)) 13789 && INSN(7,4) == BITS4(1,0,0,1)) { 13790 UInt bitS = (insn >> 20) & 1; /* 20:20 */ 13791 UInt rDhi = INSN(19,16); 13792 UInt rDlo = INSN(15,12); 13793 UInt rS = INSN(11,8); 13794 UInt rM = INSN(3,0); 13795 UInt isS = (INSN(27,20) >> 2) & 1; /* 22:22 */ 13796 if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo) { 13797 /* Unpredictable; don't decode; fall through */ 13798 } else { 13799 IRTemp argL = newTemp(Ity_I32); 13800 IRTemp argR = newTemp(Ity_I32); 13801 IRTemp res = newTemp(Ity_I64); 13802 IRTemp resHi = newTemp(Ity_I32); 13803 IRTemp resLo = newTemp(Ity_I32); 13804 IRTemp oldC = IRTemp_INVALID; 13805 IRTemp oldV = IRTemp_INVALID; 13806 IROp mulOp = isS ? Iop_MullS32 : Iop_MullU32; 13807 assign( argL, getIRegA(rM)); 13808 assign( argR, getIRegA(rS)); 13809 assign( res, binop(mulOp, mkexpr(argL), mkexpr(argR)) ); 13810 assign( resHi, unop(Iop_64HIto32, mkexpr(res)) ); 13811 assign( resLo, unop(Iop_64to32, mkexpr(res)) ); 13812 if (bitS) { 13813 oldC = newTemp(Ity_I32); 13814 assign(oldC, mk_armg_calculate_flag_c()); 13815 oldV = newTemp(Ity_I32); 13816 assign(oldV, mk_armg_calculate_flag_v()); 13817 } 13818 // now update guest state 13819 putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring ); 13820 putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring ); 13821 if (bitS) { 13822 IRTemp pair = newTemp(Ity_I32); 13823 assign( pair, binop(Iop_Or32, 13824 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)), 13825 mkexpr(oldV)) ); 13826 setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT ); 13827 } 13828 DIP("%cmull%c%s r%u, r%u, r%u, r%u\n", 13829 isS ? 's' : 'u', bitS ? 's' : ' ', 13830 nCC(INSN_COND), rDlo, rDhi, rM, rS); 13831 goto decode_success; 13832 } 13833 /* fall through */ 13834 } 13835 13836 // SMLAL, UMLAL 13837 if (BITS8(0,0,0,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0)) 13838 && INSN(7,4) == BITS4(1,0,0,1)) { 13839 UInt bitS = (insn >> 20) & 1; /* 20:20 */ 13840 UInt rDhi = INSN(19,16); 13841 UInt rDlo = INSN(15,12); 13842 UInt rS = INSN(11,8); 13843 UInt rM = INSN(3,0); 13844 UInt isS = (INSN(27,20) >> 2) & 1; /* 22:22 */ 13845 if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo) { 13846 /* Unpredictable; don't decode; fall through */ 13847 } else { 13848 IRTemp argL = newTemp(Ity_I32); 13849 IRTemp argR = newTemp(Ity_I32); 13850 IRTemp old = newTemp(Ity_I64); 13851 IRTemp res = newTemp(Ity_I64); 13852 IRTemp resHi = newTemp(Ity_I32); 13853 IRTemp resLo = newTemp(Ity_I32); 13854 IRTemp oldC = IRTemp_INVALID; 13855 IRTemp oldV = IRTemp_INVALID; 13856 IROp mulOp = isS ? Iop_MullS32 : Iop_MullU32; 13857 assign( argL, getIRegA(rM)); 13858 assign( argR, getIRegA(rS)); 13859 assign( old, binop(Iop_32HLto64, getIRegA(rDhi), getIRegA(rDlo)) ); 13860 assign( res, binop(Iop_Add64, 13861 mkexpr(old), 13862 binop(mulOp, mkexpr(argL), mkexpr(argR))) ); 13863 assign( resHi, unop(Iop_64HIto32, mkexpr(res)) ); 13864 assign( resLo, unop(Iop_64to32, mkexpr(res)) ); 13865 if (bitS) { 13866 oldC = newTemp(Ity_I32); 13867 assign(oldC, mk_armg_calculate_flag_c()); 13868 oldV = newTemp(Ity_I32); 13869 assign(oldV, mk_armg_calculate_flag_v()); 13870 } 13871 // now update guest state 13872 putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring ); 13873 putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring ); 13874 if (bitS) { 13875 IRTemp pair = newTemp(Ity_I32); 13876 assign( pair, binop(Iop_Or32, 13877 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)), 13878 mkexpr(oldV)) ); 13879 setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT ); 13880 } 13881 DIP("%cmlal%c%s r%u, r%u, r%u, r%u\n", 13882 isS ? 's' : 'u', bitS ? 's' : ' ', nCC(INSN_COND), 13883 rDlo, rDhi, rM, rS); 13884 goto decode_success; 13885 } 13886 /* fall through */ 13887 } 13888 13889 /* --------------------- Msr etc --------------------- */ 13890 13891 // MSR apsr, #imm 13892 if (INSN(27,20) == BITS8(0,0,1,1,0,0,1,0) 13893 && INSN(17,12) == BITS6(0,0,1,1,1,1)) { 13894 UInt write_ge = INSN(18,18); 13895 UInt write_nzcvq = INSN(19,19); 13896 if (write_nzcvq || write_ge) { 13897 UInt imm = (INSN(11,0) >> 0) & 0xFF; 13898 UInt rot = 2 * ((INSN(11,0) >> 8) & 0xF); 13899 IRTemp immT = newTemp(Ity_I32); 13900 vassert(rot <= 30); 13901 imm = ROR32(imm, rot); 13902 assign(immT, mkU32(imm)); 13903 desynthesise_APSR( write_nzcvq, write_ge, immT, condT ); 13904 DIP("msr%s cpsr%s%sf, #0x%08x\n", nCC(INSN_COND), 13905 write_nzcvq ? "f" : "", write_ge ? "g" : "", imm); 13906 goto decode_success; 13907 } 13908 /* fall through */ 13909 } 13910 13911 // MSR apsr, reg 13912 if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0) 13913 && INSN(17,12) == BITS6(0,0,1,1,1,1) 13914 && INSN(11,4) == BITS8(0,0,0,0,0,0,0,0)) { 13915 UInt rN = INSN(3,0); 13916 UInt write_ge = INSN(18,18); 13917 UInt write_nzcvq = INSN(19,19); 13918 if (rN != 15 && (write_nzcvq || write_ge)) { 13919 IRTemp rNt = newTemp(Ity_I32); 13920 assign(rNt, getIRegA(rN)); 13921 desynthesise_APSR( write_nzcvq, write_ge, rNt, condT ); 13922 DIP("msr%s cpsr_%s%s, r%u\n", nCC(INSN_COND), 13923 write_nzcvq ? "f" : "", write_ge ? "g" : "", rN); 13924 goto decode_success; 13925 } 13926 /* fall through */ 13927 } 13928 13929 // MRS rD, cpsr 13930 if ((insn & 0x0FFF0FFF) == 0x010F0000) { 13931 UInt rD = INSN(15,12); 13932 if (rD != 15) { 13933 IRTemp apsr = synthesise_APSR(); 13934 putIRegA( rD, mkexpr(apsr), condT, Ijk_Boring ); 13935 DIP("mrs%s r%u, cpsr\n", nCC(INSN_COND), rD); 13936 goto decode_success; 13937 } 13938 /* fall through */ 13939 } 13940 13941 /* --------------------- Svc --------------------- */ 13942 if (BITS8(1,1,1,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))) { 13943 UInt imm24 = (insn >> 0) & 0xFFFFFF; 13944 if (imm24 == 0) { 13945 /* A syscall. We can't do this conditionally, hence: */ 13946 if (condT != IRTemp_INVALID) { 13947 mk_skip_over_A32_if_cond_is_false( condT ); 13948 } 13949 // AL after here 13950 llPutIReg(15, mkU32( guest_R15_curr_instr_notENC + 4 )); 13951 dres.jk_StopHere = Ijk_Sys_syscall; 13952 dres.whatNext = Dis_StopHere; 13953 DIP("svc%s #0x%08x\n", nCC(INSN_COND), imm24); 13954 goto decode_success; 13955 } 13956 /* fall through */ 13957 } 13958 13959 /* ------------------------ swp ------------------------ */ 13960 13961 // SWP, SWPB 13962 if (BITS8(0,0,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 13963 && BITS4(0,0,0,0) == INSN(11,8) 13964 && BITS4(1,0,0,1) == INSN(7,4)) { 13965 UInt rN = INSN(19,16); 13966 UInt rD = INSN(15,12); 13967 UInt rM = INSN(3,0); 13968 IRTemp tRn = newTemp(Ity_I32); 13969 IRTemp tNew = newTemp(Ity_I32); 13970 IRTemp tOld = IRTemp_INVALID; 13971 IRTemp tSC1 = newTemp(Ity_I1); 13972 UInt isB = (insn >> 22) & 1; 13973 13974 if (rD == 15 || rN == 15 || rM == 15 || rN == rM || rN == rD) { 13975 /* undecodable; fall through */ 13976 } else { 13977 /* make unconditional */ 13978 if (condT != IRTemp_INVALID) { 13979 mk_skip_over_A32_if_cond_is_false( condT ); 13980 condT = IRTemp_INVALID; 13981 } 13982 /* Ok, now we're unconditional. Generate a LL-SC loop. */ 13983 assign(tRn, getIRegA(rN)); 13984 assign(tNew, getIRegA(rM)); 13985 if (isB) { 13986 /* swpb */ 13987 tOld = newTemp(Ity_I8); 13988 stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn), 13989 NULL/*=>isLL*/) ); 13990 stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn), 13991 unop(Iop_32to8, mkexpr(tNew))) ); 13992 } else { 13993 /* swp */ 13994 tOld = newTemp(Ity_I32); 13995 stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn), 13996 NULL/*=>isLL*/) ); 13997 stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn), 13998 mkexpr(tNew)) ); 13999 } 14000 stmt( IRStmt_Exit(unop(Iop_Not1, mkexpr(tSC1)), 14001 /*Ijk_NoRedir*/Ijk_Boring, 14002 IRConst_U32(guest_R15_curr_instr_notENC), 14003 OFFB_R15T )); 14004 putIRegA(rD, isB ? unop(Iop_8Uto32, mkexpr(tOld)) : mkexpr(tOld), 14005 IRTemp_INVALID, Ijk_Boring); 14006 DIP("swp%s%s r%u, r%u, [r%u]\n", 14007 isB ? "b" : "", nCC(INSN_COND), rD, rM, rN); 14008 goto decode_success; 14009 } 14010 /* fall through */ 14011 } 14012 14013 /* ----------------------------------------------------------- */ 14014 /* -- ARMv6 instructions -- */ 14015 /* ----------------------------------------------------------- */ 14016 14017 /* ------------------- {ldr,str}ex{,b,h,d} ------------------- */ 14018 14019 // LDREXD, LDREX, LDREXH, LDREXB 14020 if (0x01900F9F == (insn & 0x0F900FFF)) { 14021 UInt rT = INSN(15,12); 14022 UInt rN = INSN(19,16); 14023 IRType ty = Ity_INVALID; 14024 IROp widen = Iop_INVALID; 14025 HChar* nm = NULL; 14026 Bool valid = True; 14027 switch (INSN(22,21)) { 14028 case 0: nm = ""; ty = Ity_I32; break; 14029 case 1: nm = "d"; ty = Ity_I64; break; 14030 case 2: nm = "b"; ty = Ity_I8; widen = Iop_8Uto32; break; 14031 case 3: nm = "h"; ty = Ity_I16; widen = Iop_16Uto32; break; 14032 default: vassert(0); 14033 } 14034 if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) { 14035 if (rT == 15 || rN == 15) 14036 valid = False; 14037 } else { 14038 vassert(ty == Ity_I64); 14039 if ((rT & 1) == 1 || rT == 14 || rN == 15) 14040 valid = False; 14041 } 14042 if (valid) { 14043 IRTemp res; 14044 /* make unconditional */ 14045 if (condT != IRTemp_INVALID) { 14046 mk_skip_over_A32_if_cond_is_false( condT ); 14047 condT = IRTemp_INVALID; 14048 } 14049 /* Ok, now we're unconditional. Do the load. */ 14050 res = newTemp(ty); 14051 // FIXME: assumes little-endian guest 14052 stmt( IRStmt_LLSC(Iend_LE, res, getIRegA(rN), 14053 NULL/*this is a load*/) ); 14054 if (ty == Ity_I64) { 14055 // FIXME: assumes little-endian guest 14056 putIRegA(rT+0, unop(Iop_64to32, mkexpr(res)), 14057 IRTemp_INVALID, Ijk_Boring); 14058 putIRegA(rT+1, unop(Iop_64HIto32, mkexpr(res)), 14059 IRTemp_INVALID, Ijk_Boring); 14060 DIP("ldrex%s%s r%u, r%u, [r%u]\n", 14061 nm, nCC(INSN_COND), rT+0, rT+1, rN); 14062 } else { 14063 putIRegA(rT, widen == Iop_INVALID 14064 ? mkexpr(res) : unop(widen, mkexpr(res)), 14065 IRTemp_INVALID, Ijk_Boring); 14066 DIP("ldrex%s%s r%u, [r%u]\n", nm, nCC(INSN_COND), rT, rN); 14067 } 14068 goto decode_success; 14069 } 14070 /* undecodable; fall through */ 14071 } 14072 14073 // STREXD, STREX, STREXH, STREXB 14074 if (0x01800F90 == (insn & 0x0F900FF0)) { 14075 UInt rT = INSN(3,0); 14076 UInt rN = INSN(19,16); 14077 UInt rD = INSN(15,12); 14078 IRType ty = Ity_INVALID; 14079 IROp narrow = Iop_INVALID; 14080 HChar* nm = NULL; 14081 Bool valid = True; 14082 switch (INSN(22,21)) { 14083 case 0: nm = ""; ty = Ity_I32; break; 14084 case 1: nm = "d"; ty = Ity_I64; break; 14085 case 2: nm = "b"; ty = Ity_I8; narrow = Iop_32to8; break; 14086 case 3: nm = "h"; ty = Ity_I16; narrow = Iop_32to16; break; 14087 default: vassert(0); 14088 } 14089 if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) { 14090 if (rD == 15 || rN == 15 || rT == 15 14091 || rD == rN || rD == rT) 14092 valid = False; 14093 } else { 14094 vassert(ty == Ity_I64); 14095 if (rD == 15 || (rT & 1) == 1 || rT == 14 || rN == 15 14096 || rD == rN || rD == rT || rD == rT+1) 14097 valid = False; 14098 } 14099 if (valid) { 14100 IRTemp resSC1, resSC32, data; 14101 /* make unconditional */ 14102 if (condT != IRTemp_INVALID) { 14103 mk_skip_over_A32_if_cond_is_false( condT ); 14104 condT = IRTemp_INVALID; 14105 } 14106 /* Ok, now we're unconditional. Do the store. */ 14107 data = newTemp(ty); 14108 assign(data, 14109 ty == Ity_I64 14110 // FIXME: assumes little-endian guest 14111 ? binop(Iop_32HLto64, getIRegA(rT+1), getIRegA(rT+0)) 14112 : narrow == Iop_INVALID 14113 ? getIRegA(rT) 14114 : unop(narrow, getIRegA(rT))); 14115 resSC1 = newTemp(Ity_I1); 14116 // FIXME: assumes little-endian guest 14117 stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegA(rN), mkexpr(data)) ); 14118 14119 /* Set rD to 1 on failure, 0 on success. Currently we have 14120 resSC1 == 0 on failure, 1 on success. */ 14121 resSC32 = newTemp(Ity_I32); 14122 assign(resSC32, 14123 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1)))); 14124 14125 putIRegA(rD, mkexpr(resSC32), 14126 IRTemp_INVALID, Ijk_Boring); 14127 if (ty == Ity_I64) { 14128 DIP("strex%s%s r%u, r%u, r%u, [r%u]\n", 14129 nm, nCC(INSN_COND), rD, rT, rT+1, rN); 14130 } else { 14131 DIP("strex%s%s r%u, r%u, [r%u]\n", 14132 nm, nCC(INSN_COND), rD, rT, rN); 14133 } 14134 goto decode_success; 14135 } 14136 /* fall through */ 14137 } 14138 14139 /* --------------------- movw, movt --------------------- */ 14140 if (0x03000000 == (insn & 0x0FF00000) 14141 || 0x03400000 == (insn & 0x0FF00000)) /* pray for CSE */ { 14142 UInt rD = INSN(15,12); 14143 UInt imm16 = (insn & 0xFFF) | ((insn >> 4) & 0x0000F000); 14144 UInt isT = (insn >> 22) & 1; 14145 if (rD == 15) { 14146 /* forget it */ 14147 } else { 14148 if (isT) { 14149 putIRegA(rD, 14150 binop(Iop_Or32, 14151 binop(Iop_And32, getIRegA(rD), mkU32(0xFFFF)), 14152 mkU32(imm16 << 16)), 14153 condT, Ijk_Boring); 14154 DIP("movt%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16); 14155 goto decode_success; 14156 } else { 14157 putIRegA(rD, mkU32(imm16), condT, Ijk_Boring); 14158 DIP("movw%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16); 14159 goto decode_success; 14160 } 14161 } 14162 /* fall through */ 14163 } 14164 14165 /* ----------- uxtb, sxtb, uxth, sxth, uxtb16, sxtb16 ----------- */ 14166 /* FIXME: this is an exact duplicate of the Thumb version. They 14167 should be commoned up. */ 14168 if (BITS8(0,1,1,0,1, 0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,0)) 14169 && BITS4(1,1,1,1) == INSN(19,16) 14170 && BITS4(0,1,1,1) == INSN(7,4) 14171 && BITS4(0,0, 0,0) == (INSN(11,8) & BITS4(0,0,1,1))) { 14172 UInt subopc = INSN(27,20) & BITS8(0,0,0,0,0, 1,1,1); 14173 if (subopc != BITS4(0,0,0,1) && subopc != BITS4(0,1,0,1)) { 14174 Int rot = (INSN(11,8) >> 2) & 3; 14175 UInt rM = INSN(3,0); 14176 UInt rD = INSN(15,12); 14177 IRTemp srcT = newTemp(Ity_I32); 14178 IRTemp rotT = newTemp(Ity_I32); 14179 IRTemp dstT = newTemp(Ity_I32); 14180 HChar* nm = "???"; 14181 assign(srcT, getIRegA(rM)); 14182 assign(rotT, genROR32(srcT, 8 * rot)); /* 0, 8, 16 or 24 only */ 14183 switch (subopc) { 14184 case BITS4(0,1,1,0): // UXTB 14185 assign(dstT, unop(Iop_8Uto32, unop(Iop_32to8, mkexpr(rotT)))); 14186 nm = "uxtb"; 14187 break; 14188 case BITS4(0,0,1,0): // SXTB 14189 assign(dstT, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rotT)))); 14190 nm = "sxtb"; 14191 break; 14192 case BITS4(0,1,1,1): // UXTH 14193 assign(dstT, unop(Iop_16Uto32, unop(Iop_32to16, mkexpr(rotT)))); 14194 nm = "uxth"; 14195 break; 14196 case BITS4(0,0,1,1): // SXTH 14197 assign(dstT, unop(Iop_16Sto32, unop(Iop_32to16, mkexpr(rotT)))); 14198 nm = "sxth"; 14199 break; 14200 case BITS4(0,1,0,0): // UXTB16 14201 assign(dstT, binop(Iop_And32, mkexpr(rotT), mkU32(0x00FF00FF))); 14202 nm = "uxtb16"; 14203 break; 14204 case BITS4(0,0,0,0): { // SXTB16 14205 IRTemp lo32 = newTemp(Ity_I32); 14206 IRTemp hi32 = newTemp(Ity_I32); 14207 assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF))); 14208 assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16))); 14209 assign( 14210 dstT, 14211 binop(Iop_Or32, 14212 binop(Iop_And32, 14213 unop(Iop_8Sto32, 14214 unop(Iop_32to8, mkexpr(lo32))), 14215 mkU32(0xFFFF)), 14216 binop(Iop_Shl32, 14217 unop(Iop_8Sto32, 14218 unop(Iop_32to8, mkexpr(hi32))), 14219 mkU8(16)) 14220 )); 14221 nm = "sxtb16"; 14222 break; 14223 } 14224 default: 14225 vassert(0); // guarded by "if" above 14226 } 14227 putIRegA(rD, mkexpr(dstT), condT, Ijk_Boring); 14228 DIP("%s%s r%u, r%u, ROR #%u\n", nm, nCC(INSN_COND), rD, rM, rot); 14229 goto decode_success; 14230 } 14231 /* fall through */ 14232 } 14233 14234 /* ------------------- bfi, bfc ------------------- */ 14235 if (BITS8(0,1,1,1,1,1,0, 0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0)) 14236 && BITS4(0, 0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) { 14237 UInt rD = INSN(15,12); 14238 UInt rN = INSN(3,0); 14239 UInt msb = (insn >> 16) & 0x1F; /* 20:16 */ 14240 UInt lsb = (insn >> 7) & 0x1F; /* 11:7 */ 14241 if (rD == 15 || msb < lsb) { 14242 /* undecodable; fall through */ 14243 } else { 14244 IRTemp src = newTemp(Ity_I32); 14245 IRTemp olddst = newTemp(Ity_I32); 14246 IRTemp newdst = newTemp(Ity_I32); 14247 UInt mask = 1 << (msb - lsb); 14248 mask = (mask - 1) + mask; 14249 vassert(mask != 0); // guaranteed by "msb < lsb" check above 14250 mask <<= lsb; 14251 14252 assign(src, rN == 15 ? mkU32(0) : getIRegA(rN)); 14253 assign(olddst, getIRegA(rD)); 14254 assign(newdst, 14255 binop(Iop_Or32, 14256 binop(Iop_And32, 14257 binop(Iop_Shl32, mkexpr(src), mkU8(lsb)), 14258 mkU32(mask)), 14259 binop(Iop_And32, 14260 mkexpr(olddst), 14261 mkU32(~mask))) 14262 ); 14263 14264 putIRegA(rD, mkexpr(newdst), condT, Ijk_Boring); 14265 14266 if (rN == 15) { 14267 DIP("bfc%s r%u, #%u, #%u\n", 14268 nCC(INSN_COND), rD, lsb, msb-lsb+1); 14269 } else { 14270 DIP("bfi%s r%u, r%u, #%u, #%u\n", 14271 nCC(INSN_COND), rD, rN, lsb, msb-lsb+1); 14272 } 14273 goto decode_success; 14274 } 14275 /* fall through */ 14276 } 14277 14278 /* ------------------- {u,s}bfx ------------------- */ 14279 if (BITS8(0,1,1,1,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0)) 14280 && BITS4(0,1,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) { 14281 UInt rD = INSN(15,12); 14282 UInt rN = INSN(3,0); 14283 UInt wm1 = (insn >> 16) & 0x1F; /* 20:16 */ 14284 UInt lsb = (insn >> 7) & 0x1F; /* 11:7 */ 14285 UInt msb = lsb + wm1; 14286 UInt isU = (insn >> 22) & 1; /* 22:22 */ 14287 if (rD == 15 || rN == 15 || msb >= 32) { 14288 /* undecodable; fall through */ 14289 } else { 14290 IRTemp src = newTemp(Ity_I32); 14291 IRTemp tmp = newTemp(Ity_I32); 14292 IRTemp res = newTemp(Ity_I32); 14293 UInt mask = ((1 << wm1) - 1) + (1 << wm1); 14294 vassert(msb >= 0 && msb <= 31); 14295 vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive 14296 14297 assign(src, getIRegA(rN)); 14298 assign(tmp, binop(Iop_And32, 14299 binop(Iop_Shr32, mkexpr(src), mkU8(lsb)), 14300 mkU32(mask))); 14301 assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32, 14302 binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)), 14303 mkU8(31-wm1))); 14304 14305 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 14306 14307 DIP("%s%s r%u, r%u, #%u, #%u\n", 14308 isU ? "ubfx" : "sbfx", 14309 nCC(INSN_COND), rD, rN, lsb, wm1 + 1); 14310 goto decode_success; 14311 } 14312 /* fall through */ 14313 } 14314 14315 /* --------------------- Load/store doubleword ------------- */ 14316 // LDRD STRD 14317 /* 31 27 23 19 15 11 7 3 # highest bit 14318 28 24 20 16 12 8 4 0 14319 A5-36 1 | 16 cond 0001 U100 Rn Rd im4h 11S1 im4l 14320 A5-38 1 | 32 cond 0001 U000 Rn Rd 0000 11S1 Rm 14321 A5-40 2 | 16 cond 0001 U110 Rn Rd im4h 11S1 im4l 14322 A5-42 2 | 32 cond 0001 U010 Rn Rd 0000 11S1 Rm 14323 A5-44 3 | 16 cond 0000 U100 Rn Rd im4h 11S1 im4l 14324 A5-46 3 | 32 cond 0000 U000 Rn Rd 0000 11S1 Rm 14325 */ 14326 /* case coding: 14327 1 at-ea (access at ea) 14328 2 at-ea-then-upd (access at ea, then Rn = ea) 14329 3 at-Rn-then-upd (access at Rn, then Rn = ea) 14330 ea coding 14331 16 Rn +/- imm8 14332 32 Rn +/- Rm 14333 */ 14334 /* Quickly skip over all of this for hopefully most instructions */ 14335 if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0)) 14336 goto after_load_store_doubleword; 14337 14338 /* Check the "11S1" thing. */ 14339 if ((INSN(7,4) & BITS4(1,1,0,1)) != BITS4(1,1,0,1)) 14340 goto after_load_store_doubleword; 14341 14342 summary = 0; 14343 14344 /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,0,0)) { 14345 summary = 1 | 16; 14346 } 14347 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,0,0)) { 14348 summary = 1 | 32; 14349 } 14350 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,1,0)) { 14351 summary = 2 | 16; 14352 } 14353 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,1,0)) { 14354 summary = 2 | 32; 14355 } 14356 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(1,0,0)) { 14357 summary = 3 | 16; 14358 } 14359 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(0,0,0)) { 14360 summary = 3 | 32; 14361 } 14362 else goto after_load_store_doubleword; 14363 14364 { UInt rN = (insn >> 16) & 0xF; /* 19:16 */ 14365 UInt rD = (insn >> 12) & 0xF; /* 15:12 */ 14366 UInt rM = (insn >> 0) & 0xF; /* 3:0 */ 14367 UInt bU = (insn >> 23) & 1; /* 23 U=1 offset+, U=0 offset- */ 14368 UInt bS = (insn >> 5) & 1; /* S=1 store, S=0 load */ 14369 UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */ 14370 14371 /* Require rD to be an even numbered register */ 14372 if ((rD & 1) != 0) 14373 goto after_load_store_doubleword; 14374 14375 /* Require 11:8 == 0 for Rn +/- Rm cases */ 14376 if ((summary & 32) != 0 && (imm8 & 0xF0) != 0) 14377 goto after_load_store_doubleword; 14378 14379 /* Skip some invalid cases, which would lead to two competing 14380 updates to the same register, or which are otherwise 14381 disallowed by the spec. */ 14382 switch (summary) { 14383 case 1 | 16: 14384 break; 14385 case 1 | 32: 14386 if (rM == 15) goto after_load_store_doubleword; 14387 break; 14388 case 2 | 16: case 3 | 16: 14389 if (rN == 15) goto after_load_store_doubleword; 14390 if (bS == 0 && (rN == rD || rN == rD+1)) 14391 goto after_load_store_doubleword; 14392 break; 14393 case 2 | 32: case 3 | 32: 14394 if (rM == 15) goto after_load_store_doubleword; 14395 if (rN == 15) goto after_load_store_doubleword; 14396 if (rN == rM) goto after_load_store_doubleword; 14397 if (bS == 0 && (rN == rD || rN == rD+1)) 14398 goto after_load_store_doubleword; 14399 break; 14400 default: 14401 vassert(0); 14402 } 14403 14404 /* Now, we can't do a conditional load or store, since that very 14405 likely will generate an exception. So we have to take a side 14406 exit at this point if the condition is false. */ 14407 if (condT != IRTemp_INVALID) { 14408 mk_skip_over_A32_if_cond_is_false( condT ); 14409 condT = IRTemp_INVALID; 14410 } 14411 /* Ok, now we're unconditional. Do the load or store. */ 14412 14413 /* compute the effective address. Bind it to a tmp since we 14414 may need to use it twice. */ 14415 IRExpr* eaE = NULL; 14416 switch (summary & 0xF0) { 14417 case 16: 14418 eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf ); 14419 break; 14420 case 32: 14421 eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf ); 14422 break; 14423 } 14424 vassert(eaE); 14425 IRTemp eaT = newTemp(Ity_I32); 14426 assign(eaT, eaE); 14427 14428 /* get the old Rn value */ 14429 IRTemp rnT = newTemp(Ity_I32); 14430 assign(rnT, getIRegA(rN)); 14431 14432 /* decide on the transfer address */ 14433 IRTemp taT = IRTemp_INVALID; 14434 switch (summary & 0x0F) { 14435 case 1: case 2: taT = eaT; break; 14436 case 3: taT = rnT; break; 14437 } 14438 vassert(taT != IRTemp_INVALID); 14439 14440 /* XXX deal with alignment constraints */ 14441 /* XXX: but the A8 doesn't seem to trap for misaligned loads, so, 14442 ignore alignment issues for the time being. */ 14443 14444 /* doubleword store S 1 14445 doubleword load S 0 14446 */ 14447 HChar* name = NULL; 14448 /* generate the transfers */ 14449 if (bS == 1) { // doubleword store 14450 storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(0)), getIRegA(rD+0) ); 14451 storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(4)), getIRegA(rD+1) ); 14452 name = "strd"; 14453 } else { // doubleword load 14454 putIRegA( rD+0, 14455 loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(0))), 14456 IRTemp_INVALID, Ijk_Boring ); 14457 putIRegA( rD+1, 14458 loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(4))), 14459 IRTemp_INVALID, Ijk_Boring ); 14460 name = "ldrd"; 14461 } 14462 14463 /* Update Rn if necessary. */ 14464 switch (summary & 0x0F) { 14465 case 2: case 3: 14466 // should be assured by logic above: 14467 if (bS == 0) { 14468 vassert(rD+0 != rN); /* since we just wrote rD+0 */ 14469 vassert(rD+1 != rN); /* since we just wrote rD+1 */ 14470 } 14471 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring ); 14472 break; 14473 } 14474 14475 switch (summary & 0x0F) { 14476 case 1: DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf); 14477 break; 14478 case 2: DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n", 14479 name, nCC(INSN_COND), rD, dis_buf); 14480 break; 14481 case 3: DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n", 14482 name, nCC(INSN_COND), rD, dis_buf); 14483 break; 14484 default: vassert(0); 14485 } 14486 14487 goto decode_success; 14488 } 14489 14490 after_load_store_doubleword: 14491 14492 /* ------------------- {s,u}xtab ------------- */ 14493 if (BITS8(0,1,1,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 14494 && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1)) 14495 && BITS4(0,1,1,1) == INSN(7,4)) { 14496 UInt rN = INSN(19,16); 14497 UInt rD = INSN(15,12); 14498 UInt rM = INSN(3,0); 14499 UInt rot = (insn >> 10) & 3; 14500 UInt isU = INSN(22,22); 14501 if (rN == 15/*it's {S,U}XTB*/ || rD == 15 || rM == 15) { 14502 /* undecodable; fall through */ 14503 } else { 14504 IRTemp srcL = newTemp(Ity_I32); 14505 IRTemp srcR = newTemp(Ity_I32); 14506 IRTemp res = newTemp(Ity_I32); 14507 assign(srcR, getIRegA(rM)); 14508 assign(srcL, getIRegA(rN)); 14509 assign(res, binop(Iop_Add32, 14510 mkexpr(srcL), 14511 unop(isU ? Iop_8Uto32 : Iop_8Sto32, 14512 unop(Iop_32to8, 14513 genROR32(srcR, 8 * rot))))); 14514 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 14515 DIP("%cxtab%s r%u, r%u, r%u, ror #%u\n", 14516 isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot); 14517 goto decode_success; 14518 } 14519 /* fall through */ 14520 } 14521 14522 /* ------------------- {s,u}xtah ------------- */ 14523 if (BITS8(0,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 14524 && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1)) 14525 && BITS4(0,1,1,1) == INSN(7,4)) { 14526 UInt rN = INSN(19,16); 14527 UInt rD = INSN(15,12); 14528 UInt rM = INSN(3,0); 14529 UInt rot = (insn >> 10) & 3; 14530 UInt isU = INSN(22,22); 14531 if (rN == 15/*it's {S,U}XTH*/ || rD == 15 || rM == 15) { 14532 /* undecodable; fall through */ 14533 } else { 14534 IRTemp srcL = newTemp(Ity_I32); 14535 IRTemp srcR = newTemp(Ity_I32); 14536 IRTemp res = newTemp(Ity_I32); 14537 assign(srcR, getIRegA(rM)); 14538 assign(srcL, getIRegA(rN)); 14539 assign(res, binop(Iop_Add32, 14540 mkexpr(srcL), 14541 unop(isU ? Iop_16Uto32 : Iop_16Sto32, 14542 unop(Iop_32to16, 14543 genROR32(srcR, 8 * rot))))); 14544 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 14545 14546 DIP("%cxtah%s r%u, r%u, r%u, ror #%u\n", 14547 isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot); 14548 goto decode_success; 14549 } 14550 /* fall through */ 14551 } 14552 14553 /* ------------------- rev16, rev ------------------ */ 14554 if (INSN(27,16) == 0x6BF 14555 && (INSN(11,4) == 0xFB/*rev16*/ || INSN(11,4) == 0xF3/*rev*/)) { 14556 Bool isREV = INSN(11,4) == 0xF3; 14557 UInt rM = INSN(3,0); 14558 UInt rD = INSN(15,12); 14559 if (rM != 15 && rD != 15) { 14560 IRTemp rMt = newTemp(Ity_I32); 14561 assign(rMt, getIRegA(rM)); 14562 IRTemp res = isREV ? gen_REV(rMt) : gen_REV16(rMt); 14563 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 14564 DIP("rev%s%s r%u, r%u\n", isREV ? "" : "16", 14565 nCC(INSN_COND), rD, rM); 14566 goto decode_success; 14567 } 14568 } 14569 14570 /* ------------------- rbit ------------------ */ 14571 if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) { 14572 UInt rD = INSN(15,12); 14573 UInt rM = INSN(3,0); 14574 if (rD != 15 && rM != 15) { 14575 IRTemp arg = newTemp(Ity_I32); 14576 assign(arg, getIRegA(rM)); 14577 IRTemp res = gen_BITREV(arg); 14578 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 14579 DIP("rbit r%u, r%u\n", rD, rM); 14580 goto decode_success; 14581 } 14582 } 14583 14584 /* ------------------- smmul ------------------ */ 14585 if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1) 14586 && INSN(15,12) == BITS4(1,1,1,1) 14587 && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) { 14588 UInt bitR = INSN(5,5); 14589 UInt rD = INSN(19,16); 14590 UInt rM = INSN(11,8); 14591 UInt rN = INSN(3,0); 14592 if (rD != 15 && rM != 15 && rN != 15) { 14593 IRExpr* res 14594 = unop(Iop_64HIto32, 14595 binop(Iop_Add64, 14596 binop(Iop_MullS32, getIRegA(rN), getIRegA(rM)), 14597 mkU64(bitR ? 0x80000000ULL : 0ULL))); 14598 putIRegA(rD, res, condT, Ijk_Boring); 14599 DIP("smmul%s%s r%u, r%u, r%u\n", 14600 nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM); 14601 goto decode_success; 14602 } 14603 } 14604 14605 /* ------------------- smmla ------------------ */ 14606 if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1) 14607 && INSN(15,12) != BITS4(1,1,1,1) 14608 && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) { 14609 UInt bitR = INSN(5,5); 14610 UInt rD = INSN(19,16); 14611 UInt rA = INSN(15,12); 14612 UInt rM = INSN(11,8); 14613 UInt rN = INSN(3,0); 14614 if (rD != 15 && rM != 15 && rN != 15) { 14615 IRExpr* res 14616 = unop(Iop_64HIto32, 14617 binop(Iop_Add64, 14618 binop(Iop_Add64, 14619 binop(Iop_32HLto64, getIRegA(rA), mkU32(0)), 14620 binop(Iop_MullS32, getIRegA(rN), getIRegA(rM))), 14621 mkU64(bitR ? 0x80000000ULL : 0ULL))); 14622 putIRegA(rD, res, condT, Ijk_Boring); 14623 DIP("smmla%s%s r%u, r%u, r%u, r%u\n", 14624 nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM, rA); 14625 goto decode_success; 14626 } 14627 } 14628 14629 /* ------------------- NOP ------------------ */ 14630 if (0x0320F000 == (insn & 0x0FFFFFFF)) { 14631 DIP("nop%s\n", nCC(INSN_COND)); 14632 goto decode_success; 14633 } 14634 14635 /* ----------------------------------------------------------- */ 14636 /* -- ARMv7 instructions -- */ 14637 /* ----------------------------------------------------------- */ 14638 14639 /* -------------- read CP15 TPIDRURO register ------------- */ 14640 /* mrc p15, 0, r0, c13, c0, 3 up to 14641 mrc p15, 0, r14, c13, c0, 3 14642 */ 14643 /* I don't know whether this is really v7-only. But anyway, we 14644 have to support it since arm-linux uses TPIDRURO as a thread 14645 state register. */ 14646 if (0x0E1D0F70 == (insn & 0x0FFF0FFF)) { 14647 UInt rD = INSN(15,12); 14648 if (rD <= 14) { 14649 /* skip r15, that's too stupid to handle */ 14650 putIRegA(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), 14651 condT, Ijk_Boring); 14652 DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND), rD); 14653 goto decode_success; 14654 } 14655 /* fall through */ 14656 } 14657 14658 /* Handle various kinds of barriers. This is rather indiscriminate 14659 in the sense that they are all turned into an IR Fence, which 14660 means we don't know which they are, so the back end has to 14661 re-emit them all when it comes acrosss an IR Fence. 14662 */ 14663 /* v6 */ /* mcr 15, 0, rT, c7, c10, 5 */ 14664 if (0xEE070FBA == (insn & 0xFFFF0FFF)) { 14665 UInt rT = INSN(15,12); 14666 if (rT <= 14) { 14667 /* mcr 15, 0, rT, c7, c10, 5 (v6) equiv to DMB (v7). Data 14668 Memory Barrier -- ensures ordering of memory accesses. */ 14669 stmt( IRStmt_MBE(Imbe_Fence) ); 14670 DIP("mcr 15, 0, r%u, c7, c10, 5 (data memory barrier)\n", rT); 14671 goto decode_success; 14672 } 14673 /* fall through */ 14674 } 14675 /* other flavours of barrier */ 14676 switch (insn) { 14677 case 0xEE070F9A: /* v6 */ 14678 /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7). Data 14679 Synch Barrier -- ensures completion of memory accesses. */ 14680 stmt( IRStmt_MBE(Imbe_Fence) ); 14681 DIP("mcr 15, 0, r0, c7, c10, 4 (data synch barrier)\n"); 14682 goto decode_success; 14683 case 0xEE070F95: /* v6 */ 14684 /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7). 14685 Instruction Synchronisation Barrier (or Flush Prefetch 14686 Buffer) -- a pipe flush, I think. I suspect we could 14687 ignore those, but to be on the safe side emit a fence 14688 anyway. */ 14689 stmt( IRStmt_MBE(Imbe_Fence) ); 14690 DIP("mcr 15, 0, r0, c7, c5, 4 (insn synch barrier)\n"); 14691 goto decode_success; 14692 default: 14693 break; 14694 } 14695 14696 /* ----------------------------------------------------------- */ 14697 /* -- VFP (CP 10, CP 11) instructions (in ARM mode) -- */ 14698 /* ----------------------------------------------------------- */ 14699 14700 if (INSN_COND != ARMCondNV) { 14701 Bool ok_vfp = decode_CP10_CP11_instruction ( 14702 &dres, INSN(27,0), condT, INSN_COND, 14703 False/*!isT*/ 14704 ); 14705 if (ok_vfp) 14706 goto decode_success; 14707 } 14708 14709 /* ----------------------------------------------------------- */ 14710 /* -- NEON instructions (in ARM mode) -- */ 14711 /* ----------------------------------------------------------- */ 14712 14713 /* These are all in NV space, and so are taken care of (far) above, 14714 by a call from this function to decode_NV_instruction(). */ 14715 14716 /* ----------------------------------------------------------- */ 14717 /* -- v6 media instructions (in ARM mode) -- */ 14718 /* ----------------------------------------------------------- */ 14719 14720 { Bool ok_v6m = decode_V6MEDIA_instruction( 14721 &dres, INSN(27,0), condT, INSN_COND, 14722 False/*!isT*/ 14723 ); 14724 if (ok_v6m) 14725 goto decode_success; 14726 } 14727 14728 /* ----------------------------------------------------------- */ 14729 /* -- Undecodable -- */ 14730 /* ----------------------------------------------------------- */ 14731 14732 goto decode_failure; 14733 /*NOTREACHED*/ 14734 14735 decode_failure: 14736 /* All decode failures end up here. */ 14737 vex_printf("disInstr(arm): unhandled instruction: " 14738 "0x%x\n", insn); 14739 vex_printf(" cond=%d(0x%x) 27:20=%u(0x%02x) " 14740 "4:4=%d " 14741 "3:0=%u(0x%x)\n", 14742 (Int)INSN_COND, (UInt)INSN_COND, 14743 (Int)INSN(27,20), (UInt)INSN(27,20), 14744 (Int)INSN(4,4), 14745 (Int)INSN(3,0), (UInt)INSN(3,0) ); 14746 14747 /* Tell the dispatcher that this insn cannot be decoded, and so has 14748 not been executed, and (is currently) the next to be executed. 14749 R15 should be up-to-date since it made so at the start of each 14750 insn, but nevertheless be paranoid and update it again right 14751 now. */ 14752 vassert(0 == (guest_R15_curr_instr_notENC & 3)); 14753 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) ); 14754 dres.whatNext = Dis_StopHere; 14755 dres.jk_StopHere = Ijk_NoDecode; 14756 dres.len = 0; 14757 return dres; 14758 14759 decode_success: 14760 /* All decode successes end up here. */ 14761 DIP("\n"); 14762 14763 vassert(dres.len == 4 || dres.len == 20); 14764 14765 /* Now then. Do we have an implicit jump to r15 to deal with? */ 14766 if (r15written) { 14767 /* If we get jump to deal with, we assume that there's been no 14768 other competing branch stuff previously generated for this 14769 insn. That's reasonable, in the sense that the ARM insn set 14770 appears to declare as "Unpredictable" any instruction which 14771 generates more than one possible new value for r15. Hence 14772 just assert. The decoders themselves should check against 14773 all such instructions which are thusly Unpredictable, and 14774 decline to decode them. Hence we should never get here if we 14775 have competing new values for r15, and hence it is safe to 14776 assert here. */ 14777 vassert(dres.whatNext == Dis_Continue); 14778 vassert(irsb->next == NULL); 14779 vassert(irsb->jumpkind == Ijk_Boring); 14780 /* If r15 is unconditionally written, terminate the block by 14781 jumping to it. If it's conditionally written, still 14782 terminate the block (a shame, but we can't do side exits to 14783 arbitrary destinations), but first jump to the next 14784 instruction if the condition doesn't hold. */ 14785 /* We can't use getIReg(15) to get the destination, since that 14786 will produce r15+8, which isn't what we want. Must use 14787 llGetIReg(15) instead. */ 14788 if (r15guard == IRTemp_INVALID) { 14789 /* unconditional */ 14790 } else { 14791 /* conditional */ 14792 stmt( IRStmt_Exit( 14793 unop(Iop_32to1, 14794 binop(Iop_Xor32, 14795 mkexpr(r15guard), mkU32(1))), 14796 r15kind, 14797 IRConst_U32(guest_R15_curr_instr_notENC + 4), 14798 OFFB_R15T 14799 )); 14800 } 14801 /* This seems crazy, but we're required to finish the insn with 14802 a write to the guest PC. As usual we rely on ir_opt to tidy 14803 up later. */ 14804 llPutIReg(15, llGetIReg(15)); 14805 dres.whatNext = Dis_StopHere; 14806 dres.jk_StopHere = r15kind; 14807 } else { 14808 /* Set up the end-state in the normal way. */ 14809 switch (dres.whatNext) { 14810 case Dis_Continue: 14811 llPutIReg(15, mkU32(dres.len + guest_R15_curr_instr_notENC)); 14812 break; 14813 case Dis_ResteerU: 14814 case Dis_ResteerC: 14815 llPutIReg(15, mkU32(dres.continueAt)); 14816 break; 14817 case Dis_StopHere: 14818 break; 14819 default: 14820 vassert(0); 14821 } 14822 } 14823 14824 return dres; 14825 14826 # undef INSN_COND 14827 # undef INSN 14828 } 14829 14830 14831 /*------------------------------------------------------------*/ 14832 /*--- Disassemble a single Thumb2 instruction ---*/ 14833 /*------------------------------------------------------------*/ 14834 14835 static const UChar it_length_table[256]; /* fwds */ 14836 14837 /* NB: in Thumb mode we do fetches of regs with getIRegT, which 14838 automagically adds 4 to fetches of r15. However, writes to regs 14839 are done with putIRegT, which disallows writes to r15. Hence any 14840 r15 writes and associated jumps have to be done "by hand". */ 14841 14842 /* Disassemble a single Thumb instruction into IR. The instruction is 14843 located in host memory at guest_instr, and has (decoded) guest IP 14844 of guest_R15_curr_instr_notENC, which will have been set before the 14845 call here. */ 14846 14847 static 14848 DisResult disInstr_THUMB_WRK ( 14849 Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ), 14850 Bool resteerCisOk, 14851 void* callback_opaque, 14852 UChar* guest_instr, 14853 VexArchInfo* archinfo, 14854 VexAbiInfo* abiinfo 14855 ) 14856 { 14857 /* A macro to fish bits out of insn0. There's also INSN1, to fish 14858 bits out of insn1, but that's defined only after the end of the 14859 16-bit insn decoder, so as to stop it mistakenly being used 14860 therein. */ 14861 # define INSN0(_bMax,_bMin) SLICE_UInt(((UInt)insn0), (_bMax), (_bMin)) 14862 14863 DisResult dres; 14864 UShort insn0; /* first 16 bits of the insn */ 14865 UShort insn1; /* second 16 bits of the insn */ 14866 //Bool allow_VFP = False; 14867 //UInt hwcaps = archinfo->hwcaps; 14868 HChar dis_buf[128]; // big enough to hold LDMIA etc text 14869 14870 /* Summary result of the ITxxx backwards analysis: False == safe 14871 but suboptimal. */ 14872 Bool guaranteedUnconditional = False; 14873 14874 /* What insn variants are we supporting today? */ 14875 //allow_VFP = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP)); 14876 // etc etc 14877 14878 /* Set result defaults. */ 14879 dres.whatNext = Dis_Continue; 14880 dres.len = 2; 14881 dres.continueAt = 0; 14882 dres.jk_StopHere = Ijk_INVALID; 14883 14884 /* Set default actions for post-insn handling of writes to r15, if 14885 required. */ 14886 r15written = False; 14887 r15guard = IRTemp_INVALID; /* unconditional */ 14888 r15kind = Ijk_Boring; 14889 14890 /* Insns could be 2 or 4 bytes long. Just get the first 16 bits at 14891 this point. If we need the second 16, get them later. We can't 14892 get them both out immediately because it risks a fault (very 14893 unlikely, but ..) if the second 16 bits aren't actually 14894 necessary. */ 14895 insn0 = getUShortLittleEndianly( guest_instr ); 14896 insn1 = 0; /* We'll get it later, once we know we need it. */ 14897 14898 /* Similarly, will set this later. */ 14899 IRTemp old_itstate = IRTemp_INVALID; 14900 14901 if (0) vex_printf("insn: 0x%x\n", insn0); 14902 14903 DIP("\t(thumb) 0x%x: ", (UInt)guest_R15_curr_instr_notENC); 14904 14905 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 14906 14907 /* ----------------------------------------------------------- */ 14908 /* Spot "Special" instructions (see comment at top of file). */ 14909 { 14910 UChar* code = (UChar*)guest_instr; 14911 /* Spot the 16-byte preamble: 14912 14913 ea4f 0cfc mov.w ip, ip, ror #3 14914 ea4f 3c7c mov.w ip, ip, ror #13 14915 ea4f 7c7c mov.w ip, ip, ror #29 14916 ea4f 4cfc mov.w ip, ip, ror #19 14917 */ 14918 UInt word1 = 0x0CFCEA4F; 14919 UInt word2 = 0x3C7CEA4F; 14920 UInt word3 = 0x7C7CEA4F; 14921 UInt word4 = 0x4CFCEA4F; 14922 if (getUIntLittleEndianly(code+ 0) == word1 && 14923 getUIntLittleEndianly(code+ 4) == word2 && 14924 getUIntLittleEndianly(code+ 8) == word3 && 14925 getUIntLittleEndianly(code+12) == word4) { 14926 /* Got a "Special" instruction preamble. Which one is it? */ 14927 // 0x 0A 0A EA 4A 14928 if (getUIntLittleEndianly(code+16) == 0x0A0AEA4A 14929 /* orr.w r10,r10,r10 */) { 14930 /* R3 = client_request ( R4 ) */ 14931 DIP("r3 = client_request ( %%r4 )\n"); 14932 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 )); 14933 dres.jk_StopHere = Ijk_ClientReq; 14934 dres.whatNext = Dis_StopHere; 14935 goto decode_success; 14936 } 14937 else 14938 // 0x 0B 0B EA 4B 14939 if (getUIntLittleEndianly(code+16) == 0x0B0BEA4B 14940 /* orr r11,r11,r11 */) { 14941 /* R3 = guest_NRADDR */ 14942 DIP("r3 = guest_NRADDR\n"); 14943 dres.len = 20; 14944 llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 )); 14945 goto decode_success; 14946 } 14947 else 14948 // 0x 0C 0C EA 4C 14949 if (getUIntLittleEndianly(code+16) == 0x0C0CEA4C 14950 /* orr r12,r12,r12 */) { 14951 /* branch-and-link-to-noredir R4 */ 14952 DIP("branch-and-link-to-noredir r4\n"); 14953 llPutIReg(14, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 )); 14954 llPutIReg(15, getIRegT(4)); 14955 dres.jk_StopHere = Ijk_NoRedir; 14956 dres.whatNext = Dis_StopHere; 14957 goto decode_success; 14958 } 14959 /* We don't know what it is. Set insn0 so decode_failure 14960 can print the insn following the Special-insn preamble. */ 14961 insn0 = getUShortLittleEndianly(code+16); 14962 goto decode_failure; 14963 /*NOTREACHED*/ 14964 } 14965 14966 } 14967 14968 /* ----------------------------------------------------------- */ 14969 14970 /* Main Thumb instruction decoder starts here. It's a series of 14971 switches which examine ever longer bit sequences at the MSB of 14972 the instruction word, first for 16-bit insns, then for 32-bit 14973 insns. */ 14974 14975 /* --- BEGIN ITxxx optimisation analysis --- */ 14976 /* This is a crucial optimisation for the ITState boilerplate that 14977 follows. Examine the 9 halfwords preceding this instruction, 14978 and if we are absolutely sure that none of them constitute an 14979 'it' instruction, then we can be sure that this instruction is 14980 not under the control of any 'it' instruction, and so 14981 guest_ITSTATE must be zero. So write zero into ITSTATE right 14982 now, so that iropt can fold out almost all of the resulting 14983 junk. 14984 14985 If we aren't sure, we can always safely skip this step. So be a 14986 bit conservative about it: only poke around in the same page as 14987 this instruction, lest we get a fault from the previous page 14988 that would not otherwise have happened. The saving grace is 14989 that such skipping is pretty rare -- it only happens, 14990 statistically, 18/4096ths of the time, so is judged unlikely to 14991 be a performance problems. 14992 14993 FIXME: do better. Take into account the number of insns covered 14994 by any IT insns we find, to rule out cases where an IT clearly 14995 cannot cover this instruction. This would improve behaviour for 14996 branch targets immediately following an IT-guarded group that is 14997 not of full length. Eg, (and completely ignoring issues of 16- 14998 vs 32-bit insn length): 14999 15000 ite cond 15001 insn1 15002 insn2 15003 label: insn3 15004 insn4 15005 15006 The 'it' only conditionalises insn1 and insn2. However, the 15007 current analysis is conservative and considers insn3 and insn4 15008 also possibly guarded. Hence if 'label:' is the start of a hot 15009 loop we will get a big performance hit. 15010 */ 15011 { 15012 /* Summary result of this analysis: False == safe but 15013 suboptimal. */ 15014 vassert(guaranteedUnconditional == False); 15015 15016 UInt pc = guest_R15_curr_instr_notENC; 15017 vassert(0 == (pc & 1)); 15018 15019 UInt pageoff = pc & 0xFFF; 15020 if (pageoff >= 18) { 15021 /* It's safe to poke about in the 9 halfwords preceding this 15022 insn. So, have a look at them. */ 15023 guaranteedUnconditional = True; /* assume no 'it' insn found, 15024 till we do */ 15025 UShort* hwp = (UShort*)(HWord)pc; 15026 Int i; 15027 for (i = -1; i >= -9; i--) { 15028 /* We're in the same page. (True, but commented out due 15029 to expense.) */ 15030 /* 15031 vassert( ( ((UInt)(&hwp[i])) & 0xFFFFF000 ) 15032 == ( pc & 0xFFFFF000 ) ); 15033 */ 15034 /* All valid IT instructions must have the form 0xBFxy, 15035 where x can be anything, but y must be nonzero. Find 15036 the number of insns covered by it (1 .. 4) and check to 15037 see if it can possibly reach up to the instruction in 15038 question. Some (x,y) combinations mean UNPREDICTABLE, 15039 and the table is constructed to be conservative by 15040 returning 4 for those cases, so the analysis is safe 15041 even if the code uses unpredictable IT instructions (in 15042 which case its authors are nuts, but hey.) */ 15043 UShort hwp_i = hwp[i]; 15044 if (UNLIKELY((hwp_i & 0xFF00) == 0xBF00 && (hwp_i & 0xF) != 0)) { 15045 /* might be an 'it' insn. */ 15046 /* # guarded insns */ 15047 Int n_guarded = (Int)it_length_table[hwp_i & 0xFF]; 15048 vassert(n_guarded >= 1 && n_guarded <= 4); 15049 if (n_guarded * 2 /* # guarded HWs, worst case */ 15050 > (-(i+1))) /* -(i+1): # remaining HWs after the IT */ 15051 /* -(i+0) also seems to work, even though I think 15052 it's wrong. I don't understand that. */ 15053 guaranteedUnconditional = False; 15054 break; 15055 } 15056 } 15057 } 15058 } 15059 /* --- END ITxxx optimisation analysis --- */ 15060 15061 /* Generate the guarding condition for this insn, by examining 15062 ITSTATE. Assign it to condT. Also, generate new 15063 values for ITSTATE ready for stuffing back into the 15064 guest state, but don't actually do the Put yet, since it will 15065 need to stuffed back in only after the instruction gets to a 15066 point where it is sure to complete. Mostly we let the code at 15067 decode_success handle this, but in cases where the insn contains 15068 a side exit, we have to update them before the exit. */ 15069 15070 /* If the ITxxx optimisation analysis above could not prove that 15071 this instruction is guaranteed unconditional, we insert a 15072 lengthy IR preamble to compute the guarding condition at 15073 runtime. If it can prove it (which obviously we hope is the 15074 normal case) then we insert a minimal preamble, which is 15075 equivalent to setting guest_ITSTATE to zero and then folding 15076 that through the full preamble (which completely disappears). */ 15077 15078 IRTemp condT = IRTemp_INVALID; 15079 IRTemp cond_AND_notInIT_T = IRTemp_INVALID; 15080 15081 IRTemp new_itstate = IRTemp_INVALID; 15082 vassert(old_itstate == IRTemp_INVALID); 15083 15084 if (guaranteedUnconditional) { 15085 /* BEGIN "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */ 15086 15087 // ITSTATE = 0 :: I32 15088 IRTemp z32 = newTemp(Ity_I32); 15089 assign(z32, mkU32(0)); 15090 put_ITSTATE(z32); 15091 15092 // old_itstate = 0 :: I32 15093 // 15094 // old_itstate = get_ITSTATE(); 15095 old_itstate = z32; /* 0 :: I32 */ 15096 15097 // new_itstate = old_itstate >> 8 15098 // = 0 >> 8 15099 // = 0 :: I32 15100 // 15101 // new_itstate = newTemp(Ity_I32); 15102 // assign(new_itstate, 15103 // binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8))); 15104 new_itstate = z32; 15105 15106 // ITSTATE = 0 :: I32(again) 15107 // 15108 // put_ITSTATE(new_itstate); 15109 15110 // condT1 = calc_cond_dyn( xor(and(old_istate,0xF0), 0xE0) ) 15111 // = calc_cond_dyn( xor(0,0xE0) ) 15112 // = calc_cond_dyn ( 0xE0 ) 15113 // = 1 :: I32 15114 // Not that this matters, since the computed value is not used: 15115 // see condT folding below 15116 // 15117 // IRTemp condT1 = newTemp(Ity_I32); 15118 // assign(condT1, 15119 // mk_armg_calculate_condition_dyn( 15120 // binop(Iop_Xor32, 15121 // binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)), 15122 // mkU32(0xE0)) 15123 // ) 15124 // ); 15125 15126 // condT = 32to8(and32(old_itstate,0xF0)) == 0 ? 1 : condT1 15127 // = 32to8(and32(0,0xF0)) == 0 ? 1 : condT1 15128 // = 32to8(0) == 0 ? 1 : condT1 15129 // = 0 == 0 ? 1 : condT1 15130 // = 1 15131 // 15132 // condT = newTemp(Ity_I32); 15133 // assign(condT, IRExpr_Mux0X( 15134 // unop(Iop_32to8, binop(Iop_And32, 15135 // mkexpr(old_itstate), 15136 // mkU32(0xF0))), 15137 // mkU32(1), 15138 // mkexpr(condT1) 15139 // )); 15140 condT = newTemp(Ity_I32); 15141 assign(condT, mkU32(1)); 15142 15143 // notInITt = xor32(and32(old_itstate, 1), 1) 15144 // = xor32(and32(0, 1), 1) 15145 // = xor32(0, 1) 15146 // = 1 :: I32 15147 // 15148 // IRTemp notInITt = newTemp(Ity_I32); 15149 // assign(notInITt, 15150 // binop(Iop_Xor32, 15151 // binop(Iop_And32, mkexpr(old_itstate), mkU32(1)), 15152 // mkU32(1))); 15153 15154 // cond_AND_notInIT_T = and32(notInITt, condT) 15155 // = and32(1, 1) 15156 // = 1 15157 // 15158 // cond_AND_notInIT_T = newTemp(Ity_I32); 15159 // assign(cond_AND_notInIT_T, 15160 // binop(Iop_And32, mkexpr(notInITt), mkexpr(condT))); 15161 cond_AND_notInIT_T = condT; /* 1 :: I32 */ 15162 15163 /* END "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */ 15164 } else { 15165 /* BEGIN { STANDARD PREAMBLE; } */ 15166 15167 old_itstate = get_ITSTATE(); 15168 15169 new_itstate = newTemp(Ity_I32); 15170 assign(new_itstate, 15171 binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8))); 15172 15173 put_ITSTATE(new_itstate); 15174 15175 /* Same strategy as for ARM insns: generate a condition 15176 temporary at this point (or IRTemp_INVALID, meaning 15177 unconditional). We leave it to lower-level instruction 15178 decoders to decide whether they can generate straight-line 15179 code, or whether they must generate a side exit before the 15180 instruction. condT :: Ity_I32 and is always either zero or 15181 one. */ 15182 IRTemp condT1 = newTemp(Ity_I32); 15183 assign(condT1, 15184 mk_armg_calculate_condition_dyn( 15185 binop(Iop_Xor32, 15186 binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)), 15187 mkU32(0xE0)) 15188 ) 15189 ); 15190 15191 /* This is a bit complex, but needed to make Memcheck understand 15192 that, if the condition in old_itstate[7:4] denotes AL (that 15193 is, if this instruction is to be executed unconditionally), 15194 then condT does not depend on the results of calling the 15195 helper. 15196 15197 We test explicitly for old_itstate[7:4] == AL ^ 0xE, and in 15198 that case set condT directly to 1. Else we use the results 15199 of the helper. Since old_itstate is always defined and 15200 because Memcheck does lazy V-bit propagation through Mux0X, 15201 this will cause condT to always be a defined 1 if the 15202 condition is 'AL'. From an execution semantics point of view 15203 this is irrelevant since we're merely duplicating part of the 15204 behaviour of the helper. But it makes it clear to Memcheck, 15205 in this case, that condT does not in fact depend on the 15206 contents of the condition code thunk. Without it, we get 15207 quite a lot of false errors. 15208 15209 So, just to clarify: from a straight semantics point of view, 15210 we can simply do "assign(condT, mkexpr(condT1))", and the 15211 simulator still runs fine. It's just that we get loads of 15212 false errors from Memcheck. */ 15213 condT = newTemp(Ity_I32); 15214 assign(condT, IRExpr_Mux0X( 15215 unop(Iop_32to8, binop(Iop_And32, 15216 mkexpr(old_itstate), 15217 mkU32(0xF0))), 15218 mkU32(1), 15219 mkexpr(condT1) 15220 )); 15221 15222 /* Something we don't have in ARM: generate a 0 or 1 value 15223 indicating whether or not we are in an IT block (NB: 0 = in 15224 IT block, 1 = not in IT block). This is used to gate 15225 condition code updates in 16-bit Thumb instructions. */ 15226 IRTemp notInITt = newTemp(Ity_I32); 15227 assign(notInITt, 15228 binop(Iop_Xor32, 15229 binop(Iop_And32, mkexpr(old_itstate), mkU32(1)), 15230 mkU32(1))); 15231 15232 /* Compute 'condT && notInITt' -- that is, the instruction is 15233 going to execute, and we're not in an IT block. This is the 15234 gating condition for updating condition codes in 16-bit Thumb 15235 instructions, except for CMP, CMN and TST. */ 15236 cond_AND_notInIT_T = newTemp(Ity_I32); 15237 assign(cond_AND_notInIT_T, 15238 binop(Iop_And32, mkexpr(notInITt), mkexpr(condT))); 15239 /* END { STANDARD PREAMBLE; } */ 15240 } 15241 15242 15243 /* At this point: 15244 * ITSTATE has been updated 15245 * condT holds the guarding condition for this instruction (0 or 1), 15246 * notInITt is 1 if we're in "normal" code, 0 if in an IT block 15247 * cond_AND_notInIT_T is the AND of the above two. 15248 15249 If the instruction proper can't trap, then there's nothing else 15250 to do w.r.t. ITSTATE -- just go and and generate IR for the 15251 insn, taking into account the guarding condition. 15252 15253 If, however, the instruction might trap, then we must back up 15254 ITSTATE to the old value, and re-update it after the potentially 15255 trapping IR section. A trap can happen either via a memory 15256 reference or because we need to throw SIGILL. 15257 15258 If an instruction has a side exit, we need to be sure that any 15259 ITSTATE backup is re-updated before the side exit. 15260 */ 15261 15262 /* ----------------------------------------------------------- */ 15263 /* -- -- */ 15264 /* -- Thumb 16-bit integer instructions -- */ 15265 /* -- -- */ 15266 /* -- IMPORTANT: references to insn1 or INSN1 are -- */ 15267 /* -- not allowed in this section -- */ 15268 /* -- -- */ 15269 /* ----------------------------------------------------------- */ 15270 15271 /* 16-bit instructions inside an IT block, apart from CMP, CMN and 15272 TST, do not set the condition codes. Hence we must dynamically 15273 test for this case for every condition code update. */ 15274 15275 IROp anOp = Iop_INVALID; 15276 HChar* anOpNm = NULL; 15277 15278 /* ================ 16-bit 15:6 cases ================ */ 15279 15280 switch (INSN0(15,6)) { 15281 15282 case 0x10a: // CMP 15283 case 0x10b: { // CMN 15284 /* ---------------- CMP Rn, Rm ---------------- */ 15285 Bool isCMN = INSN0(15,6) == 0x10b; 15286 UInt rN = INSN0(2,0); 15287 UInt rM = INSN0(5,3); 15288 IRTemp argL = newTemp(Ity_I32); 15289 IRTemp argR = newTemp(Ity_I32); 15290 assign( argL, getIRegT(rN) ); 15291 assign( argR, getIRegT(rM) ); 15292 /* Update flags regardless of whether in an IT block or not. */ 15293 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB, 15294 argL, argR, condT ); 15295 DIP("%s r%u, r%u\n", isCMN ? "cmn" : "cmp", rN, rM); 15296 goto decode_success; 15297 } 15298 15299 case 0x108: { 15300 /* ---------------- TST Rn, Rm ---------------- */ 15301 UInt rN = INSN0(2,0); 15302 UInt rM = INSN0(5,3); 15303 IRTemp oldC = newTemp(Ity_I32); 15304 IRTemp oldV = newTemp(Ity_I32); 15305 IRTemp res = newTemp(Ity_I32); 15306 assign( oldC, mk_armg_calculate_flag_c() ); 15307 assign( oldV, mk_armg_calculate_flag_v() ); 15308 assign( res, binop(Iop_And32, getIRegT(rN), getIRegT(rM)) ); 15309 /* Update flags regardless of whether in an IT block or not. */ 15310 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT ); 15311 DIP("tst r%u, r%u\n", rN, rM); 15312 goto decode_success; 15313 } 15314 15315 case 0x109: { 15316 /* ---------------- NEGS Rd, Rm ---------------- */ 15317 /* Rd = -Rm */ 15318 UInt rM = INSN0(5,3); 15319 UInt rD = INSN0(2,0); 15320 IRTemp arg = newTemp(Ity_I32); 15321 IRTemp zero = newTemp(Ity_I32); 15322 assign(arg, getIRegT(rM)); 15323 assign(zero, mkU32(0)); 15324 // rD can never be r15 15325 putIRegT(rD, binop(Iop_Sub32, mkexpr(zero), mkexpr(arg)), condT); 15326 setFlags_D1_D2( ARMG_CC_OP_SUB, zero, arg, cond_AND_notInIT_T); 15327 DIP("negs r%u, r%u\n", rD, rM); 15328 goto decode_success; 15329 } 15330 15331 case 0x10F: { 15332 /* ---------------- MVNS Rd, Rm ---------------- */ 15333 /* Rd = ~Rm */ 15334 UInt rM = INSN0(5,3); 15335 UInt rD = INSN0(2,0); 15336 IRTemp oldV = newTemp(Ity_I32); 15337 IRTemp oldC = newTemp(Ity_I32); 15338 IRTemp res = newTemp(Ity_I32); 15339 assign( oldV, mk_armg_calculate_flag_v() ); 15340 assign( oldC, mk_armg_calculate_flag_c() ); 15341 assign(res, unop(Iop_Not32, getIRegT(rM))); 15342 // rD can never be r15 15343 putIRegT(rD, mkexpr(res), condT); 15344 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 15345 cond_AND_notInIT_T ); 15346 DIP("mvns r%u, r%u\n", rD, rM); 15347 goto decode_success; 15348 } 15349 15350 case 0x10C: 15351 /* ---------------- ORRS Rd, Rm ---------------- */ 15352 anOp = Iop_Or32; anOpNm = "orr"; goto and_orr_eor_mul; 15353 case 0x100: 15354 /* ---------------- ANDS Rd, Rm ---------------- */ 15355 anOp = Iop_And32; anOpNm = "and"; goto and_orr_eor_mul; 15356 case 0x101: 15357 /* ---------------- EORS Rd, Rm ---------------- */ 15358 anOp = Iop_Xor32; anOpNm = "eor"; goto and_orr_eor_mul; 15359 case 0x10d: 15360 /* ---------------- MULS Rd, Rm ---------------- */ 15361 anOp = Iop_Mul32; anOpNm = "mul"; goto and_orr_eor_mul; 15362 and_orr_eor_mul: { 15363 /* Rd = Rd `op` Rm */ 15364 UInt rM = INSN0(5,3); 15365 UInt rD = INSN0(2,0); 15366 IRTemp res = newTemp(Ity_I32); 15367 IRTemp oldV = newTemp(Ity_I32); 15368 IRTemp oldC = newTemp(Ity_I32); 15369 assign( oldV, mk_armg_calculate_flag_v() ); 15370 assign( oldC, mk_armg_calculate_flag_c() ); 15371 assign( res, binop(anOp, getIRegT(rD), getIRegT(rM) )); 15372 // not safe to read guest state after here 15373 // rD can never be r15 15374 putIRegT(rD, mkexpr(res), condT); 15375 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 15376 cond_AND_notInIT_T ); 15377 DIP("%s r%u, r%u\n", anOpNm, rD, rM); 15378 goto decode_success; 15379 } 15380 15381 case 0x10E: { 15382 /* ---------------- BICS Rd, Rm ---------------- */ 15383 /* Rd = Rd & ~Rm */ 15384 UInt rM = INSN0(5,3); 15385 UInt rD = INSN0(2,0); 15386 IRTemp res = newTemp(Ity_I32); 15387 IRTemp oldV = newTemp(Ity_I32); 15388 IRTemp oldC = newTemp(Ity_I32); 15389 assign( oldV, mk_armg_calculate_flag_v() ); 15390 assign( oldC, mk_armg_calculate_flag_c() ); 15391 assign( res, binop(Iop_And32, getIRegT(rD), 15392 unop(Iop_Not32, getIRegT(rM) ))); 15393 // not safe to read guest state after here 15394 // rD can never be r15 15395 putIRegT(rD, mkexpr(res), condT); 15396 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 15397 cond_AND_notInIT_T ); 15398 DIP("bics r%u, r%u\n", rD, rM); 15399 goto decode_success; 15400 } 15401 15402 case 0x105: { 15403 /* ---------------- ADCS Rd, Rm ---------------- */ 15404 /* Rd = Rd + Rm + oldC */ 15405 UInt rM = INSN0(5,3); 15406 UInt rD = INSN0(2,0); 15407 IRTemp argL = newTemp(Ity_I32); 15408 IRTemp argR = newTemp(Ity_I32); 15409 IRTemp oldC = newTemp(Ity_I32); 15410 IRTemp res = newTemp(Ity_I32); 15411 assign(argL, getIRegT(rD)); 15412 assign(argR, getIRegT(rM)); 15413 assign(oldC, mk_armg_calculate_flag_c()); 15414 assign(res, binop(Iop_Add32, 15415 binop(Iop_Add32, mkexpr(argL), mkexpr(argR)), 15416 mkexpr(oldC))); 15417 // rD can never be r15 15418 putIRegT(rD, mkexpr(res), condT); 15419 setFlags_D1_D2_ND( ARMG_CC_OP_ADC, argL, argR, oldC, 15420 cond_AND_notInIT_T ); 15421 DIP("adcs r%u, r%u\n", rD, rM); 15422 goto decode_success; 15423 } 15424 15425 case 0x106: { 15426 /* ---------------- SBCS Rd, Rm ---------------- */ 15427 /* Rd = Rd - Rm - (oldC ^ 1) */ 15428 UInt rM = INSN0(5,3); 15429 UInt rD = INSN0(2,0); 15430 IRTemp argL = newTemp(Ity_I32); 15431 IRTemp argR = newTemp(Ity_I32); 15432 IRTemp oldC = newTemp(Ity_I32); 15433 IRTemp res = newTemp(Ity_I32); 15434 assign(argL, getIRegT(rD)); 15435 assign(argR, getIRegT(rM)); 15436 assign(oldC, mk_armg_calculate_flag_c()); 15437 assign(res, binop(Iop_Sub32, 15438 binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)), 15439 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)))); 15440 // rD can never be r15 15441 putIRegT(rD, mkexpr(res), condT); 15442 setFlags_D1_D2_ND( ARMG_CC_OP_SBB, argL, argR, oldC, 15443 cond_AND_notInIT_T ); 15444 DIP("sbcs r%u, r%u\n", rD, rM); 15445 goto decode_success; 15446 } 15447 15448 case 0x2CB: { 15449 /* ---------------- UXTB Rd, Rm ---------------- */ 15450 /* Rd = 8Uto32(Rm) */ 15451 UInt rM = INSN0(5,3); 15452 UInt rD = INSN0(2,0); 15453 putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFF)), 15454 condT); 15455 DIP("uxtb r%u, r%u\n", rD, rM); 15456 goto decode_success; 15457 } 15458 15459 case 0x2C9: { 15460 /* ---------------- SXTB Rd, Rm ---------------- */ 15461 /* Rd = 8Sto32(Rm) */ 15462 UInt rM = INSN0(5,3); 15463 UInt rD = INSN0(2,0); 15464 putIRegT(rD, binop(Iop_Sar32, 15465 binop(Iop_Shl32, getIRegT(rM), mkU8(24)), 15466 mkU8(24)), 15467 condT); 15468 DIP("sxtb r%u, r%u\n", rD, rM); 15469 goto decode_success; 15470 } 15471 15472 case 0x2CA: { 15473 /* ---------------- UXTH Rd, Rm ---------------- */ 15474 /* Rd = 16Uto32(Rm) */ 15475 UInt rM = INSN0(5,3); 15476 UInt rD = INSN0(2,0); 15477 putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFFFF)), 15478 condT); 15479 DIP("uxth r%u, r%u\n", rD, rM); 15480 goto decode_success; 15481 } 15482 15483 case 0x2C8: { 15484 /* ---------------- SXTH Rd, Rm ---------------- */ 15485 /* Rd = 16Sto32(Rm) */ 15486 UInt rM = INSN0(5,3); 15487 UInt rD = INSN0(2,0); 15488 putIRegT(rD, binop(Iop_Sar32, 15489 binop(Iop_Shl32, getIRegT(rM), mkU8(16)), 15490 mkU8(16)), 15491 condT); 15492 DIP("sxth r%u, r%u\n", rD, rM); 15493 goto decode_success; 15494 } 15495 15496 case 0x102: // LSLS 15497 case 0x103: // LSRS 15498 case 0x104: // ASRS 15499 case 0x107: { // RORS 15500 /* ---------------- LSLS Rs, Rd ---------------- */ 15501 /* ---------------- LSRS Rs, Rd ---------------- */ 15502 /* ---------------- ASRS Rs, Rd ---------------- */ 15503 /* ---------------- RORS Rs, Rd ---------------- */ 15504 /* Rd = Rd `op` Rs, and set flags */ 15505 UInt rS = INSN0(5,3); 15506 UInt rD = INSN0(2,0); 15507 IRTemp oldV = newTemp(Ity_I32); 15508 IRTemp rDt = newTemp(Ity_I32); 15509 IRTemp rSt = newTemp(Ity_I32); 15510 IRTemp res = newTemp(Ity_I32); 15511 IRTemp resC = newTemp(Ity_I32); 15512 HChar* wot = "???"; 15513 assign(rSt, getIRegT(rS)); 15514 assign(rDt, getIRegT(rD)); 15515 assign(oldV, mk_armg_calculate_flag_v()); 15516 /* Does not appear to be the standard 'how' encoding. */ 15517 switch (INSN0(15,6)) { 15518 case 0x102: 15519 compute_result_and_C_after_LSL_by_reg( 15520 dis_buf, &res, &resC, rDt, rSt, rD, rS 15521 ); 15522 wot = "lsl"; 15523 break; 15524 case 0x103: 15525 compute_result_and_C_after_LSR_by_reg( 15526 dis_buf, &res, &resC, rDt, rSt, rD, rS 15527 ); 15528 wot = "lsr"; 15529 break; 15530 case 0x104: 15531 compute_result_and_C_after_ASR_by_reg( 15532 dis_buf, &res, &resC, rDt, rSt, rD, rS 15533 ); 15534 wot = "asr"; 15535 break; 15536 case 0x107: 15537 compute_result_and_C_after_ROR_by_reg( 15538 dis_buf, &res, &resC, rDt, rSt, rD, rS 15539 ); 15540 wot = "ror"; 15541 break; 15542 default: 15543 /*NOTREACHED*/vassert(0); 15544 } 15545 // not safe to read guest state after this point 15546 putIRegT(rD, mkexpr(res), condT); 15547 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV, 15548 cond_AND_notInIT_T ); 15549 DIP("%ss r%u, r%u\n", wot, rS, rD); 15550 goto decode_success; 15551 } 15552 15553 case 0x2E8: // REV 15554 case 0x2E9: { // REV16 15555 /* ---------------- REV Rd, Rm ---------------- */ 15556 /* ---------------- REV16 Rd, Rm ---------------- */ 15557 UInt rM = INSN0(5,3); 15558 UInt rD = INSN0(2,0); 15559 Bool isREV = INSN0(15,6) == 0x2E8; 15560 IRTemp arg = newTemp(Ity_I32); 15561 assign(arg, getIRegT(rM)); 15562 IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg); 15563 putIRegT(rD, mkexpr(res), condT); 15564 DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM); 15565 goto decode_success; 15566 } 15567 15568 default: 15569 break; /* examine the next shortest prefix */ 15570 15571 } 15572 15573 15574 /* ================ 16-bit 15:7 cases ================ */ 15575 15576 switch (INSN0(15,7)) { 15577 15578 case BITS9(1,0,1,1,0,0,0,0,0): { 15579 /* ------------ ADD SP, #imm7 * 4 ------------ */ 15580 UInt uimm7 = INSN0(6,0); 15581 putIRegT(13, binop(Iop_Add32, getIRegT(13), mkU32(uimm7 * 4)), 15582 condT); 15583 DIP("add sp, #%u\n", uimm7 * 4); 15584 goto decode_success; 15585 } 15586 15587 case BITS9(1,0,1,1,0,0,0,0,1): { 15588 /* ------------ SUB SP, #imm7 * 4 ------------ */ 15589 UInt uimm7 = INSN0(6,0); 15590 putIRegT(13, binop(Iop_Sub32, getIRegT(13), mkU32(uimm7 * 4)), 15591 condT); 15592 DIP("sub sp, #%u\n", uimm7 * 4); 15593 goto decode_success; 15594 } 15595 15596 case BITS9(0,1,0,0,0,1,1,1,0): { 15597 /* ---------------- BX rM ---------------- */ 15598 /* Branch to reg, and optionally switch modes. Reg contains a 15599 suitably encoded address therefore (w CPSR.T at the bottom). 15600 Have to special-case r15, as usual. */ 15601 UInt rM = (INSN0(6,6) << 3) | INSN0(5,3); 15602 if (BITS3(0,0,0) == INSN0(2,0)) { 15603 IRTemp dst = newTemp(Ity_I32); 15604 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 15605 mk_skip_over_T16_if_cond_is_false(condT); 15606 condT = IRTemp_INVALID; 15607 // now uncond 15608 if (rM <= 14) { 15609 assign( dst, getIRegT(rM) ); 15610 } else { 15611 vassert(rM == 15); 15612 assign( dst, mkU32(guest_R15_curr_instr_notENC + 4) ); 15613 } 15614 llPutIReg(15, mkexpr(dst)); 15615 dres.jk_StopHere = rM == 14 ? Ijk_Ret : Ijk_Boring; 15616 dres.whatNext = Dis_StopHere; 15617 DIP("bx r%u (possibly switch to ARM mode)\n", rM); 15618 goto decode_success; 15619 } 15620 break; 15621 } 15622 15623 /* ---------------- BLX rM ---------------- */ 15624 /* Branch and link to interworking address in rM. */ 15625 case BITS9(0,1,0,0,0,1,1,1,1): { 15626 if (BITS3(0,0,0) == INSN0(2,0)) { 15627 UInt rM = (INSN0(6,6) << 3) | INSN0(5,3); 15628 IRTemp dst = newTemp(Ity_I32); 15629 if (rM <= 14) { 15630 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 15631 mk_skip_over_T16_if_cond_is_false(condT); 15632 condT = IRTemp_INVALID; 15633 // now uncond 15634 /* We're returning to Thumb code, hence "| 1" */ 15635 assign( dst, getIRegT(rM) ); 15636 putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ), 15637 IRTemp_INVALID ); 15638 llPutIReg(15, mkexpr(dst)); 15639 dres.jk_StopHere = Ijk_Call; 15640 dres.whatNext = Dis_StopHere; 15641 DIP("blx r%u (possibly switch to ARM mode)\n", rM); 15642 goto decode_success; 15643 } 15644 /* else unpredictable, fall through */ 15645 } 15646 break; 15647 } 15648 15649 default: 15650 break; /* examine the next shortest prefix */ 15651 15652 } 15653 15654 15655 /* ================ 16-bit 15:8 cases ================ */ 15656 15657 switch (INSN0(15,8)) { 15658 15659 case BITS8(1,1,0,1,1,1,1,1): { 15660 /* ---------------- SVC ---------------- */ 15661 UInt imm8 = INSN0(7,0); 15662 if (imm8 == 0) { 15663 /* A syscall. We can't do this conditionally, hence: */ 15664 mk_skip_over_T16_if_cond_is_false( condT ); 15665 // FIXME: what if we have to back up and restart this insn? 15666 // then ITSTATE will be wrong (we'll have it as "used") 15667 // when it isn't. Correct is to save ITSTATE in a 15668 // stash pseudo-reg, and back up from that if we have to 15669 // restart. 15670 // uncond after here 15671 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 )); 15672 dres.jk_StopHere = Ijk_Sys_syscall; 15673 dres.whatNext = Dis_StopHere; 15674 DIP("svc #0x%08x\n", imm8); 15675 goto decode_success; 15676 } 15677 /* else fall through */ 15678 break; 15679 } 15680 15681 case BITS8(0,1,0,0,0,1,0,0): { 15682 /* ---------------- ADD(HI) Rd, Rm ---------------- */ 15683 UInt h1 = INSN0(7,7); 15684 UInt h2 = INSN0(6,6); 15685 UInt rM = (h2 << 3) | INSN0(5,3); 15686 UInt rD = (h1 << 3) | INSN0(2,0); 15687 //if (h1 == 0 && h2 == 0) { // Original T1 was more restrictive 15688 if (rD == 15 && rM == 15) { 15689 // then it's invalid 15690 } else { 15691 IRTemp res = newTemp(Ity_I32); 15692 assign( res, binop(Iop_Add32, getIRegT(rD), getIRegT(rM) )); 15693 if (rD != 15) { 15694 putIRegT( rD, mkexpr(res), condT ); 15695 } else { 15696 /* Only allowed outside or last-in IT block; SIGILL if not so. */ 15697 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 15698 /* jump over insn if not selected */ 15699 mk_skip_over_T16_if_cond_is_false(condT); 15700 condT = IRTemp_INVALID; 15701 // now uncond 15702 /* non-interworking branch */ 15703 irsb->next = binop(Iop_Or32, mkexpr(res), mkU32(1)); 15704 irsb->jumpkind = Ijk_Boring; 15705 dres.whatNext = Dis_StopHere; 15706 } 15707 DIP("add(hi) r%u, r%u\n", rD, rM); 15708 goto decode_success; 15709 } 15710 break; 15711 } 15712 15713 case BITS8(0,1,0,0,0,1,0,1): { 15714 /* ---------------- CMP(HI) Rd, Rm ---------------- */ 15715 UInt h1 = INSN0(7,7); 15716 UInt h2 = INSN0(6,6); 15717 UInt rM = (h2 << 3) | INSN0(5,3); 15718 UInt rN = (h1 << 3) | INSN0(2,0); 15719 if (h1 != 0 || h2 != 0) { 15720 IRTemp argL = newTemp(Ity_I32); 15721 IRTemp argR = newTemp(Ity_I32); 15722 assign( argL, getIRegT(rN) ); 15723 assign( argR, getIRegT(rM) ); 15724 /* Update flags regardless of whether in an IT block or not. */ 15725 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT ); 15726 DIP("cmphi r%u, r%u\n", rN, rM); 15727 goto decode_success; 15728 } 15729 break; 15730 } 15731 15732 case BITS8(0,1,0,0,0,1,1,0): { 15733 /* ---------------- MOV(HI) Rd, Rm ---------------- */ 15734 UInt h1 = INSN0(7,7); 15735 UInt h2 = INSN0(6,6); 15736 UInt rM = (h2 << 3) | INSN0(5,3); 15737 UInt rD = (h1 << 3) | INSN0(2,0); 15738 /* The old ARM ARM seems to disallow the case where both Rd and 15739 Rm are "low" registers, but newer versions allow it. */ 15740 if (1 /*h1 != 0 || h2 != 0*/) { 15741 IRTemp val = newTemp(Ity_I32); 15742 assign( val, getIRegT(rM) ); 15743 if (rD != 15) { 15744 putIRegT( rD, mkexpr(val), condT ); 15745 } else { 15746 /* Only allowed outside or last-in IT block; SIGILL if not so. */ 15747 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 15748 /* jump over insn if not selected */ 15749 mk_skip_over_T16_if_cond_is_false(condT); 15750 condT = IRTemp_INVALID; 15751 // now uncond 15752 /* non-interworking branch */ 15753 llPutIReg(15, binop(Iop_Or32, mkexpr(val), mkU32(1))); 15754 dres.jk_StopHere = rM == 14 ? Ijk_Ret : Ijk_Boring; 15755 dres.whatNext = Dis_StopHere; 15756 } 15757 DIP("mov r%u, r%u\n", rD, rM); 15758 goto decode_success; 15759 } 15760 break; 15761 } 15762 15763 case BITS8(1,0,1,1,1,1,1,1): { 15764 /* ---------------- IT (if-then) ---------------- */ 15765 UInt firstcond = INSN0(7,4); 15766 UInt mask = INSN0(3,0); 15767 UInt newITSTATE = 0; 15768 /* This is the ITSTATE represented as described in 15769 libvex_guest_arm.h. It is not the ARM ARM representation. */ 15770 UChar c1 = '.'; 15771 UChar c2 = '.'; 15772 UChar c3 = '.'; 15773 Bool valid = compute_ITSTATE( &newITSTATE, &c1, &c2, &c3, 15774 firstcond, mask ); 15775 if (valid && firstcond != 0xF/*NV*/) { 15776 /* Not allowed in an IT block; SIGILL if so. */ 15777 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate); 15778 15779 IRTemp t = newTemp(Ity_I32); 15780 assign(t, mkU32(newITSTATE)); 15781 put_ITSTATE(t); 15782 15783 DIP("it%c%c%c %s\n", c1, c2, c3, nCC(firstcond)); 15784 goto decode_success; 15785 } 15786 break; 15787 } 15788 15789 case BITS8(1,0,1,1,0,0,0,1): 15790 case BITS8(1,0,1,1,0,0,1,1): 15791 case BITS8(1,0,1,1,1,0,0,1): 15792 case BITS8(1,0,1,1,1,0,1,1): { 15793 /* ---------------- CB{N}Z ---------------- */ 15794 UInt rN = INSN0(2,0); 15795 UInt bOP = INSN0(11,11); 15796 UInt imm32 = (INSN0(9,9) << 6) | (INSN0(7,3) << 1); 15797 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate); 15798 /* It's a conditional branch forward. */ 15799 IRTemp kond = newTemp(Ity_I1); 15800 assign( kond, binop(bOP ? Iop_CmpNE32 : Iop_CmpEQ32, 15801 getIRegT(rN), mkU32(0)) ); 15802 15803 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 15804 /* Looks like the nearest insn we can branch to is the one after 15805 next. That makes sense, as there's no point in being able to 15806 encode a conditional branch to the next instruction. */ 15807 UInt dst = (guest_R15_curr_instr_notENC + 4 + imm32) | 1; 15808 stmt(IRStmt_Exit( mkexpr(kond), 15809 Ijk_Boring, 15810 IRConst_U32(toUInt(dst)), 15811 OFFB_R15T )); 15812 DIP("cb%s r%u, 0x%x\n", bOP ? "nz" : "z", rN, dst - 1); 15813 goto decode_success; 15814 } 15815 15816 default: 15817 break; /* examine the next shortest prefix */ 15818 15819 } 15820 15821 15822 /* ================ 16-bit 15:9 cases ================ */ 15823 15824 switch (INSN0(15,9)) { 15825 15826 case BITS7(1,0,1,1,0,1,0): { 15827 /* ---------------- PUSH ---------------- */ 15828 /* This is a bit like STMxx, but way simpler. Complications we 15829 don't have to deal with: 15830 * SP being one of the transferred registers 15831 * direction (increment vs decrement) 15832 * before-vs-after-ness 15833 */ 15834 Int i, nRegs; 15835 UInt bitR = INSN0(8,8); 15836 UInt regList = INSN0(7,0); 15837 if (bitR) regList |= (1 << 14); 15838 15839 /* At least one register must be transferred, else result is 15840 UNPREDICTABLE. */ 15841 if (regList != 0) { 15842 /* Since we can't generate a guaranteed non-trapping IR 15843 sequence, (1) jump over the insn if it is gated false, and 15844 (2) back out the ITSTATE update. */ 15845 mk_skip_over_T16_if_cond_is_false(condT); 15846 condT = IRTemp_INVALID; 15847 put_ITSTATE(old_itstate); 15848 // now uncond 15849 15850 nRegs = 0; 15851 for (i = 0; i < 16; i++) { 15852 if ((regList & (1 << i)) != 0) 15853 nRegs++; 15854 } 15855 vassert(nRegs >= 1 && nRegs <= 9); 15856 15857 /* Move SP down first of all, so we're "covered". And don't 15858 mess with its alignment. */ 15859 IRTemp newSP = newTemp(Ity_I32); 15860 assign(newSP, binop(Iop_Sub32, getIRegT(13), mkU32(4 * nRegs))); 15861 putIRegT(13, mkexpr(newSP), IRTemp_INVALID); 15862 15863 /* Generate a transfer base address as a forced-aligned 15864 version of the final SP value. */ 15865 IRTemp base = newTemp(Ity_I32); 15866 assign(base, binop(Iop_And32, mkexpr(newSP), mkU32(~3))); 15867 15868 /* Now the transfers */ 15869 nRegs = 0; 15870 for (i = 0; i < 16; i++) { 15871 if ((regList & (1 << i)) != 0) { 15872 storeLE( binop(Iop_Add32, mkexpr(base), mkU32(4 * nRegs)), 15873 getIRegT(i) ); 15874 nRegs++; 15875 } 15876 } 15877 15878 /* Reinstate the ITSTATE update. */ 15879 put_ITSTATE(new_itstate); 15880 15881 DIP("push {%s0x%04x}\n", bitR ? "lr," : "", regList & 0xFF); 15882 goto decode_success; 15883 } 15884 break; 15885 } 15886 15887 case BITS7(1,0,1,1,1,1,0): { 15888 /* ---------------- POP ---------------- */ 15889 Int i, nRegs; 15890 UInt bitR = INSN0(8,8); 15891 UInt regList = INSN0(7,0); 15892 15893 /* At least one register must be transferred, else result is 15894 UNPREDICTABLE. */ 15895 if (regList != 0 || bitR) { 15896 /* Since we can't generate a guaranteed non-trapping IR 15897 sequence, (1) jump over the insn if it is gated false, and 15898 (2) back out the ITSTATE update. */ 15899 mk_skip_over_T16_if_cond_is_false(condT); 15900 condT = IRTemp_INVALID; 15901 put_ITSTATE(old_itstate); 15902 // now uncond 15903 15904 nRegs = 0; 15905 for (i = 0; i < 8; i++) { 15906 if ((regList & (1 << i)) != 0) 15907 nRegs++; 15908 } 15909 vassert(nRegs >= 0 && nRegs <= 8); 15910 vassert(bitR == 0 || bitR == 1); 15911 15912 IRTemp oldSP = newTemp(Ity_I32); 15913 assign(oldSP, getIRegT(13)); 15914 15915 /* Generate a transfer base address as a forced-aligned 15916 version of the original SP value. */ 15917 IRTemp base = newTemp(Ity_I32); 15918 assign(base, binop(Iop_And32, mkexpr(oldSP), mkU32(~3))); 15919 15920 /* Compute a new value for SP, but don't install it yet, so 15921 that we're "covered" until all the transfers are done. 15922 And don't mess with its alignment. */ 15923 IRTemp newSP = newTemp(Ity_I32); 15924 assign(newSP, binop(Iop_Add32, mkexpr(oldSP), 15925 mkU32(4 * (nRegs + bitR)))); 15926 15927 /* Now the transfers, not including PC */ 15928 nRegs = 0; 15929 for (i = 0; i < 8; i++) { 15930 if ((regList & (1 << i)) != 0) { 15931 putIRegT(i, loadLE( Ity_I32, 15932 binop(Iop_Add32, mkexpr(base), 15933 mkU32(4 * nRegs))), 15934 IRTemp_INVALID ); 15935 nRegs++; 15936 } 15937 } 15938 15939 IRTemp newPC = IRTemp_INVALID; 15940 if (bitR) { 15941 newPC = newTemp(Ity_I32); 15942 assign( newPC, loadLE( Ity_I32, 15943 binop(Iop_Add32, mkexpr(base), 15944 mkU32(4 * nRegs)))); 15945 } 15946 15947 /* Now we can safely install the new SP value */ 15948 putIRegT(13, mkexpr(newSP), IRTemp_INVALID); 15949 15950 /* Reinstate the ITSTATE update. */ 15951 put_ITSTATE(new_itstate); 15952 15953 /* now, do we also have to do a branch? If so, it turns out 15954 that the new PC value is encoded exactly as we need it to 15955 be -- with CPSR.T in the bottom bit. So we can simply use 15956 it as is, no need to mess with it. Note, therefore, this 15957 is an interworking return. */ 15958 if (bitR) { 15959 llPutIReg(15, mkexpr(newPC)); 15960 dres.jk_StopHere = Ijk_Ret; 15961 dres.whatNext = Dis_StopHere; 15962 } 15963 15964 DIP("pop {%s0x%04x}\n", bitR ? "pc," : "", regList & 0xFF); 15965 goto decode_success; 15966 } 15967 break; 15968 } 15969 15970 case BITS7(0,0,0,1,1,1,0): /* ADDS */ 15971 case BITS7(0,0,0,1,1,1,1): { /* SUBS */ 15972 /* ---------------- ADDS Rd, Rn, #uimm3 ---------------- */ 15973 /* ---------------- SUBS Rd, Rn, #uimm3 ---------------- */ 15974 UInt uimm3 = INSN0(8,6); 15975 UInt rN = INSN0(5,3); 15976 UInt rD = INSN0(2,0); 15977 UInt isSub = INSN0(9,9); 15978 IRTemp argL = newTemp(Ity_I32); 15979 IRTemp argR = newTemp(Ity_I32); 15980 assign( argL, getIRegT(rN) ); 15981 assign( argR, mkU32(uimm3) ); 15982 putIRegT(rD, binop(isSub ? Iop_Sub32 : Iop_Add32, 15983 mkexpr(argL), mkexpr(argR)), 15984 condT); 15985 setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD, 15986 argL, argR, cond_AND_notInIT_T ); 15987 DIP("%s r%u, r%u, #%u\n", isSub ? "subs" : "adds", rD, rN, uimm3); 15988 goto decode_success; 15989 } 15990 15991 case BITS7(0,0,0,1,1,0,0): /* ADDS */ 15992 case BITS7(0,0,0,1,1,0,1): { /* SUBS */ 15993 /* ---------------- ADDS Rd, Rn, Rm ---------------- */ 15994 /* ---------------- SUBS Rd, Rn, Rm ---------------- */ 15995 UInt rM = INSN0(8,6); 15996 UInt rN = INSN0(5,3); 15997 UInt rD = INSN0(2,0); 15998 UInt isSub = INSN0(9,9); 15999 IRTemp argL = newTemp(Ity_I32); 16000 IRTemp argR = newTemp(Ity_I32); 16001 assign( argL, getIRegT(rN) ); 16002 assign( argR, getIRegT(rM) ); 16003 putIRegT( rD, binop(isSub ? Iop_Sub32 : Iop_Add32, 16004 mkexpr(argL), mkexpr(argR)), 16005 condT ); 16006 setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD, 16007 argL, argR, cond_AND_notInIT_T ); 16008 DIP("%s r%u, r%u, r%u\n", isSub ? "subs" : "adds", rD, rN, rM); 16009 goto decode_success; 16010 } 16011 16012 case BITS7(0,1,0,1,0,0,0): /* STR */ 16013 case BITS7(0,1,0,1,1,0,0): { /* LDR */ 16014 /* ------------- LDR Rd, [Rn, Rm] ------------- */ 16015 /* ------------- STR Rd, [Rn, Rm] ------------- */ 16016 /* LDR/STR Rd, [Rn + Rm] */ 16017 UInt rD = INSN0(2,0); 16018 UInt rN = INSN0(5,3); 16019 UInt rM = INSN0(8,6); 16020 UInt isLD = INSN0(11,11); 16021 16022 mk_skip_over_T16_if_cond_is_false(condT); 16023 condT = IRTemp_INVALID; 16024 // now uncond 16025 16026 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM)); 16027 put_ITSTATE(old_itstate); // backout 16028 if (isLD) { 16029 putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID); 16030 } else { 16031 storeLE(ea, getIRegT(rD)); 16032 } 16033 put_ITSTATE(new_itstate); // restore 16034 16035 DIP("%s r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM); 16036 goto decode_success; 16037 } 16038 16039 case BITS7(0,1,0,1,0,0,1): 16040 case BITS7(0,1,0,1,1,0,1): { 16041 /* ------------- LDRH Rd, [Rn, Rm] ------------- */ 16042 /* ------------- STRH Rd, [Rn, Rm] ------------- */ 16043 /* LDRH/STRH Rd, [Rn + Rm] */ 16044 UInt rD = INSN0(2,0); 16045 UInt rN = INSN0(5,3); 16046 UInt rM = INSN0(8,6); 16047 UInt isLD = INSN0(11,11); 16048 16049 mk_skip_over_T16_if_cond_is_false(condT); 16050 condT = IRTemp_INVALID; 16051 // now uncond 16052 16053 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM)); 16054 put_ITSTATE(old_itstate); // backout 16055 if (isLD) { 16056 putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)), 16057 IRTemp_INVALID); 16058 } else { 16059 storeLE( ea, unop(Iop_32to16, getIRegT(rD)) ); 16060 } 16061 put_ITSTATE(new_itstate); // restore 16062 16063 DIP("%sh r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM); 16064 goto decode_success; 16065 } 16066 16067 case BITS7(0,1,0,1,1,1,1): { 16068 /* ------------- LDRSH Rd, [Rn, Rm] ------------- */ 16069 /* LDRSH Rd, [Rn + Rm] */ 16070 UInt rD = INSN0(2,0); 16071 UInt rN = INSN0(5,3); 16072 UInt rM = INSN0(8,6); 16073 16074 mk_skip_over_T16_if_cond_is_false(condT); 16075 condT = IRTemp_INVALID; 16076 // now uncond 16077 16078 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM)); 16079 put_ITSTATE(old_itstate); // backout 16080 putIRegT(rD, unop(Iop_16Sto32, loadLE(Ity_I16, ea)), 16081 IRTemp_INVALID); 16082 put_ITSTATE(new_itstate); // restore 16083 16084 DIP("ldrsh r%u, [r%u, r%u]\n", rD, rN, rM); 16085 goto decode_success; 16086 } 16087 16088 case BITS7(0,1,0,1,0,1,1): { 16089 /* ------------- LDRSB Rd, [Rn, Rm] ------------- */ 16090 /* LDRSB Rd, [Rn + Rm] */ 16091 UInt rD = INSN0(2,0); 16092 UInt rN = INSN0(5,3); 16093 UInt rM = INSN0(8,6); 16094 16095 mk_skip_over_T16_if_cond_is_false(condT); 16096 condT = IRTemp_INVALID; 16097 // now uncond 16098 16099 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM)); 16100 put_ITSTATE(old_itstate); // backout 16101 putIRegT(rD, unop(Iop_8Sto32, loadLE(Ity_I8, ea)), 16102 IRTemp_INVALID); 16103 put_ITSTATE(new_itstate); // restore 16104 16105 DIP("ldrsb r%u, [r%u, r%u]\n", rD, rN, rM); 16106 goto decode_success; 16107 } 16108 16109 case BITS7(0,1,0,1,0,1,0): 16110 case BITS7(0,1,0,1,1,1,0): { 16111 /* ------------- LDRB Rd, [Rn, Rm] ------------- */ 16112 /* ------------- STRB Rd, [Rn, Rm] ------------- */ 16113 /* LDRB/STRB Rd, [Rn + Rm] */ 16114 UInt rD = INSN0(2,0); 16115 UInt rN = INSN0(5,3); 16116 UInt rM = INSN0(8,6); 16117 UInt isLD = INSN0(11,11); 16118 16119 mk_skip_over_T16_if_cond_is_false(condT); 16120 condT = IRTemp_INVALID; 16121 // now uncond 16122 16123 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM)); 16124 put_ITSTATE(old_itstate); // backout 16125 if (isLD) { 16126 putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)), 16127 IRTemp_INVALID); 16128 } else { 16129 storeLE( ea, unop(Iop_32to8, getIRegT(rD)) ); 16130 } 16131 put_ITSTATE(new_itstate); // restore 16132 16133 DIP("%sb r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM); 16134 goto decode_success; 16135 } 16136 16137 default: 16138 break; /* examine the next shortest prefix */ 16139 16140 } 16141 16142 16143 /* ================ 16-bit 15:11 cases ================ */ 16144 16145 switch (INSN0(15,11)) { 16146 16147 case BITS5(0,0,1,1,0): 16148 case BITS5(0,0,1,1,1): { 16149 /* ---------------- ADDS Rn, #uimm8 ---------------- */ 16150 /* ---------------- SUBS Rn, #uimm8 ---------------- */ 16151 UInt isSub = INSN0(11,11); 16152 UInt rN = INSN0(10,8); 16153 UInt uimm8 = INSN0(7,0); 16154 IRTemp argL = newTemp(Ity_I32); 16155 IRTemp argR = newTemp(Ity_I32); 16156 assign( argL, getIRegT(rN) ); 16157 assign( argR, mkU32(uimm8) ); 16158 putIRegT( rN, binop(isSub ? Iop_Sub32 : Iop_Add32, 16159 mkexpr(argL), mkexpr(argR)), condT ); 16160 setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD, 16161 argL, argR, cond_AND_notInIT_T ); 16162 DIP("%s r%u, #%u\n", isSub ? "subs" : "adds", rN, uimm8); 16163 goto decode_success; 16164 } 16165 16166 case BITS5(1,0,1,0,0): { 16167 /* ---------------- ADD rD, PC, #imm8 * 4 ---------------- */ 16168 /* a.k.a. ADR */ 16169 /* rD = align4(PC) + imm8 * 4 */ 16170 UInt rD = INSN0(10,8); 16171 UInt imm8 = INSN0(7,0); 16172 putIRegT(rD, binop(Iop_Add32, 16173 binop(Iop_And32, getIRegT(15), mkU32(~3U)), 16174 mkU32(imm8 * 4)), 16175 condT); 16176 DIP("add r%u, pc, #%u\n", rD, imm8 * 4); 16177 goto decode_success; 16178 } 16179 16180 case BITS5(1,0,1,0,1): { 16181 /* ---------------- ADD rD, SP, #imm8 * 4 ---------------- */ 16182 UInt rD = INSN0(10,8); 16183 UInt imm8 = INSN0(7,0); 16184 putIRegT(rD, binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4)), 16185 condT); 16186 DIP("add r%u, r13, #%u\n", rD, imm8 * 4); 16187 goto decode_success; 16188 } 16189 16190 case BITS5(0,0,1,0,1): { 16191 /* ---------------- CMP Rn, #uimm8 ---------------- */ 16192 UInt rN = INSN0(10,8); 16193 UInt uimm8 = INSN0(7,0); 16194 IRTemp argL = newTemp(Ity_I32); 16195 IRTemp argR = newTemp(Ity_I32); 16196 assign( argL, getIRegT(rN) ); 16197 assign( argR, mkU32(uimm8) ); 16198 /* Update flags regardless of whether in an IT block or not. */ 16199 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT ); 16200 DIP("cmp r%u, #%u\n", rN, uimm8); 16201 goto decode_success; 16202 } 16203 16204 case BITS5(0,0,1,0,0): { 16205 /* -------------- (T1) MOVS Rn, #uimm8 -------------- */ 16206 UInt rD = INSN0(10,8); 16207 UInt uimm8 = INSN0(7,0); 16208 IRTemp oldV = newTemp(Ity_I32); 16209 IRTemp oldC = newTemp(Ity_I32); 16210 IRTemp res = newTemp(Ity_I32); 16211 assign( oldV, mk_armg_calculate_flag_v() ); 16212 assign( oldC, mk_armg_calculate_flag_c() ); 16213 assign( res, mkU32(uimm8) ); 16214 putIRegT(rD, mkexpr(res), condT); 16215 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 16216 cond_AND_notInIT_T ); 16217 DIP("movs r%u, #%u\n", rD, uimm8); 16218 goto decode_success; 16219 } 16220 16221 case BITS5(0,1,0,0,1): { 16222 /* ------------- LDR Rd, [PC, #imm8 * 4] ------------- */ 16223 /* LDR Rd, [align4(PC) + imm8 * 4] */ 16224 UInt rD = INSN0(10,8); 16225 UInt imm8 = INSN0(7,0); 16226 IRTemp ea = newTemp(Ity_I32); 16227 16228 mk_skip_over_T16_if_cond_is_false(condT); 16229 condT = IRTemp_INVALID; 16230 // now uncond 16231 16232 assign(ea, binop(Iop_Add32, 16233 binop(Iop_And32, getIRegT(15), mkU32(~3U)), 16234 mkU32(imm8 * 4))); 16235 put_ITSTATE(old_itstate); // backout 16236 putIRegT(rD, loadLE(Ity_I32, mkexpr(ea)), 16237 IRTemp_INVALID); 16238 put_ITSTATE(new_itstate); // restore 16239 16240 DIP("ldr r%u, [pc, #%u]\n", rD, imm8 * 4); 16241 goto decode_success; 16242 } 16243 16244 case BITS5(0,1,1,0,0): /* STR */ 16245 case BITS5(0,1,1,0,1): { /* LDR */ 16246 /* ------------- LDR Rd, [Rn, #imm5 * 4] ------------- */ 16247 /* ------------- STR Rd, [Rn, #imm5 * 4] ------------- */ 16248 /* LDR/STR Rd, [Rn + imm5 * 4] */ 16249 UInt rD = INSN0(2,0); 16250 UInt rN = INSN0(5,3); 16251 UInt imm5 = INSN0(10,6); 16252 UInt isLD = INSN0(11,11); 16253 16254 mk_skip_over_T16_if_cond_is_false(condT); 16255 condT = IRTemp_INVALID; 16256 // now uncond 16257 16258 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 4)); 16259 put_ITSTATE(old_itstate); // backout 16260 if (isLD) { 16261 putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID); 16262 } else { 16263 storeLE( ea, getIRegT(rD) ); 16264 } 16265 put_ITSTATE(new_itstate); // restore 16266 16267 DIP("%s r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 4); 16268 goto decode_success; 16269 } 16270 16271 case BITS5(1,0,0,0,0): /* STRH */ 16272 case BITS5(1,0,0,0,1): { /* LDRH */ 16273 /* ------------- LDRH Rd, [Rn, #imm5 * 2] ------------- */ 16274 /* ------------- STRH Rd, [Rn, #imm5 * 2] ------------- */ 16275 /* LDRH/STRH Rd, [Rn + imm5 * 2] */ 16276 UInt rD = INSN0(2,0); 16277 UInt rN = INSN0(5,3); 16278 UInt imm5 = INSN0(10,6); 16279 UInt isLD = INSN0(11,11); 16280 16281 mk_skip_over_T16_if_cond_is_false(condT); 16282 condT = IRTemp_INVALID; 16283 // now uncond 16284 16285 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 2)); 16286 put_ITSTATE(old_itstate); // backout 16287 if (isLD) { 16288 putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)), 16289 IRTemp_INVALID); 16290 } else { 16291 storeLE( ea, unop(Iop_32to16, getIRegT(rD)) ); 16292 } 16293 put_ITSTATE(new_itstate); // restore 16294 16295 DIP("%sh r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 2); 16296 goto decode_success; 16297 } 16298 16299 case BITS5(0,1,1,1,0): /* STRB */ 16300 case BITS5(0,1,1,1,1): { /* LDRB */ 16301 /* ------------- LDRB Rd, [Rn, #imm5] ------------- */ 16302 /* ------------- STRB Rd, [Rn, #imm5] ------------- */ 16303 /* LDRB/STRB Rd, [Rn + imm5] */ 16304 UInt rD = INSN0(2,0); 16305 UInt rN = INSN0(5,3); 16306 UInt imm5 = INSN0(10,6); 16307 UInt isLD = INSN0(11,11); 16308 16309 mk_skip_over_T16_if_cond_is_false(condT); 16310 condT = IRTemp_INVALID; 16311 // now uncond 16312 16313 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5)); 16314 put_ITSTATE(old_itstate); // backout 16315 if (isLD) { 16316 putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)), 16317 IRTemp_INVALID); 16318 } else { 16319 storeLE( ea, unop(Iop_32to8, getIRegT(rD)) ); 16320 } 16321 put_ITSTATE(new_itstate); // restore 16322 16323 DIP("%sb r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5); 16324 goto decode_success; 16325 } 16326 16327 case BITS5(1,0,0,1,0): /* STR */ 16328 case BITS5(1,0,0,1,1): { /* LDR */ 16329 /* ------------- LDR Rd, [SP, #imm8 * 4] ------------- */ 16330 /* ------------- STR Rd, [SP, #imm8 * 4] ------------- */ 16331 /* LDR/STR Rd, [SP + imm8 * 4] */ 16332 UInt rD = INSN0(10,8); 16333 UInt imm8 = INSN0(7,0); 16334 UInt isLD = INSN0(11,11); 16335 16336 mk_skip_over_T16_if_cond_is_false(condT); 16337 condT = IRTemp_INVALID; 16338 // now uncond 16339 16340 IRExpr* ea = binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4)); 16341 put_ITSTATE(old_itstate); // backout 16342 if (isLD) { 16343 putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID); 16344 } else { 16345 storeLE(ea, getIRegT(rD)); 16346 } 16347 put_ITSTATE(new_itstate); // restore 16348 16349 DIP("%s r%u, [sp, #%u]\n", isLD ? "ldr" : "str", rD, imm8 * 4); 16350 goto decode_success; 16351 } 16352 16353 case BITS5(1,1,0,0,1): { 16354 /* ------------- LDMIA Rn!, {reglist} ------------- */ 16355 Int i, nRegs = 0; 16356 UInt rN = INSN0(10,8); 16357 UInt list = INSN0(7,0); 16358 /* Empty lists aren't allowed. */ 16359 if (list != 0) { 16360 mk_skip_over_T16_if_cond_is_false(condT); 16361 condT = IRTemp_INVALID; 16362 put_ITSTATE(old_itstate); 16363 // now uncond 16364 16365 IRTemp oldRn = newTemp(Ity_I32); 16366 IRTemp base = newTemp(Ity_I32); 16367 assign(oldRn, getIRegT(rN)); 16368 assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U))); 16369 for (i = 0; i < 8; i++) { 16370 if (0 == (list & (1 << i))) 16371 continue; 16372 nRegs++; 16373 putIRegT( 16374 i, loadLE(Ity_I32, 16375 binop(Iop_Add32, mkexpr(base), 16376 mkU32(nRegs * 4 - 4))), 16377 IRTemp_INVALID 16378 ); 16379 } 16380 /* Only do the writeback for rN if it isn't in the list of 16381 registers to be transferred. */ 16382 if (0 == (list & (1 << rN))) { 16383 putIRegT(rN, 16384 binop(Iop_Add32, mkexpr(oldRn), 16385 mkU32(nRegs * 4)), 16386 IRTemp_INVALID 16387 ); 16388 } 16389 16390 /* Reinstate the ITSTATE update. */ 16391 put_ITSTATE(new_itstate); 16392 16393 DIP("ldmia r%u!, {0x%04x}\n", rN, list); 16394 goto decode_success; 16395 } 16396 break; 16397 } 16398 16399 case BITS5(1,1,0,0,0): { 16400 /* ------------- STMIA Rn!, {reglist} ------------- */ 16401 Int i, nRegs = 0; 16402 UInt rN = INSN0(10,8); 16403 UInt list = INSN0(7,0); 16404 /* Empty lists aren't allowed. Also, if rN is in the list then 16405 it must be the lowest numbered register in the list. */ 16406 Bool valid = list != 0; 16407 if (valid && 0 != (list & (1 << rN))) { 16408 for (i = 0; i < rN; i++) { 16409 if (0 != (list & (1 << i))) 16410 valid = False; 16411 } 16412 } 16413 if (valid) { 16414 mk_skip_over_T16_if_cond_is_false(condT); 16415 condT = IRTemp_INVALID; 16416 put_ITSTATE(old_itstate); 16417 // now uncond 16418 16419 IRTemp oldRn = newTemp(Ity_I32); 16420 IRTemp base = newTemp(Ity_I32); 16421 assign(oldRn, getIRegT(rN)); 16422 assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U))); 16423 for (i = 0; i < 8; i++) { 16424 if (0 == (list & (1 << i))) 16425 continue; 16426 nRegs++; 16427 storeLE( binop(Iop_Add32, mkexpr(base), mkU32(nRegs * 4 - 4)), 16428 getIRegT(i) ); 16429 } 16430 /* Always do the writeback. */ 16431 putIRegT(rN, 16432 binop(Iop_Add32, mkexpr(oldRn), 16433 mkU32(nRegs * 4)), 16434 IRTemp_INVALID); 16435 16436 /* Reinstate the ITSTATE update. */ 16437 put_ITSTATE(new_itstate); 16438 16439 DIP("stmia r%u!, {0x%04x}\n", rN, list); 16440 goto decode_success; 16441 } 16442 break; 16443 } 16444 16445 case BITS5(0,0,0,0,0): /* LSLS */ 16446 case BITS5(0,0,0,0,1): /* LSRS */ 16447 case BITS5(0,0,0,1,0): { /* ASRS */ 16448 /* ---------------- LSLS Rd, Rm, #imm5 ---------------- */ 16449 /* ---------------- LSRS Rd, Rm, #imm5 ---------------- */ 16450 /* ---------------- ASRS Rd, Rm, #imm5 ---------------- */ 16451 UInt rD = INSN0(2,0); 16452 UInt rM = INSN0(5,3); 16453 UInt imm5 = INSN0(10,6); 16454 IRTemp res = newTemp(Ity_I32); 16455 IRTemp resC = newTemp(Ity_I32); 16456 IRTemp rMt = newTemp(Ity_I32); 16457 IRTemp oldV = newTemp(Ity_I32); 16458 HChar* wot = "???"; 16459 assign(rMt, getIRegT(rM)); 16460 assign(oldV, mk_armg_calculate_flag_v()); 16461 /* Looks like INSN0(12,11) are the standard 'how' encoding. 16462 Could compactify if the ROR case later appears. */ 16463 switch (INSN0(15,11)) { 16464 case BITS5(0,0,0,0,0): 16465 compute_result_and_C_after_LSL_by_imm5( 16466 dis_buf, &res, &resC, rMt, imm5, rM 16467 ); 16468 wot = "lsl"; 16469 break; 16470 case BITS5(0,0,0,0,1): 16471 compute_result_and_C_after_LSR_by_imm5( 16472 dis_buf, &res, &resC, rMt, imm5, rM 16473 ); 16474 wot = "lsr"; 16475 break; 16476 case BITS5(0,0,0,1,0): 16477 compute_result_and_C_after_ASR_by_imm5( 16478 dis_buf, &res, &resC, rMt, imm5, rM 16479 ); 16480 wot = "asr"; 16481 break; 16482 default: 16483 /*NOTREACHED*/vassert(0); 16484 } 16485 // not safe to read guest state after this point 16486 putIRegT(rD, mkexpr(res), condT); 16487 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV, 16488 cond_AND_notInIT_T ); 16489 /* ignore buf and roll our own output */ 16490 DIP("%ss r%u, r%u, #%u\n", wot, rD, rM, imm5); 16491 goto decode_success; 16492 } 16493 16494 case BITS5(1,1,1,0,0): { 16495 /* ---------------- B #simm11 ---------------- */ 16496 Int simm11 = INSN0(10,0); 16497 simm11 = (simm11 << 21) >> 20; 16498 UInt dst = simm11 + guest_R15_curr_instr_notENC + 4; 16499 /* Only allowed outside or last-in IT block; SIGILL if not so. */ 16500 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 16501 // and skip this insn if not selected; being cleverer is too 16502 // difficult 16503 mk_skip_over_T16_if_cond_is_false(condT); 16504 condT = IRTemp_INVALID; 16505 // now uncond 16506 llPutIReg(15, mkU32( dst | 1 /*CPSR.T*/ )); 16507 dres.jk_StopHere = Ijk_Boring; 16508 dres.whatNext = Dis_StopHere; 16509 DIP("b 0x%x\n", dst); 16510 goto decode_success; 16511 } 16512 16513 default: 16514 break; /* examine the next shortest prefix */ 16515 16516 } 16517 16518 16519 /* ================ 16-bit 15:12 cases ================ */ 16520 16521 switch (INSN0(15,12)) { 16522 16523 case BITS4(1,1,0,1): { 16524 /* ---------------- Bcond #simm8 ---------------- */ 16525 UInt cond = INSN0(11,8); 16526 Int simm8 = INSN0(7,0); 16527 simm8 = (simm8 << 24) >> 23; 16528 UInt dst = simm8 + guest_R15_curr_instr_notENC + 4; 16529 if (cond != ARMCondAL && cond != ARMCondNV) { 16530 /* Not allowed in an IT block; SIGILL if so. */ 16531 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate); 16532 16533 IRTemp kondT = newTemp(Ity_I32); 16534 assign( kondT, mk_armg_calculate_condition(cond) ); 16535 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)), 16536 Ijk_Boring, 16537 IRConst_U32(dst | 1/*CPSR.T*/), 16538 OFFB_R15T )); 16539 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 2) 16540 | 1 /*CPSR.T*/ )); 16541 dres.jk_StopHere = Ijk_Boring; 16542 dres.whatNext = Dis_StopHere; 16543 DIP("b%s 0x%x\n", nCC(cond), dst); 16544 goto decode_success; 16545 } 16546 break; 16547 } 16548 16549 default: 16550 break; /* hmm, nothing matched */ 16551 16552 } 16553 16554 /* ================ 16-bit misc cases ================ */ 16555 16556 /* ------ NOP ------ */ 16557 if (INSN0(15,0) == 0xBF00) { 16558 DIP("nop"); 16559 goto decode_success; 16560 } 16561 16562 /* ----------------------------------------------------------- */ 16563 /* -- -- */ 16564 /* -- Thumb 32-bit integer instructions -- */ 16565 /* -- -- */ 16566 /* ----------------------------------------------------------- */ 16567 16568 # define INSN1(_bMax,_bMin) SLICE_UInt(((UInt)insn1), (_bMax), (_bMin)) 16569 16570 /* second 16 bits of the instruction, if any */ 16571 vassert(insn1 == 0); 16572 insn1 = getUShortLittleEndianly( guest_instr+2 ); 16573 16574 anOp = Iop_INVALID; /* paranoia */ 16575 anOpNm = NULL; /* paranoia */ 16576 16577 /* Change result defaults to suit 32-bit insns. */ 16578 vassert(dres.whatNext == Dis_Continue); 16579 vassert(dres.len == 2); 16580 vassert(dres.continueAt == 0); 16581 dres.len = 4; 16582 16583 /* ---------------- BL/BLX simm26 ---------------- */ 16584 if (BITS5(1,1,1,1,0) == INSN0(15,11) && BITS2(1,1) == INSN1(15,14)) { 16585 UInt isBL = INSN1(12,12); 16586 UInt bS = INSN0(10,10); 16587 UInt bJ1 = INSN1(13,13); 16588 UInt bJ2 = INSN1(11,11); 16589 UInt bI1 = 1 ^ (bJ1 ^ bS); 16590 UInt bI2 = 1 ^ (bJ2 ^ bS); 16591 Int simm25 16592 = (bS << (1 + 1 + 10 + 11 + 1)) 16593 | (bI1 << (1 + 10 + 11 + 1)) 16594 | (bI2 << (10 + 11 + 1)) 16595 | (INSN0(9,0) << (11 + 1)) 16596 | (INSN1(10,0) << 1); 16597 simm25 = (simm25 << 7) >> 7; 16598 16599 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 16600 UInt dst = simm25 + guest_R15_curr_instr_notENC + 4; 16601 16602 /* One further validity case to check: in the case of BLX 16603 (not-BL), that insn1[0] must be zero. */ 16604 Bool valid = True; 16605 if (isBL == 0 && INSN1(0,0) == 1) valid = False; 16606 if (valid) { 16607 /* Only allowed outside or last-in IT block; SIGILL if not so. */ 16608 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 16609 // and skip this insn if not selected; being cleverer is too 16610 // difficult 16611 mk_skip_over_T32_if_cond_is_false(condT); 16612 condT = IRTemp_INVALID; 16613 // now uncond 16614 16615 /* We're returning to Thumb code, hence "| 1" */ 16616 putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 4) | 1 ), 16617 IRTemp_INVALID); 16618 if (isBL) { 16619 /* BL: unconditional T -> T call */ 16620 /* we're calling Thumb code, hence "| 1" */ 16621 llPutIReg(15, mkU32( dst | 1 )); 16622 DIP("bl 0x%x (stay in Thumb mode)\n", dst); 16623 } else { 16624 /* BLX: unconditional T -> A call */ 16625 /* we're calling ARM code, hence "& 3" to align to a 16626 valid ARM insn address */ 16627 llPutIReg(15, mkU32( dst & ~3 )); 16628 DIP("blx 0x%x (switch to ARM mode)\n", dst & ~3); 16629 } 16630 dres.whatNext = Dis_StopHere; 16631 dres.jk_StopHere = Ijk_Call; 16632 goto decode_success; 16633 } 16634 } 16635 16636 /* ---------------- {LD,ST}M{IA,DB} ---------------- */ 16637 if (0x3a2 == INSN0(15,6) // {LD,ST}MIA 16638 || 0x3a4 == INSN0(15,6)) { // {LD,ST}MDB 16639 UInt bW = INSN0(5,5); /* writeback Rn ? */ 16640 UInt bL = INSN0(4,4); 16641 UInt rN = INSN0(3,0); 16642 UInt bP = INSN1(15,15); /* reglist entry for r15 */ 16643 UInt bM = INSN1(14,14); /* reglist entry for r14 */ 16644 UInt rLmost = INSN1(12,0); /* reglist entry for r0 .. 12 */ 16645 UInt rL13 = INSN1(13,13); /* must be zero */ 16646 UInt regList = 0; 16647 Bool valid = True; 16648 16649 UInt bINC = 1; 16650 UInt bBEFORE = 0; 16651 if (INSN0(15,6) == 0x3a4) { 16652 bINC = 0; 16653 bBEFORE = 1; 16654 } 16655 16656 /* detect statically invalid cases, and construct the final 16657 reglist */ 16658 if (rL13 == 1) 16659 valid = False; 16660 16661 if (bL == 1) { 16662 regList = (bP << 15) | (bM << 14) | rLmost; 16663 if (rN == 15) valid = False; 16664 if (popcount32(regList) < 2) valid = False; 16665 if (bP == 1 && bM == 1) valid = False; 16666 if (bW == 1 && (regList & (1<<rN))) valid = False; 16667 } else { 16668 regList = (bM << 14) | rLmost; 16669 if (bP == 1) valid = False; 16670 if (rN == 15) valid = False; 16671 if (popcount32(regList) < 2) valid = False; 16672 if (bW == 1 && (regList & (1<<rN))) valid = False; 16673 } 16674 16675 if (valid) { 16676 if (bL == 1 && bP == 1) { 16677 // We'll be writing the PC. Hence: 16678 /* Only allowed outside or last-in IT block; SIGILL if not so. */ 16679 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 16680 } 16681 16682 /* Go uncond: */ 16683 mk_skip_over_T32_if_cond_is_false(condT); 16684 condT = IRTemp_INVALID; 16685 // now uncond 16686 16687 /* Generate the IR. This might generate a write to R15. */ 16688 mk_ldm_stm(False/*!arm*/, rN, bINC, bBEFORE, bW, bL, regList); 16689 16690 if (bL == 1 && (regList & (1<<15))) { 16691 // If we wrote to R15, we have an interworking return to 16692 // deal with. 16693 llPutIReg(15, llGetIReg(15)); 16694 dres.jk_StopHere = Ijk_Ret; 16695 dres.whatNext = Dis_StopHere; 16696 } 16697 16698 DIP("%sm%c%c r%u%s, {0x%04x}\n", 16699 bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a', 16700 rN, bW ? "!" : "", regList); 16701 16702 goto decode_success; 16703 } 16704 } 16705 16706 /* -------------- (T3) ADD{S}.W Rd, Rn, #constT -------------- */ 16707 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16708 && INSN0(9,5) == BITS5(0,1,0,0,0) 16709 && INSN1(15,15) == 0) { 16710 UInt bS = INSN0(4,4); 16711 UInt rN = INSN0(3,0); 16712 UInt rD = INSN1(11,8); 16713 Bool valid = !isBadRegT(rN) && !isBadRegT(rD); 16714 /* but allow "add.w reg, sp, #constT" for reg != PC */ 16715 if (!valid && rD <= 14 && rN == 13) 16716 valid = True; 16717 if (valid) { 16718 IRTemp argL = newTemp(Ity_I32); 16719 IRTemp argR = newTemp(Ity_I32); 16720 IRTemp res = newTemp(Ity_I32); 16721 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1); 16722 assign(argL, getIRegT(rN)); 16723 assign(argR, mkU32(imm32)); 16724 assign(res, binop(Iop_Add32, mkexpr(argL), mkexpr(argR))); 16725 putIRegT(rD, mkexpr(res), condT); 16726 if (bS == 1) 16727 setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT ); 16728 DIP("add%s.w r%u, r%u, #%u\n", 16729 bS == 1 ? "s" : "", rD, rN, imm32); 16730 goto decode_success; 16731 } 16732 } 16733 16734 /* ---------------- (T4) ADDW Rd, Rn, #uimm12 -------------- */ 16735 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16736 && INSN0(9,4) == BITS6(1,0,0,0,0,0) 16737 && INSN1(15,15) == 0) { 16738 UInt rN = INSN0(3,0); 16739 UInt rD = INSN1(11,8); 16740 Bool valid = !isBadRegT(rN) && !isBadRegT(rD); 16741 /* but allow "addw reg, sp, #uimm12" for reg != PC */ 16742 if (!valid && rD <= 14 && rN == 13) 16743 valid = True; 16744 if (valid) { 16745 IRTemp argL = newTemp(Ity_I32); 16746 IRTemp argR = newTemp(Ity_I32); 16747 IRTemp res = newTemp(Ity_I32); 16748 UInt imm12 = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0); 16749 assign(argL, getIRegT(rN)); 16750 assign(argR, mkU32(imm12)); 16751 assign(res, binop(Iop_Add32, mkexpr(argL), mkexpr(argR))); 16752 putIRegT(rD, mkexpr(res), condT); 16753 DIP("addw r%u, r%u, #%u\n", rD, rN, imm12); 16754 goto decode_success; 16755 } 16756 } 16757 16758 /* ---------------- (T2) CMP.W Rn, #constT ---------------- */ 16759 /* ---------------- (T2) CMN.W Rn, #constT ---------------- */ 16760 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16761 && ( INSN0(9,4) == BITS6(0,1,1,0,1,1) // CMP 16762 || INSN0(9,4) == BITS6(0,1,0,0,0,1)) // CMN 16763 && INSN1(15,15) == 0 16764 && INSN1(11,8) == BITS4(1,1,1,1)) { 16765 UInt rN = INSN0(3,0); 16766 if (rN != 15) { 16767 IRTemp argL = newTemp(Ity_I32); 16768 IRTemp argR = newTemp(Ity_I32); 16769 Bool isCMN = INSN0(9,4) == BITS6(0,1,0,0,0,1); 16770 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1); 16771 assign(argL, getIRegT(rN)); 16772 assign(argR, mkU32(imm32)); 16773 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB, 16774 argL, argR, condT ); 16775 DIP("%s.w r%u, #%u\n", isCMN ? "cmn" : "cmp", rN, imm32); 16776 goto decode_success; 16777 } 16778 } 16779 16780 /* -------------- (T1) TST.W Rn, #constT -------------- */ 16781 /* -------------- (T1) TEQ.W Rn, #constT -------------- */ 16782 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16783 && ( INSN0(9,4) == BITS6(0,0,0,0,0,1) // TST 16784 || INSN0(9,4) == BITS6(0,0,1,0,0,1)) // TEQ 16785 && INSN1(15,15) == 0 16786 && INSN1(11,8) == BITS4(1,1,1,1)) { 16787 UInt rN = INSN0(3,0); 16788 if (!isBadRegT(rN)) { // yes, really, it's inconsistent with CMP.W 16789 Bool isTST = INSN0(9,4) == BITS6(0,0,0,0,0,1); 16790 IRTemp argL = newTemp(Ity_I32); 16791 IRTemp argR = newTemp(Ity_I32); 16792 IRTemp res = newTemp(Ity_I32); 16793 IRTemp oldV = newTemp(Ity_I32); 16794 IRTemp oldC = newTemp(Ity_I32); 16795 Bool updC = False; 16796 UInt imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1); 16797 assign(argL, getIRegT(rN)); 16798 assign(argR, mkU32(imm32)); 16799 assign(res, binop(isTST ? Iop_And32 : Iop_Xor32, 16800 mkexpr(argL), mkexpr(argR))); 16801 assign( oldV, mk_armg_calculate_flag_v() ); 16802 assign( oldC, updC 16803 ? mkU32((imm32 >> 31) & 1) 16804 : mk_armg_calculate_flag_c() ); 16805 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT ); 16806 DIP("%s.w r%u, #%u\n", isTST ? "tst" : "teq", rN, imm32); 16807 goto decode_success; 16808 } 16809 } 16810 16811 /* -------------- (T3) SUB{S}.W Rd, Rn, #constT -------------- */ 16812 /* -------------- (T3) RSB{S}.W Rd, Rn, #constT -------------- */ 16813 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16814 && (INSN0(9,5) == BITS5(0,1,1,0,1) // SUB 16815 || INSN0(9,5) == BITS5(0,1,1,1,0)) // RSB 16816 && INSN1(15,15) == 0) { 16817 Bool isRSB = INSN0(9,5) == BITS5(0,1,1,1,0); 16818 UInt bS = INSN0(4,4); 16819 UInt rN = INSN0(3,0); 16820 UInt rD = INSN1(11,8); 16821 Bool valid = !isBadRegT(rN) && !isBadRegT(rD); 16822 /* but allow "sub{s}.w reg, sp, #constT 16823 this is (T2) of "SUB (SP minus immediate)" */ 16824 if (!valid && !isRSB && rN == 13 && rD != 15) 16825 valid = True; 16826 if (valid) { 16827 IRTemp argL = newTemp(Ity_I32); 16828 IRTemp argR = newTemp(Ity_I32); 16829 IRTemp res = newTemp(Ity_I32); 16830 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1); 16831 assign(argL, getIRegT(rN)); 16832 assign(argR, mkU32(imm32)); 16833 assign(res, isRSB 16834 ? binop(Iop_Sub32, mkexpr(argR), mkexpr(argL)) 16835 : binop(Iop_Sub32, mkexpr(argL), mkexpr(argR))); 16836 putIRegT(rD, mkexpr(res), condT); 16837 if (bS == 1) { 16838 if (isRSB) 16839 setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT ); 16840 else 16841 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT ); 16842 } 16843 DIP("%s%s.w r%u, r%u, #%u\n", 16844 isRSB ? "rsb" : "sub", bS == 1 ? "s" : "", rD, rN, imm32); 16845 goto decode_success; 16846 } 16847 } 16848 16849 /* -------------- (T4) SUBW Rd, Rn, #uimm12 ------------------- */ 16850 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16851 && INSN0(9,4) == BITS6(1,0,1,0,1,0) 16852 && INSN1(15,15) == 0) { 16853 UInt rN = INSN0(3,0); 16854 UInt rD = INSN1(11,8); 16855 Bool valid = !isBadRegT(rN) && !isBadRegT(rD); 16856 /* but allow "subw sp, sp, #uimm12" */ 16857 if (!valid && rD == 13 && rN == 13) 16858 valid = True; 16859 if (valid) { 16860 IRTemp argL = newTemp(Ity_I32); 16861 IRTemp argR = newTemp(Ity_I32); 16862 IRTemp res = newTemp(Ity_I32); 16863 UInt imm12 = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0); 16864 assign(argL, getIRegT(rN)); 16865 assign(argR, mkU32(imm12)); 16866 assign(res, binop(Iop_Sub32, mkexpr(argL), mkexpr(argR))); 16867 putIRegT(rD, mkexpr(res), condT); 16868 DIP("subw r%u, r%u, #%u\n", rD, rN, imm12); 16869 goto decode_success; 16870 } 16871 } 16872 16873 /* -------------- (T1) ADC{S}.W Rd, Rn, #constT -------------- */ 16874 /* -------------- (T1) SBC{S}.W Rd, Rn, #constT -------------- */ 16875 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16876 && ( INSN0(9,5) == BITS5(0,1,0,1,0) // ADC 16877 || INSN0(9,5) == BITS5(0,1,0,1,1)) // SBC 16878 && INSN1(15,15) == 0) { 16879 /* ADC: Rd = Rn + constT + oldC */ 16880 /* SBC: Rd = Rn - constT - (oldC ^ 1) */ 16881 UInt bS = INSN0(4,4); 16882 UInt rN = INSN0(3,0); 16883 UInt rD = INSN1(11,8); 16884 if (!isBadRegT(rN) && !isBadRegT(rD)) { 16885 IRTemp argL = newTemp(Ity_I32); 16886 IRTemp argR = newTemp(Ity_I32); 16887 IRTemp res = newTemp(Ity_I32); 16888 IRTemp oldC = newTemp(Ity_I32); 16889 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1); 16890 assign(argL, getIRegT(rN)); 16891 assign(argR, mkU32(imm32)); 16892 assign(oldC, mk_armg_calculate_flag_c() ); 16893 HChar* nm = "???"; 16894 switch (INSN0(9,5)) { 16895 case BITS5(0,1,0,1,0): // ADC 16896 nm = "adc"; 16897 assign(res, 16898 binop(Iop_Add32, 16899 binop(Iop_Add32, mkexpr(argL), mkexpr(argR)), 16900 mkexpr(oldC) )); 16901 putIRegT(rD, mkexpr(res), condT); 16902 if (bS) 16903 setFlags_D1_D2_ND( ARMG_CC_OP_ADC, 16904 argL, argR, oldC, condT ); 16905 break; 16906 case BITS5(0,1,0,1,1): // SBC 16907 nm = "sbc"; 16908 assign(res, 16909 binop(Iop_Sub32, 16910 binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)), 16911 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) )); 16912 putIRegT(rD, mkexpr(res), condT); 16913 if (bS) 16914 setFlags_D1_D2_ND( ARMG_CC_OP_SBB, 16915 argL, argR, oldC, condT ); 16916 break; 16917 default: 16918 vassert(0); 16919 } 16920 DIP("%s%s.w r%u, r%u, #%u\n", 16921 nm, bS == 1 ? "s" : "", rD, rN, imm32); 16922 goto decode_success; 16923 } 16924 } 16925 16926 /* -------------- (T1) ORR{S}.W Rd, Rn, #constT -------------- */ 16927 /* -------------- (T1) AND{S}.W Rd, Rn, #constT -------------- */ 16928 /* -------------- (T1) BIC{S}.W Rd, Rn, #constT -------------- */ 16929 /* -------------- (T1) EOR{S}.W Rd, Rn, #constT -------------- */ 16930 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16931 && ( INSN0(9,5) == BITS5(0,0,0,1,0) // ORR 16932 || INSN0(9,5) == BITS5(0,0,0,0,0) // AND 16933 || INSN0(9,5) == BITS5(0,0,0,0,1) // BIC 16934 || INSN0(9,5) == BITS5(0,0,1,0,0) // EOR 16935 || INSN0(9,5) == BITS5(0,0,0,1,1)) // ORN 16936 && INSN1(15,15) == 0) { 16937 UInt bS = INSN0(4,4); 16938 UInt rN = INSN0(3,0); 16939 UInt rD = INSN1(11,8); 16940 if (!isBadRegT(rN) && !isBadRegT(rD)) { 16941 Bool notArgR = False; 16942 IROp op = Iop_INVALID; 16943 HChar* nm = "???"; 16944 switch (INSN0(9,5)) { 16945 case BITS5(0,0,0,1,0): op = Iop_Or32; nm = "orr"; break; 16946 case BITS5(0,0,0,0,0): op = Iop_And32; nm = "and"; break; 16947 case BITS5(0,0,0,0,1): op = Iop_And32; nm = "bic"; 16948 notArgR = True; break; 16949 case BITS5(0,0,1,0,0): op = Iop_Xor32; nm = "eor"; break; 16950 case BITS5(0,0,0,1,1): op = Iop_Or32; nm = "orn"; 16951 notArgR = True; break; 16952 default: vassert(0); 16953 } 16954 IRTemp argL = newTemp(Ity_I32); 16955 IRTemp argR = newTemp(Ity_I32); 16956 IRTemp res = newTemp(Ity_I32); 16957 Bool updC = False; 16958 UInt imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1); 16959 assign(argL, getIRegT(rN)); 16960 assign(argR, mkU32(notArgR ? ~imm32 : imm32)); 16961 assign(res, binop(op, mkexpr(argL), mkexpr(argR))); 16962 putIRegT(rD, mkexpr(res), condT); 16963 if (bS) { 16964 IRTemp oldV = newTemp(Ity_I32); 16965 IRTemp oldC = newTemp(Ity_I32); 16966 assign( oldV, mk_armg_calculate_flag_v() ); 16967 assign( oldC, updC 16968 ? mkU32((imm32 >> 31) & 1) 16969 : mk_armg_calculate_flag_c() ); 16970 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 16971 condT ); 16972 } 16973 DIP("%s%s.w r%u, r%u, #%u\n", 16974 nm, bS == 1 ? "s" : "", rD, rN, imm32); 16975 goto decode_success; 16976 } 16977 } 16978 16979 /* ---------- (T3) ADD{S}.W Rd, Rn, Rm, {shift} ---------- */ 16980 /* ---------- (T3) SUB{S}.W Rd, Rn, Rm, {shift} ---------- */ 16981 /* ---------- (T3) RSB{S}.W Rd, Rn, Rm, {shift} ---------- */ 16982 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1) 16983 && ( INSN0(8,5) == BITS4(1,0,0,0) // add subopc 16984 || INSN0(8,5) == BITS4(1,1,0,1) // sub subopc 16985 || INSN0(8,5) == BITS4(1,1,1,0)) // rsb subopc 16986 && INSN1(15,15) == 0) { 16987 UInt rN = INSN0(3,0); 16988 UInt rD = INSN1(11,8); 16989 UInt rM = INSN1(3,0); 16990 UInt bS = INSN0(4,4); 16991 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 16992 UInt how = INSN1(5,4); 16993 16994 Bool valid = !isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM); 16995 /* but allow "add.w reg, sp, reg, lsl #N for N=0,1,2 or 3 16996 (T3) "ADD (SP plus register) */ 16997 if (!valid && INSN0(8,5) == BITS4(1,0,0,0) // add 16998 && rD != 15 && rN == 13 && imm5 <= 3 && how == 0) { 16999 valid = True; 17000 } 17001 /* also allow "sub.w reg, sp, reg w/ no shift 17002 (T1) "SUB (SP minus register) */ 17003 if (!valid && INSN0(8,5) == BITS4(1,1,0,1) // sub 17004 && rD != 15 && rN == 13 && imm5 == 0 && how == 0) { 17005 valid = True; 17006 } 17007 if (valid) { 17008 Bool swap = False; 17009 IROp op = Iop_INVALID; 17010 HChar* nm = "???"; 17011 switch (INSN0(8,5)) { 17012 case BITS4(1,0,0,0): op = Iop_Add32; nm = "add"; break; 17013 case BITS4(1,1,0,1): op = Iop_Sub32; nm = "sub"; break; 17014 case BITS4(1,1,1,0): op = Iop_Sub32; nm = "rsb"; 17015 swap = True; break; 17016 default: vassert(0); 17017 } 17018 17019 IRTemp argL = newTemp(Ity_I32); 17020 assign(argL, getIRegT(rN)); 17021 17022 IRTemp rMt = newTemp(Ity_I32); 17023 assign(rMt, getIRegT(rM)); 17024 17025 IRTemp argR = newTemp(Ity_I32); 17026 compute_result_and_C_after_shift_by_imm5( 17027 dis_buf, &argR, NULL, rMt, how, imm5, rM 17028 ); 17029 17030 IRTemp res = newTemp(Ity_I32); 17031 assign(res, swap 17032 ? binop(op, mkexpr(argR), mkexpr(argL)) 17033 : binop(op, mkexpr(argL), mkexpr(argR))); 17034 17035 putIRegT(rD, mkexpr(res), condT); 17036 if (bS) { 17037 switch (op) { 17038 case Iop_Add32: 17039 setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT ); 17040 break; 17041 case Iop_Sub32: 17042 if (swap) 17043 setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT ); 17044 else 17045 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT ); 17046 break; 17047 default: 17048 vassert(0); 17049 } 17050 } 17051 17052 DIP("%s%s.w r%u, r%u, %s\n", 17053 nm, bS ? "s" : "", rD, rN, dis_buf); 17054 goto decode_success; 17055 } 17056 } 17057 17058 /* ---------- (T3) ADC{S}.W Rd, Rn, Rm, {shift} ---------- */ 17059 /* ---------- (T2) SBC{S}.W Rd, Rn, Rm, {shift} ---------- */ 17060 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1) 17061 && ( INSN0(8,5) == BITS4(1,0,1,0) // adc subopc 17062 || INSN0(8,5) == BITS4(1,0,1,1)) // sbc subopc 17063 && INSN1(15,15) == 0) { 17064 /* ADC: Rd = Rn + shifter_operand + oldC */ 17065 /* SBC: Rd = Rn - shifter_operand - (oldC ^ 1) */ 17066 UInt rN = INSN0(3,0); 17067 UInt rD = INSN1(11,8); 17068 UInt rM = INSN1(3,0); 17069 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 17070 UInt bS = INSN0(4,4); 17071 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 17072 UInt how = INSN1(5,4); 17073 17074 IRTemp argL = newTemp(Ity_I32); 17075 assign(argL, getIRegT(rN)); 17076 17077 IRTemp rMt = newTemp(Ity_I32); 17078 assign(rMt, getIRegT(rM)); 17079 17080 IRTemp oldC = newTemp(Ity_I32); 17081 assign(oldC, mk_armg_calculate_flag_c()); 17082 17083 IRTemp argR = newTemp(Ity_I32); 17084 compute_result_and_C_after_shift_by_imm5( 17085 dis_buf, &argR, NULL, rMt, how, imm5, rM 17086 ); 17087 17088 HChar* nm = "???"; 17089 IRTemp res = newTemp(Ity_I32); 17090 switch (INSN0(8,5)) { 17091 case BITS4(1,0,1,0): // ADC 17092 nm = "adc"; 17093 assign(res, 17094 binop(Iop_Add32, 17095 binop(Iop_Add32, mkexpr(argL), mkexpr(argR)), 17096 mkexpr(oldC) )); 17097 putIRegT(rD, mkexpr(res), condT); 17098 if (bS) 17099 setFlags_D1_D2_ND( ARMG_CC_OP_ADC, 17100 argL, argR, oldC, condT ); 17101 break; 17102 case BITS4(1,0,1,1): // SBC 17103 nm = "sbc"; 17104 assign(res, 17105 binop(Iop_Sub32, 17106 binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)), 17107 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) )); 17108 putIRegT(rD, mkexpr(res), condT); 17109 if (bS) 17110 setFlags_D1_D2_ND( ARMG_CC_OP_SBB, 17111 argL, argR, oldC, condT ); 17112 break; 17113 default: 17114 vassert(0); 17115 } 17116 17117 DIP("%s%s.w r%u, r%u, %s\n", 17118 nm, bS ? "s" : "", rD, rN, dis_buf); 17119 goto decode_success; 17120 } 17121 } 17122 17123 /* ---------- (T3) AND{S}.W Rd, Rn, Rm, {shift} ---------- */ 17124 /* ---------- (T3) ORR{S}.W Rd, Rn, Rm, {shift} ---------- */ 17125 /* ---------- (T3) EOR{S}.W Rd, Rn, Rm, {shift} ---------- */ 17126 /* ---------- (T3) BIC{S}.W Rd, Rn, Rm, {shift} ---------- */ 17127 /* ---------- (T1) ORN{S}.W Rd, Rn, Rm, {shift} ---------- */ 17128 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1) 17129 && ( INSN0(8,5) == BITS4(0,0,0,0) // and subopc 17130 || INSN0(8,5) == BITS4(0,0,1,0) // orr subopc 17131 || INSN0(8,5) == BITS4(0,1,0,0) // eor subopc 17132 || INSN0(8,5) == BITS4(0,0,0,1) // bic subopc 17133 || INSN0(8,5) == BITS4(0,0,1,1)) // orn subopc 17134 && INSN1(15,15) == 0) { 17135 UInt rN = INSN0(3,0); 17136 UInt rD = INSN1(11,8); 17137 UInt rM = INSN1(3,0); 17138 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 17139 Bool notArgR = False; 17140 IROp op = Iop_INVALID; 17141 HChar* nm = "???"; 17142 switch (INSN0(8,5)) { 17143 case BITS4(0,0,0,0): op = Iop_And32; nm = "and"; break; 17144 case BITS4(0,0,1,0): op = Iop_Or32; nm = "orr"; break; 17145 case BITS4(0,1,0,0): op = Iop_Xor32; nm = "eor"; break; 17146 case BITS4(0,0,0,1): op = Iop_And32; nm = "bic"; 17147 notArgR = True; break; 17148 case BITS4(0,0,1,1): op = Iop_Or32; nm = "orn"; 17149 notArgR = True; break; 17150 default: vassert(0); 17151 } 17152 UInt bS = INSN0(4,4); 17153 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 17154 UInt how = INSN1(5,4); 17155 17156 IRTemp rNt = newTemp(Ity_I32); 17157 assign(rNt, getIRegT(rN)); 17158 17159 IRTemp rMt = newTemp(Ity_I32); 17160 assign(rMt, getIRegT(rM)); 17161 17162 IRTemp argR = newTemp(Ity_I32); 17163 IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID; 17164 17165 compute_result_and_C_after_shift_by_imm5( 17166 dis_buf, &argR, bS ? &oldC : NULL, rMt, how, imm5, rM 17167 ); 17168 17169 IRTemp res = newTemp(Ity_I32); 17170 if (notArgR) { 17171 vassert(op == Iop_And32 || op == Iop_Or32); 17172 assign(res, binop(op, mkexpr(rNt), 17173 unop(Iop_Not32, mkexpr(argR)))); 17174 } else { 17175 assign(res, binop(op, mkexpr(rNt), mkexpr(argR))); 17176 } 17177 17178 putIRegT(rD, mkexpr(res), condT); 17179 if (bS) { 17180 IRTemp oldV = newTemp(Ity_I32); 17181 assign( oldV, mk_armg_calculate_flag_v() ); 17182 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 17183 condT ); 17184 } 17185 17186 DIP("%s%s.w r%u, r%u, %s\n", 17187 nm, bS ? "s" : "", rD, rN, dis_buf); 17188 goto decode_success; 17189 } 17190 } 17191 17192 /* -------------- (T?) LSL{S}.W Rd, Rn, Rm -------------- */ 17193 /* -------------- (T?) LSR{S}.W Rd, Rn, Rm -------------- */ 17194 /* -------------- (T?) ASR{S}.W Rd, Rn, Rm -------------- */ 17195 /* -------------- (T?) ROR{S}.W Rd, Rn, Rm -------------- */ 17196 if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,0,0) 17197 && INSN1(15,12) == BITS4(1,1,1,1) 17198 && INSN1(7,4) == BITS4(0,0,0,0)) { 17199 UInt how = INSN0(6,5); // standard encoding 17200 UInt rN = INSN0(3,0); 17201 UInt rD = INSN1(11,8); 17202 UInt rM = INSN1(3,0); 17203 UInt bS = INSN0(4,4); 17204 Bool valid = !isBadRegT(rN) && !isBadRegT(rM) && !isBadRegT(rD); 17205 if (valid) { 17206 IRTemp rNt = newTemp(Ity_I32); 17207 IRTemp rMt = newTemp(Ity_I32); 17208 IRTemp res = newTemp(Ity_I32); 17209 IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID; 17210 IRTemp oldV = bS ? newTemp(Ity_I32) : IRTemp_INVALID; 17211 HChar* nms[4] = { "lsl", "lsr", "asr", "ror" }; 17212 HChar* nm = nms[how]; 17213 assign(rNt, getIRegT(rN)); 17214 assign(rMt, getIRegT(rM)); 17215 compute_result_and_C_after_shift_by_reg( 17216 dis_buf, &res, bS ? &oldC : NULL, 17217 rNt, how, rMt, rN, rM 17218 ); 17219 if (bS) 17220 assign(oldV, mk_armg_calculate_flag_v()); 17221 putIRegT(rD, mkexpr(res), condT); 17222 if (bS) { 17223 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 17224 condT ); 17225 } 17226 DIP("%s%s.w r%u, r%u, r%u\n", 17227 nm, bS ? "s" : "", rD, rN, rM); 17228 goto decode_success; 17229 } 17230 } 17231 17232 /* ------------ (T?) MOV{S}.W Rd, Rn, {shift} ------------ */ 17233 /* ------------ (T?) MVN{S}.W Rd, Rn, {shift} ------------ */ 17234 if ((INSN0(15,0) & 0xFFCF) == 0xEA4F 17235 && INSN1(15,15) == 0) { 17236 UInt rD = INSN1(11,8); 17237 UInt rN = INSN1(3,0); 17238 if (!isBadRegT(rD) && !isBadRegT(rN)) { 17239 UInt bS = INSN0(4,4); 17240 UInt isMVN = INSN0(5,5); 17241 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 17242 UInt how = INSN1(5,4); 17243 17244 IRTemp rNt = newTemp(Ity_I32); 17245 assign(rNt, getIRegT(rN)); 17246 17247 IRTemp oldRn = newTemp(Ity_I32); 17248 IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID; 17249 compute_result_and_C_after_shift_by_imm5( 17250 dis_buf, &oldRn, bS ? &oldC : NULL, rNt, how, imm5, rN 17251 ); 17252 17253 IRTemp res = newTemp(Ity_I32); 17254 assign(res, isMVN ? unop(Iop_Not32, mkexpr(oldRn)) 17255 : mkexpr(oldRn)); 17256 17257 putIRegT(rD, mkexpr(res), condT); 17258 if (bS) { 17259 IRTemp oldV = newTemp(Ity_I32); 17260 assign( oldV, mk_armg_calculate_flag_v() ); 17261 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT); 17262 } 17263 DIP("%s%s.w r%u, %s\n", 17264 isMVN ? "mvn" : "mov", bS ? "s" : "", rD, dis_buf); 17265 goto decode_success; 17266 } 17267 } 17268 17269 /* -------------- (T?) TST.W Rn, Rm, {shift} -------------- */ 17270 /* -------------- (T?) TEQ.W Rn, Rm, {shift} -------------- */ 17271 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1) 17272 && ( INSN0(8,4) == BITS5(0,0,0,0,1) // TST 17273 || INSN0(8,4) == BITS5(0,1,0,0,1)) // TEQ 17274 && INSN1(15,15) == 0 17275 && INSN1(11,8) == BITS4(1,1,1,1)) { 17276 UInt rN = INSN0(3,0); 17277 UInt rM = INSN1(3,0); 17278 if (!isBadRegT(rN) && !isBadRegT(rM)) { 17279 Bool isTST = INSN0(8,4) == BITS5(0,0,0,0,1); 17280 17281 UInt how = INSN1(5,4); 17282 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 17283 17284 IRTemp argL = newTemp(Ity_I32); 17285 assign(argL, getIRegT(rN)); 17286 17287 IRTemp rMt = newTemp(Ity_I32); 17288 assign(rMt, getIRegT(rM)); 17289 17290 IRTemp argR = newTemp(Ity_I32); 17291 IRTemp oldC = newTemp(Ity_I32); 17292 compute_result_and_C_after_shift_by_imm5( 17293 dis_buf, &argR, &oldC, rMt, how, imm5, rM 17294 ); 17295 17296 IRTemp oldV = newTemp(Ity_I32); 17297 assign( oldV, mk_armg_calculate_flag_v() ); 17298 17299 IRTemp res = newTemp(Ity_I32); 17300 assign(res, binop(isTST ? Iop_And32 : Iop_Xor32, 17301 mkexpr(argL), mkexpr(argR))); 17302 17303 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 17304 condT ); 17305 DIP("%s.w r%u, %s\n", isTST ? "tst" : "teq", rN, dis_buf); 17306 goto decode_success; 17307 } 17308 } 17309 17310 /* -------------- (T3) CMP.W Rn, Rm, {shift} -------------- */ 17311 /* -------------- (T2) CMN.W Rn, Rm, {shift} -------------- */ 17312 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1) 17313 && ( INSN0(8,4) == BITS5(1,1,0,1,1) // CMP 17314 || INSN0(8,4) == BITS5(1,0,0,0,1)) // CMN 17315 && INSN1(15,15) == 0 17316 && INSN1(11,8) == BITS4(1,1,1,1)) { 17317 UInt rN = INSN0(3,0); 17318 UInt rM = INSN1(3,0); 17319 if (!isBadRegT(rN) && !isBadRegT(rM)) { 17320 Bool isCMN = INSN0(8,4) == BITS5(1,0,0,0,1); 17321 UInt how = INSN1(5,4); 17322 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 17323 17324 IRTemp argL = newTemp(Ity_I32); 17325 assign(argL, getIRegT(rN)); 17326 17327 IRTemp rMt = newTemp(Ity_I32); 17328 assign(rMt, getIRegT(rM)); 17329 17330 IRTemp argR = newTemp(Ity_I32); 17331 compute_result_and_C_after_shift_by_imm5( 17332 dis_buf, &argR, NULL, rMt, how, imm5, rM 17333 ); 17334 17335 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB, 17336 argL, argR, condT ); 17337 17338 DIP("%s.w r%u, %s\n", isCMN ? "cmn" : "cmp", rN, dis_buf); 17339 goto decode_success; 17340 } 17341 } 17342 17343 /* -------------- (T2) MOV{S}.W Rd, #constT -------------- */ 17344 /* -------------- (T2) MVN{S}.W Rd, #constT -------------- */ 17345 if (INSN0(15,11) == BITS5(1,1,1,1,0) 17346 && ( INSN0(9,5) == BITS5(0,0,0,1,0) // MOV 17347 || INSN0(9,5) == BITS5(0,0,0,1,1)) // MVN 17348 && INSN0(3,0) == BITS4(1,1,1,1) 17349 && INSN1(15,15) == 0) { 17350 UInt rD = INSN1(11,8); 17351 if (!isBadRegT(rD)) { 17352 Bool updC = False; 17353 UInt bS = INSN0(4,4); 17354 Bool isMVN = INSN0(5,5) == 1; 17355 UInt imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1); 17356 IRTemp res = newTemp(Ity_I32); 17357 assign(res, mkU32(isMVN ? ~imm32 : imm32)); 17358 putIRegT(rD, mkexpr(res), condT); 17359 if (bS) { 17360 IRTemp oldV = newTemp(Ity_I32); 17361 IRTemp oldC = newTemp(Ity_I32); 17362 assign( oldV, mk_armg_calculate_flag_v() ); 17363 assign( oldC, updC 17364 ? mkU32((imm32 >> 31) & 1) 17365 : mk_armg_calculate_flag_c() ); 17366 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 17367 condT ); 17368 } 17369 DIP("%s%s.w r%u, #%u\n", 17370 isMVN ? "mvn" : "mov", bS ? "s" : "", rD, imm32); 17371 goto decode_success; 17372 } 17373 } 17374 17375 /* -------------- (T3) MOVW Rd, #imm16 -------------- */ 17376 if (INSN0(15,11) == BITS5(1,1,1,1,0) 17377 && INSN0(9,4) == BITS6(1,0,0,1,0,0) 17378 && INSN1(15,15) == 0) { 17379 UInt rD = INSN1(11,8); 17380 if (!isBadRegT(rD)) { 17381 UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11) 17382 | (INSN1(14,12) << 8) | INSN1(7,0); 17383 putIRegT(rD, mkU32(imm16), condT); 17384 DIP("movw r%u, #%u\n", rD, imm16); 17385 goto decode_success; 17386 } 17387 } 17388 17389 /* ---------------- MOVT Rd, #imm16 ---------------- */ 17390 if (INSN0(15,11) == BITS5(1,1,1,1,0) 17391 && INSN0(9,4) == BITS6(1,0,1,1,0,0) 17392 && INSN1(15,15) == 0) { 17393 UInt rD = INSN1(11,8); 17394 if (!isBadRegT(rD)) { 17395 UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11) 17396 | (INSN1(14,12) << 8) | INSN1(7,0); 17397 IRTemp res = newTemp(Ity_I32); 17398 assign(res, 17399 binop(Iop_Or32, 17400 binop(Iop_And32, getIRegT(rD), mkU32(0xFFFF)), 17401 mkU32(imm16 << 16))); 17402 putIRegT(rD, mkexpr(res), condT); 17403 DIP("movt r%u, #%u\n", rD, imm16); 17404 goto decode_success; 17405 } 17406 } 17407 17408 /* ---------------- LD/ST reg+/-#imm8 ---------------- */ 17409 /* Loads and stores of the form: 17410 op Rt, [Rn, #-imm8] or 17411 op Rt, [Rn], #+/-imm8 or 17412 op Rt, [Rn, #+/-imm8]! 17413 where op is one of 17414 ldrb ldrh ldr ldrsb ldrsh 17415 strb strh str 17416 */ 17417 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) && INSN1(11,11) == 1) { 17418 Bool valid = True; 17419 Bool syned = False; 17420 Bool isST = False; 17421 IRType ty = Ity_I8; 17422 HChar* nm = "???"; 17423 17424 switch (INSN0(8,4)) { 17425 case BITS5(0,0,0,0,0): // strb 17426 nm = "strb"; isST = True; break; 17427 case BITS5(0,0,0,0,1): // ldrb 17428 nm = "ldrb"; break; 17429 case BITS5(1,0,0,0,1): // ldrsb 17430 nm = "ldrsb"; syned = True; break; 17431 case BITS5(0,0,0,1,0): // strh 17432 nm = "strh"; ty = Ity_I16; isST = True; break; 17433 case BITS5(0,0,0,1,1): // ldrh 17434 nm = "ldrh"; ty = Ity_I16; break; 17435 case BITS5(1,0,0,1,1): // ldrsh 17436 nm = "ldrsh"; ty = Ity_I16; syned = True; break; 17437 case BITS5(0,0,1,0,0): // str 17438 nm = "str"; ty = Ity_I32; isST = True; break; 17439 case BITS5(0,0,1,0,1): 17440 nm = "ldr"; ty = Ity_I32; break; // ldr 17441 default: 17442 valid = False; break; 17443 } 17444 17445 UInt rN = INSN0(3,0); 17446 UInt rT = INSN1(15,12); 17447 UInt bP = INSN1(10,10); 17448 UInt bU = INSN1(9,9); 17449 UInt bW = INSN1(8,8); 17450 UInt imm8 = INSN1(7,0); 17451 Bool loadsPC = False; 17452 17453 if (valid) { 17454 if (bP == 1 && bU == 1 && bW == 0) 17455 valid = False; 17456 if (bP == 0 && bW == 0) 17457 valid = False; 17458 if (rN == 15) 17459 valid = False; 17460 if (bW == 1 && rN == rT) 17461 valid = False; 17462 if (ty == Ity_I8 || ty == Ity_I16) { 17463 if (isBadRegT(rT)) 17464 valid = False; 17465 } else { 17466 /* ty == Ity_I32 */ 17467 if (isST && rT == 15) 17468 valid = False; 17469 if (!isST && rT == 15) 17470 loadsPC = True; 17471 } 17472 } 17473 17474 if (valid) { 17475 // if it's a branch, it can't happen in the middle of an IT block 17476 if (loadsPC) 17477 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 17478 // go uncond 17479 mk_skip_over_T32_if_cond_is_false(condT); 17480 condT = IRTemp_INVALID; 17481 // now uncond 17482 17483 IRTemp preAddr = newTemp(Ity_I32); 17484 assign(preAddr, getIRegT(rN)); 17485 17486 IRTemp postAddr = newTemp(Ity_I32); 17487 assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32, 17488 mkexpr(preAddr), mkU32(imm8))); 17489 17490 IRTemp transAddr = bP == 1 ? postAddr : preAddr; 17491 17492 if (isST) { 17493 17494 /* Store. If necessary, update the base register before 17495 the store itself, so that the common idiom of "str rX, 17496 [sp, #-4]!" (store rX at sp-4, then do new sp = sp-4, 17497 a.k.a "push rX") doesn't cause Memcheck to complain 17498 that the access is below the stack pointer. Also, not 17499 updating sp before the store confuses Valgrind's 17500 dynamic stack-extending logic. So do it before the 17501 store. Hence we need to snarf the store data before 17502 doing the basereg update. */ 17503 17504 /* get hold of the data to be stored */ 17505 IRTemp oldRt = newTemp(Ity_I32); 17506 assign(oldRt, getIRegT(rT)); 17507 17508 /* Update Rn if necessary. */ 17509 if (bW == 1) { 17510 vassert(rN != rT); // assured by validity check above 17511 putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID); 17512 } 17513 17514 /* generate the transfer */ 17515 switch (ty) { 17516 case Ity_I8: 17517 storeLE(mkexpr(transAddr), 17518 unop(Iop_32to8, mkexpr(oldRt))); 17519 break; 17520 case Ity_I16: 17521 storeLE(mkexpr(transAddr), 17522 unop(Iop_32to16, mkexpr(oldRt))); 17523 break; 17524 case Ity_I32: 17525 storeLE(mkexpr(transAddr), mkexpr(oldRt)); 17526 break; 17527 default: 17528 vassert(0); 17529 } 17530 17531 } else { 17532 17533 /* Load. */ 17534 17535 /* generate the transfer */ 17536 IRTemp newRt = newTemp(Ity_I32); 17537 IROp widen = Iop_INVALID; 17538 switch (ty) { 17539 case Ity_I8: 17540 widen = syned ? Iop_8Sto32 : Iop_8Uto32; break; 17541 case Ity_I16: 17542 widen = syned ? Iop_16Sto32 : Iop_16Uto32; break; 17543 case Ity_I32: 17544 break; 17545 default: 17546 vassert(0); 17547 } 17548 if (widen == Iop_INVALID) { 17549 assign(newRt, loadLE(ty, mkexpr(transAddr))); 17550 } else { 17551 assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr)))); 17552 } 17553 if (loadsPC) { 17554 vassert(rT == 15); 17555 llPutIReg(rT, mkexpr(newRt)); 17556 } else { 17557 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID); 17558 } 17559 17560 /* Update Rn if necessary. */ 17561 if (bW == 1) { 17562 vassert(rN != rT); // assured by validity check above 17563 putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID); 17564 } 17565 17566 if (loadsPC) { 17567 /* Presumably this is an interworking branch. */ 17568 vassert(rN != 15); // assured by validity check above 17569 llPutIReg(15, mkexpr(newRt)); 17570 dres.jk_StopHere = Ijk_Boring; /* or _Ret ? */ 17571 dres.whatNext = Dis_StopHere; 17572 } 17573 } 17574 17575 if (bP == 1 && bW == 0) { 17576 DIP("%s.w r%u, [r%u, #%c%u]\n", 17577 nm, rT, rN, bU ? '+' : '-', imm8); 17578 } 17579 else if (bP == 1 && bW == 1) { 17580 DIP("%s.w r%u, [r%u, #%c%u]!\n", 17581 nm, rT, rN, bU ? '+' : '-', imm8); 17582 } 17583 else { 17584 vassert(bP == 0 && bW == 1); 17585 DIP("%s.w r%u, [r%u], #%c%u\n", 17586 nm, rT, rN, bU ? '+' : '-', imm8); 17587 } 17588 17589 goto decode_success; 17590 } 17591 } 17592 17593 /* ------------- LD/ST reg+(reg<<imm2) ------------- */ 17594 /* Loads and stores of the form: 17595 op Rt, [Rn, Rm, LSL #imm8] 17596 where op is one of 17597 ldrb ldrh ldr ldrsb ldrsh 17598 strb strh str 17599 */ 17600 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) 17601 && INSN1(11,6) == BITS6(0,0,0,0,0,0)) { 17602 Bool valid = True; 17603 Bool syned = False; 17604 Bool isST = False; 17605 IRType ty = Ity_I8; 17606 HChar* nm = "???"; 17607 17608 switch (INSN0(8,4)) { 17609 case BITS5(0,0,0,0,0): // strb 17610 nm = "strb"; isST = True; break; 17611 case BITS5(0,0,0,0,1): // ldrb 17612 nm = "ldrb"; break; 17613 case BITS5(1,0,0,0,1): // ldrsb 17614 nm = "ldrsb"; syned = True; break; 17615 case BITS5(0,0,0,1,0): // strh 17616 nm = "strh"; ty = Ity_I16; isST = True; break; 17617 case BITS5(0,0,0,1,1): // ldrh 17618 nm = "ldrh"; ty = Ity_I16; break; 17619 case BITS5(1,0,0,1,1): // ldrsh 17620 nm = "ldrsh"; ty = Ity_I16; syned = True; break; 17621 case BITS5(0,0,1,0,0): // str 17622 nm = "str"; ty = Ity_I32; isST = True; break; 17623 case BITS5(0,0,1,0,1): 17624 nm = "ldr"; ty = Ity_I32; break; // ldr 17625 default: 17626 valid = False; break; 17627 } 17628 17629 UInt rN = INSN0(3,0); 17630 UInt rM = INSN1(3,0); 17631 UInt rT = INSN1(15,12); 17632 UInt imm2 = INSN1(5,4); 17633 Bool loadsPC = False; 17634 17635 if (ty == Ity_I8 || ty == Ity_I16) { 17636 /* all 8- and 16-bit load and store cases have the 17637 same exclusion set. */ 17638 if (rN == 15 || isBadRegT(rT) || isBadRegT(rM)) 17639 valid = False; 17640 } else { 17641 vassert(ty == Ity_I32); 17642 if (rN == 15 || isBadRegT(rM)) 17643 valid = False; 17644 if (isST && rT == 15) 17645 valid = False; 17646 /* If it is a load and rT is 15, that's only allowable if we 17647 not in an IT block, or are the last in it. Need to insert 17648 a dynamic check for that. */ 17649 if (!isST && rT == 15) 17650 loadsPC = True; 17651 } 17652 17653 if (valid) { 17654 // if it's a branch, it can't happen in the middle of an IT block 17655 if (loadsPC) 17656 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 17657 // go uncond 17658 mk_skip_over_T32_if_cond_is_false(condT); 17659 condT = IRTemp_INVALID; 17660 // now uncond 17661 17662 IRTemp transAddr = newTemp(Ity_I32); 17663 assign(transAddr, 17664 binop( Iop_Add32, 17665 getIRegT(rN), 17666 binop(Iop_Shl32, getIRegT(rM), mkU8(imm2)) )); 17667 17668 if (isST) { 17669 IRTemp oldRt = newTemp(Ity_I32); 17670 assign(oldRt, getIRegT(rT)); 17671 switch (ty) { 17672 case Ity_I8: 17673 storeLE(mkexpr(transAddr), 17674 unop(Iop_32to8, mkexpr(oldRt))); 17675 break; 17676 case Ity_I16: 17677 storeLE(mkexpr(transAddr), 17678 unop(Iop_32to16, mkexpr(oldRt))); 17679 break; 17680 case Ity_I32: 17681 storeLE(mkexpr(transAddr), mkexpr(oldRt)); 17682 break; 17683 default: 17684 vassert(0); 17685 } 17686 } else { 17687 IRTemp newRt = newTemp(Ity_I32); 17688 IROp widen = Iop_INVALID; 17689 switch (ty) { 17690 case Ity_I8: 17691 widen = syned ? Iop_8Sto32 : Iop_8Uto32; break; 17692 case Ity_I16: 17693 widen = syned ? Iop_16Sto32 : Iop_16Uto32; break; 17694 case Ity_I32: 17695 break; 17696 default: 17697 vassert(0); 17698 } 17699 if (widen == Iop_INVALID) { 17700 assign(newRt, loadLE(ty, mkexpr(transAddr))); 17701 } else { 17702 assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr)))); 17703 } 17704 17705 /* If we're loading the PC, putIRegT will assert. So go 17706 direct via llPutIReg. In all other cases use putIRegT 17707 as it is safer (although could simply use llPutIReg for 17708 _all_ cases here.) */ 17709 if (loadsPC) { 17710 vassert(rT == 15); 17711 llPutIReg(rT, mkexpr(newRt)); 17712 } else { 17713 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID); 17714 } 17715 17716 if (loadsPC) { 17717 /* Presumably this is an interworking branch. */ 17718 llPutIReg(15, mkexpr(newRt)); 17719 dres.jk_StopHere = Ijk_Boring; /* or _Ret ? */ 17720 dres.whatNext = Dis_StopHere; 17721 } 17722 } 17723 17724 DIP("%s.w r%u, [r%u, r%u, LSL #%u]\n", 17725 nm, rT, rN, rM, imm2); 17726 17727 goto decode_success; 17728 } 17729 } 17730 17731 /* --------------- LD/ST reg+imm12 --------------- */ 17732 /* Loads and stores of the form: 17733 op Rt, [Rn, +#imm12] 17734 where op is one of 17735 ldrb ldrh ldr ldrsb ldrsh 17736 strb strh str 17737 */ 17738 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)) { 17739 Bool valid = True; 17740 Bool syned = False; 17741 Bool isST = False; 17742 IRType ty = Ity_I8; 17743 HChar* nm = "???"; 17744 17745 switch (INSN0(8,4)) { 17746 case BITS5(0,1,0,0,0): // strb 17747 nm = "strb"; isST = True; break; 17748 case BITS5(0,1,0,0,1): // ldrb 17749 nm = "ldrb"; break; 17750 case BITS5(1,1,0,0,1): // ldrsb 17751 nm = "ldrsb"; syned = True; break; 17752 case BITS5(0,1,0,1,0): // strh 17753 nm = "strh"; ty = Ity_I16; isST = True; break; 17754 case BITS5(0,1,0,1,1): // ldrh 17755 nm = "ldrh"; ty = Ity_I16; break; 17756 case BITS5(1,1,0,1,1): // ldrsh 17757 nm = "ldrsh"; ty = Ity_I16; syned = True; break; 17758 case BITS5(0,1,1,0,0): // str 17759 nm = "str"; ty = Ity_I32; isST = True; break; 17760 case BITS5(0,1,1,0,1): 17761 nm = "ldr"; ty = Ity_I32; break; // ldr 17762 default: 17763 valid = False; break; 17764 } 17765 17766 UInt rN = INSN0(3,0); 17767 UInt rT = INSN1(15,12); 17768 UInt imm12 = INSN1(11,0); 17769 Bool loadsPC = False; 17770 17771 if (ty == Ity_I8 || ty == Ity_I16) { 17772 /* all 8- and 16-bit load and store cases have the 17773 same exclusion set. */ 17774 if (rN == 15 || isBadRegT(rT)) 17775 valid = False; 17776 } else { 17777 vassert(ty == Ity_I32); 17778 if (isST) { 17779 if (rN == 15 || rT == 15) 17780 valid = False; 17781 } else { 17782 /* For a 32-bit load, rT == 15 is only allowable if we not 17783 in an IT block, or are the last in it. Need to insert 17784 a dynamic check for that. Also, in this particular 17785 case, rN == 15 is allowable. In this case however, the 17786 value obtained for rN is (apparently) 17787 "word-align(address of current insn + 4)". */ 17788 if (rT == 15) 17789 loadsPC = True; 17790 } 17791 } 17792 17793 if (valid) { 17794 // if it's a branch, it can't happen in the middle of an IT block 17795 if (loadsPC) 17796 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 17797 // go uncond 17798 mk_skip_over_T32_if_cond_is_false(condT); 17799 condT = IRTemp_INVALID; 17800 // now uncond 17801 17802 IRTemp rNt = newTemp(Ity_I32); 17803 if (rN == 15) { 17804 vassert(ty == Ity_I32 && !isST); 17805 assign(rNt, binop(Iop_And32, getIRegT(rN), mkU32(~3))); 17806 } else { 17807 assign(rNt, getIRegT(rN)); 17808 } 17809 17810 IRTemp transAddr = newTemp(Ity_I32); 17811 assign(transAddr, 17812 binop( Iop_Add32, mkexpr(rNt), mkU32(imm12) )); 17813 17814 if (isST) { 17815 IRTemp oldRt = newTemp(Ity_I32); 17816 assign(oldRt, getIRegT(rT)); 17817 switch (ty) { 17818 case Ity_I8: 17819 storeLE(mkexpr(transAddr), 17820 unop(Iop_32to8, mkexpr(oldRt))); 17821 break; 17822 case Ity_I16: 17823 storeLE(mkexpr(transAddr), 17824 unop(Iop_32to16, mkexpr(oldRt))); 17825 break; 17826 case Ity_I32: 17827 storeLE(mkexpr(transAddr), mkexpr(oldRt)); 17828 break; 17829 default: 17830 vassert(0); 17831 } 17832 } else { 17833 IRTemp newRt = newTemp(Ity_I32); 17834 IROp widen = Iop_INVALID; 17835 switch (ty) { 17836 case Ity_I8: 17837 widen = syned ? Iop_8Sto32 : Iop_8Uto32; break; 17838 case Ity_I16: 17839 widen = syned ? Iop_16Sto32 : Iop_16Uto32; break; 17840 case Ity_I32: 17841 break; 17842 default: 17843 vassert(0); 17844 } 17845 if (widen == Iop_INVALID) { 17846 assign(newRt, loadLE(ty, mkexpr(transAddr))); 17847 } else { 17848 assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr)))); 17849 } 17850 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID); 17851 17852 if (loadsPC) { 17853 /* Presumably this is an interworking branch. */ 17854 irsb->next = mkexpr(newRt); 17855 irsb->jumpkind = Ijk_Boring; /* or _Ret ? */ 17856 dres.whatNext = Dis_StopHere; 17857 } 17858 } 17859 17860 DIP("%s.w r%u, [r%u, +#%u]\n", nm, rT, rN, imm12); 17861 17862 goto decode_success; 17863 } 17864 } 17865 17866 /* -------------- LDRD/STRD reg+/-#imm8 -------------- */ 17867 /* Doubleword loads and stores of the form: 17868 ldrd/strd Rt, Rt2, [Rn, #-imm8] or 17869 ldrd/strd Rt, Rt2, [Rn], #+/-imm8 or 17870 ldrd/strd Rt, Rt2, [Rn, #+/-imm8]! 17871 */ 17872 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,0) && INSN0(6,6) == 1) { 17873 UInt bP = INSN0(8,8); 17874 UInt bU = INSN0(7,7); 17875 UInt bW = INSN0(5,5); 17876 UInt bL = INSN0(4,4); // 1: load 0: store 17877 UInt rN = INSN0(3,0); 17878 UInt rT = INSN1(15,12); 17879 UInt rT2 = INSN1(11,8); 17880 UInt imm8 = INSN1(7,0); 17881 17882 Bool valid = True; 17883 if (bP == 0 && bW == 0) valid = False; 17884 if (bW == 1 && (rN == rT || rN == rT2)) valid = False; 17885 if (isBadRegT(rT) || isBadRegT(rT2)) valid = False; 17886 if (rN == 15) valid = False; 17887 if (bL == 1 && rT == rT2) valid = False; 17888 17889 if (valid) { 17890 // go uncond 17891 mk_skip_over_T32_if_cond_is_false(condT); 17892 condT = IRTemp_INVALID; 17893 // now uncond 17894 17895 IRTemp preAddr = newTemp(Ity_I32); 17896 assign(preAddr, getIRegT(rN)); 17897 17898 IRTemp postAddr = newTemp(Ity_I32); 17899 assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32, 17900 mkexpr(preAddr), mkU32(imm8 << 2))); 17901 17902 IRTemp transAddr = bP == 1 ? postAddr : preAddr; 17903 17904 if (bL == 0) { 17905 IRTemp oldRt = newTemp(Ity_I32); 17906 IRTemp oldRt2 = newTemp(Ity_I32); 17907 assign(oldRt, getIRegT(rT)); 17908 assign(oldRt2, getIRegT(rT2)); 17909 storeLE(mkexpr(transAddr), 17910 mkexpr(oldRt)); 17911 storeLE(binop(Iop_Add32, mkexpr(transAddr), mkU32(4)), 17912 mkexpr(oldRt2)); 17913 } else { 17914 IRTemp newRt = newTemp(Ity_I32); 17915 IRTemp newRt2 = newTemp(Ity_I32); 17916 assign(newRt, 17917 loadLE(Ity_I32, 17918 mkexpr(transAddr))); 17919 assign(newRt2, 17920 loadLE(Ity_I32, 17921 binop(Iop_Add32, mkexpr(transAddr), mkU32(4)))); 17922 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID); 17923 putIRegT(rT2, mkexpr(newRt2), IRTemp_INVALID); 17924 } 17925 17926 if (bW == 1) { 17927 putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID); 17928 } 17929 17930 HChar* nm = bL ? "ldrd" : "strd"; 17931 17932 if (bP == 1 && bW == 0) { 17933 DIP("%s.w r%u, r%u, [r%u, #%c%u]\n", 17934 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2); 17935 } 17936 else if (bP == 1 && bW == 1) { 17937 DIP("%s.w r%u, r%u, [r%u, #%c%u]!\n", 17938 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2); 17939 } 17940 else { 17941 vassert(bP == 0 && bW == 1); 17942 DIP("%s.w r%u, r%u, [r%u], #%c%u\n", 17943 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2); 17944 } 17945 17946 goto decode_success; 17947 } 17948 } 17949 17950 /* -------------- (T3) Bcond.W label -------------- */ 17951 /* This variant carries its own condition, so can't be part of an 17952 IT block ... */ 17953 if (INSN0(15,11) == BITS5(1,1,1,1,0) 17954 && INSN1(15,14) == BITS2(1,0) 17955 && INSN1(12,12) == 0) { 17956 UInt cond = INSN0(9,6); 17957 if (cond != ARMCondAL && cond != ARMCondNV) { 17958 Int simm21 17959 = (INSN0(10,10) << (1 + 1 + 6 + 11 + 1)) 17960 | (INSN1(11,11) << (1 + 6 + 11 + 1)) 17961 | (INSN1(13,13) << (6 + 11 + 1)) 17962 | (INSN0(5,0) << (11 + 1)) 17963 | (INSN1(10,0) << 1); 17964 simm21 = (simm21 << 11) >> 11; 17965 17966 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 17967 UInt dst = simm21 + guest_R15_curr_instr_notENC + 4; 17968 17969 /* Not allowed in an IT block; SIGILL if so. */ 17970 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate); 17971 17972 IRTemp kondT = newTemp(Ity_I32); 17973 assign( kondT, mk_armg_calculate_condition(cond) ); 17974 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)), 17975 Ijk_Boring, 17976 IRConst_U32(dst | 1/*CPSR.T*/), 17977 OFFB_R15T )); 17978 llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 4) 17979 | 1 /*CPSR.T*/ )); 17980 dres.jk_StopHere = Ijk_Boring; 17981 dres.whatNext = Dis_StopHere; 17982 DIP("b%s.w 0x%x\n", nCC(cond), dst); 17983 goto decode_success; 17984 } 17985 } 17986 17987 /* ---------------- (T4) B.W label ---------------- */ 17988 /* ... whereas this variant doesn't carry its own condition, so it 17989 has to be either unconditional or the conditional by virtue of 17990 being the last in an IT block. The upside is that there's 4 17991 more bits available for the jump offset, so it has a 16-times 17992 greater branch range than the T3 variant. */ 17993 if (INSN0(15,11) == BITS5(1,1,1,1,0) 17994 && INSN1(15,14) == BITS2(1,0) 17995 && INSN1(12,12) == 1) { 17996 if (1) { 17997 UInt bS = INSN0(10,10); 17998 UInt bJ1 = INSN1(13,13); 17999 UInt bJ2 = INSN1(11,11); 18000 UInt bI1 = 1 ^ (bJ1 ^ bS); 18001 UInt bI2 = 1 ^ (bJ2 ^ bS); 18002 Int simm25 18003 = (bS << (1 + 1 + 10 + 11 + 1)) 18004 | (bI1 << (1 + 10 + 11 + 1)) 18005 | (bI2 << (10 + 11 + 1)) 18006 | (INSN0(9,0) << (11 + 1)) 18007 | (INSN1(10,0) << 1); 18008 simm25 = (simm25 << 7) >> 7; 18009 18010 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 18011 UInt dst = simm25 + guest_R15_curr_instr_notENC + 4; 18012 18013 /* If in an IT block, must be the last insn. */ 18014 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 18015 18016 // go uncond 18017 mk_skip_over_T32_if_cond_is_false(condT); 18018 condT = IRTemp_INVALID; 18019 // now uncond 18020 18021 // branch to dst 18022 llPutIReg(15, mkU32( dst | 1 /*CPSR.T*/ )); 18023 dres.jk_StopHere = Ijk_Boring; 18024 dres.whatNext = Dis_StopHere; 18025 DIP("b.w 0x%x\n", dst); 18026 goto decode_success; 18027 } 18028 } 18029 18030 /* ------------------ TBB, TBH ------------------ */ 18031 if (INSN0(15,4) == 0xE8D && INSN1(15,5) == 0x780) { 18032 UInt rN = INSN0(3,0); 18033 UInt rM = INSN1(3,0); 18034 UInt bH = INSN1(4,4); 18035 if (bH/*ATC*/ || (rN != 13 && !isBadRegT(rM))) { 18036 /* Must be last or not-in IT block */ 18037 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 18038 /* Go uncond */ 18039 mk_skip_over_T32_if_cond_is_false(condT); 18040 condT = IRTemp_INVALID; 18041 18042 IRExpr* ea 18043 = binop(Iop_Add32, 18044 getIRegT(rN), 18045 bH ? binop(Iop_Shl32, getIRegT(rM), mkU8(1)) 18046 : getIRegT(rM)); 18047 18048 IRTemp delta = newTemp(Ity_I32); 18049 if (bH) { 18050 assign(delta, unop(Iop_16Uto32, loadLE(Ity_I16, ea))); 18051 } else { 18052 assign(delta, unop(Iop_8Uto32, loadLE(Ity_I8, ea))); 18053 } 18054 18055 llPutIReg( 18056 15, 18057 binop(Iop_Or32, 18058 binop(Iop_Add32, 18059 getIRegT(15), 18060 binop(Iop_Shl32, mkexpr(delta), mkU8(1)) 18061 ), 18062 mkU32(1) 18063 )); 18064 dres.jk_StopHere = Ijk_Boring; 18065 dres.whatNext = Dis_StopHere; 18066 DIP("tb%c [r%u, r%u%s]\n", 18067 bH ? 'h' : 'b', rN, rM, bH ? ", LSL #1" : ""); 18068 goto decode_success; 18069 } 18070 } 18071 18072 /* ------------------ UBFX ------------------ */ 18073 /* ------------------ SBFX ------------------ */ 18074 /* There's also ARM versions of same, but it doesn't seem worth the 18075 hassle to common up the handling (it's only a couple of C 18076 statements). */ 18077 if ((INSN0(15,4) == 0xF3C // UBFX 18078 || INSN0(15,4) == 0xF34) // SBFX 18079 && INSN1(15,15) == 0 && INSN1(5,5) == 0) { 18080 UInt rN = INSN0(3,0); 18081 UInt rD = INSN1(11,8); 18082 UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6); 18083 UInt wm1 = INSN1(4,0); 18084 UInt msb = lsb + wm1; 18085 if (!isBadRegT(rD) && !isBadRegT(rN) && msb <= 31) { 18086 Bool isU = INSN0(15,4) == 0xF3C; 18087 IRTemp src = newTemp(Ity_I32); 18088 IRTemp tmp = newTemp(Ity_I32); 18089 IRTemp res = newTemp(Ity_I32); 18090 UInt mask = ((1 << wm1) - 1) + (1 << wm1); 18091 vassert(msb >= 0 && msb <= 31); 18092 vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive 18093 18094 assign(src, getIRegT(rN)); 18095 assign(tmp, binop(Iop_And32, 18096 binop(Iop_Shr32, mkexpr(src), mkU8(lsb)), 18097 mkU32(mask))); 18098 assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32, 18099 binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)), 18100 mkU8(31-wm1))); 18101 18102 putIRegT(rD, mkexpr(res), condT); 18103 18104 DIP("%s r%u, r%u, #%u, #%u\n", 18105 isU ? "ubfx" : "sbfx", rD, rN, lsb, wm1 + 1); 18106 goto decode_success; 18107 } 18108 } 18109 18110 /* ------------------ UXTB ------------------ */ 18111 /* ------------------ UXTH ------------------ */ 18112 /* ------------------ SXTB ------------------ */ 18113 /* ------------------ SXTH ------------------ */ 18114 /* ----------------- UXTB16 ----------------- */ 18115 /* ----------------- SXTB16 ----------------- */ 18116 /* FIXME: this is an exact duplicate of the ARM version. They 18117 should be commoned up. */ 18118 if ((INSN0(15,0) == 0xFA5F // UXTB 18119 || INSN0(15,0) == 0xFA1F // UXTH 18120 || INSN0(15,0) == 0xFA4F // SXTB 18121 || INSN0(15,0) == 0xFA0F // SXTH 18122 || INSN0(15,0) == 0xFA3F // UXTB16 18123 || INSN0(15,0) == 0xFA2F) // SXTB16 18124 && INSN1(15,12) == BITS4(1,1,1,1) 18125 && INSN1(7,6) == BITS2(1,0)) { 18126 UInt rD = INSN1(11,8); 18127 UInt rM = INSN1(3,0); 18128 UInt rot = INSN1(5,4); 18129 if (!isBadRegT(rD) && !isBadRegT(rM)) { 18130 HChar* nm = "???"; 18131 IRTemp srcT = newTemp(Ity_I32); 18132 IRTemp rotT = newTemp(Ity_I32); 18133 IRTemp dstT = newTemp(Ity_I32); 18134 assign(srcT, getIRegT(rM)); 18135 assign(rotT, genROR32(srcT, 8 * rot)); 18136 switch (INSN0(15,0)) { 18137 case 0xFA5F: // UXTB 18138 nm = "uxtb"; 18139 assign(dstT, unop(Iop_8Uto32, 18140 unop(Iop_32to8, mkexpr(rotT)))); 18141 break; 18142 case 0xFA1F: // UXTH 18143 nm = "uxth"; 18144 assign(dstT, unop(Iop_16Uto32, 18145 unop(Iop_32to16, mkexpr(rotT)))); 18146 break; 18147 case 0xFA4F: // SXTB 18148 nm = "sxtb"; 18149 assign(dstT, unop(Iop_8Sto32, 18150 unop(Iop_32to8, mkexpr(rotT)))); 18151 break; 18152 case 0xFA0F: // SXTH 18153 nm = "sxth"; 18154 assign(dstT, unop(Iop_16Sto32, 18155 unop(Iop_32to16, mkexpr(rotT)))); 18156 break; 18157 case 0xFA3F: // UXTB16 18158 nm = "uxtb16"; 18159 assign(dstT, binop(Iop_And32, mkexpr(rotT), 18160 mkU32(0x00FF00FF))); 18161 break; 18162 case 0xFA2F: { // SXTB16 18163 nm = "sxtb16"; 18164 IRTemp lo32 = newTemp(Ity_I32); 18165 IRTemp hi32 = newTemp(Ity_I32); 18166 assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF))); 18167 assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16))); 18168 assign( 18169 dstT, 18170 binop(Iop_Or32, 18171 binop(Iop_And32, 18172 unop(Iop_8Sto32, 18173 unop(Iop_32to8, mkexpr(lo32))), 18174 mkU32(0xFFFF)), 18175 binop(Iop_Shl32, 18176 unop(Iop_8Sto32, 18177 unop(Iop_32to8, mkexpr(hi32))), 18178 mkU8(16)) 18179 )); 18180 break; 18181 } 18182 default: 18183 vassert(0); 18184 } 18185 putIRegT(rD, mkexpr(dstT), condT); 18186 DIP("%s r%u, r%u, ror #%u\n", nm, rD, rM, 8 * rot); 18187 goto decode_success; 18188 } 18189 } 18190 18191 /* -------------- MUL.W Rd, Rn, Rm -------------- */ 18192 if (INSN0(15,4) == 0xFB0 18193 && (INSN1(15,0) & 0xF0F0) == 0xF000) { 18194 UInt rN = INSN0(3,0); 18195 UInt rD = INSN1(11,8); 18196 UInt rM = INSN1(3,0); 18197 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 18198 IRTemp res = newTemp(Ity_I32); 18199 assign(res, binop(Iop_Mul32, getIRegT(rN), getIRegT(rM))); 18200 putIRegT(rD, mkexpr(res), condT); 18201 DIP("mul.w r%u, r%u, r%u\n", rD, rN, rM); 18202 goto decode_success; 18203 } 18204 } 18205 18206 /* -------------- SDIV.W Rd, Rn, Rm -------------- */ 18207 if (INSN0(15,4) == 0xFB9 18208 && (INSN1(15,0) & 0xF0F0) == 0xF0F0) { 18209 UInt rN = INSN0(3,0); 18210 UInt rD = INSN1(11,8); 18211 UInt rM = INSN1(3,0); 18212 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 18213 IRTemp res = newTemp(Ity_I32); 18214 IRTemp argL = newTemp(Ity_I32); 18215 IRTemp argR = newTemp(Ity_I32); 18216 assign(argL, getIRegT(rN)); 18217 assign(argR, getIRegT(rM)); 18218 assign(res, binop(Iop_DivS32, mkexpr(argL), mkexpr(argR))); 18219 putIRegT(rD, mkexpr(res), condT); 18220 DIP("sdiv.w r%u, r%u, r%u\n", rD, rN, rM); 18221 goto decode_success; 18222 } 18223 } 18224 18225 /* -------------- UDIV.W Rd, Rn, Rm -------------- */ 18226 if (INSN0(15,4) == 0xFBB 18227 && (INSN1(15,0) & 0xF0F0) == 0xF0F0) { 18228 UInt rN = INSN0(3,0); 18229 UInt rD = INSN1(11,8); 18230 UInt rM = INSN1(3,0); 18231 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 18232 IRTemp res = newTemp(Ity_I32); 18233 IRTemp argL = newTemp(Ity_I32); 18234 IRTemp argR = newTemp(Ity_I32); 18235 assign(argL, getIRegT(rN)); 18236 assign(argR, getIRegT(rM)); 18237 assign(res, binop(Iop_DivU32, mkexpr(argL), mkexpr(argR))); 18238 putIRegT(rD, mkexpr(res), condT); 18239 DIP("udiv.w r%u, r%u, r%u\n", rD, rN, rM); 18240 goto decode_success; 18241 } 18242 } 18243 18244 /* ------------------ {U,S}MULL ------------------ */ 18245 if ((INSN0(15,4) == 0xFB8 || INSN0(15,4) == 0xFBA) 18246 && INSN1(7,4) == BITS4(0,0,0,0)) { 18247 UInt isU = INSN0(5,5); 18248 UInt rN = INSN0(3,0); 18249 UInt rDlo = INSN1(15,12); 18250 UInt rDhi = INSN1(11,8); 18251 UInt rM = INSN1(3,0); 18252 if (!isBadRegT(rDhi) && !isBadRegT(rDlo) 18253 && !isBadRegT(rN) && !isBadRegT(rM) && rDlo != rDhi) { 18254 IRTemp res = newTemp(Ity_I64); 18255 assign(res, binop(isU ? Iop_MullU32 : Iop_MullS32, 18256 getIRegT(rN), getIRegT(rM))); 18257 putIRegT( rDhi, unop(Iop_64HIto32, mkexpr(res)), condT ); 18258 putIRegT( rDlo, unop(Iop_64to32, mkexpr(res)), condT ); 18259 DIP("%cmull r%u, r%u, r%u, r%u\n", 18260 isU ? 'u' : 's', rDlo, rDhi, rN, rM); 18261 goto decode_success; 18262 } 18263 } 18264 18265 /* ------------------ ML{A,S} ------------------ */ 18266 if (INSN0(15,4) == 0xFB0 18267 && ( INSN1(7,4) == BITS4(0,0,0,0) // MLA 18268 || INSN1(7,4) == BITS4(0,0,0,1))) { // MLS 18269 UInt rN = INSN0(3,0); 18270 UInt rA = INSN1(15,12); 18271 UInt rD = INSN1(11,8); 18272 UInt rM = INSN1(3,0); 18273 if (!isBadRegT(rD) && !isBadRegT(rN) 18274 && !isBadRegT(rM) && !isBadRegT(rA)) { 18275 Bool isMLA = INSN1(7,4) == BITS4(0,0,0,0); 18276 IRTemp res = newTemp(Ity_I32); 18277 assign(res, 18278 binop(isMLA ? Iop_Add32 : Iop_Sub32, 18279 getIRegT(rA), 18280 binop(Iop_Mul32, getIRegT(rN), getIRegT(rM)))); 18281 putIRegT(rD, mkexpr(res), condT); 18282 DIP("%s r%u, r%u, r%u, r%u\n", 18283 isMLA ? "mla" : "mls", rD, rN, rM, rA); 18284 goto decode_success; 18285 } 18286 } 18287 18288 /* ------------------ (T3) ADR ------------------ */ 18289 if ((INSN0(15,0) == 0xF20F || INSN0(15,0) == 0xF60F) 18290 && INSN1(15,15) == 0) { 18291 /* rD = align4(PC) + imm32 */ 18292 UInt rD = INSN1(11,8); 18293 if (!isBadRegT(rD)) { 18294 UInt imm32 = (INSN0(10,10) << 11) 18295 | (INSN1(14,12) << 8) | INSN1(7,0); 18296 putIRegT(rD, binop(Iop_Add32, 18297 binop(Iop_And32, getIRegT(15), mkU32(~3U)), 18298 mkU32(imm32)), 18299 condT); 18300 DIP("add r%u, pc, #%u\n", rD, imm32); 18301 goto decode_success; 18302 } 18303 } 18304 18305 /* ----------------- (T1) UMLAL ----------------- */ 18306 /* ----------------- (T1) SMLAL ----------------- */ 18307 if ((INSN0(15,4) == 0xFBE // UMLAL 18308 || INSN0(15,4) == 0xFBC) // SMLAL 18309 && INSN1(7,4) == BITS4(0,0,0,0)) { 18310 UInt rN = INSN0(3,0); 18311 UInt rDlo = INSN1(15,12); 18312 UInt rDhi = INSN1(11,8); 18313 UInt rM = INSN1(3,0); 18314 if (!isBadRegT(rDlo) && !isBadRegT(rDhi) && !isBadRegT(rN) 18315 && !isBadRegT(rM) && rDhi != rDlo) { 18316 Bool isS = INSN0(15,4) == 0xFBC; 18317 IRTemp argL = newTemp(Ity_I32); 18318 IRTemp argR = newTemp(Ity_I32); 18319 IRTemp old = newTemp(Ity_I64); 18320 IRTemp res = newTemp(Ity_I64); 18321 IRTemp resHi = newTemp(Ity_I32); 18322 IRTemp resLo = newTemp(Ity_I32); 18323 IROp mulOp = isS ? Iop_MullS32 : Iop_MullU32; 18324 assign( argL, getIRegT(rM)); 18325 assign( argR, getIRegT(rN)); 18326 assign( old, binop(Iop_32HLto64, getIRegT(rDhi), getIRegT(rDlo)) ); 18327 assign( res, binop(Iop_Add64, 18328 mkexpr(old), 18329 binop(mulOp, mkexpr(argL), mkexpr(argR))) ); 18330 assign( resHi, unop(Iop_64HIto32, mkexpr(res)) ); 18331 assign( resLo, unop(Iop_64to32, mkexpr(res)) ); 18332 putIRegT( rDhi, mkexpr(resHi), condT ); 18333 putIRegT( rDlo, mkexpr(resLo), condT ); 18334 DIP("%cmlal r%u, r%u, r%u, r%u\n", 18335 isS ? 's' : 'u', rDlo, rDhi, rN, rM); 18336 goto decode_success; 18337 } 18338 } 18339 18340 /* ------------------ (T2) ADR ------------------ */ 18341 if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF) 18342 && INSN1(15,15) == 0) { 18343 /* rD = align4(PC) - imm32 */ 18344 UInt rD = INSN1(11,8); 18345 if (!isBadRegT(rD)) { 18346 UInt imm32 = (INSN0(10,10) << 11) 18347 | (INSN1(14,12) << 8) | INSN1(7,0); 18348 putIRegT(rD, binop(Iop_Sub32, 18349 binop(Iop_And32, getIRegT(15), mkU32(~3U)), 18350 mkU32(imm32)), 18351 condT); 18352 DIP("sub r%u, pc, #%u\n", rD, imm32); 18353 goto decode_success; 18354 } 18355 } 18356 18357 /* ------------------- (T1) BFI ------------------- */ 18358 /* ------------------- (T1) BFC ------------------- */ 18359 if (INSN0(15,4) == 0xF36 && INSN1(15,15) == 0 && INSN1(5,5) == 0) { 18360 UInt rD = INSN1(11,8); 18361 UInt rN = INSN0(3,0); 18362 UInt msb = INSN1(4,0); 18363 UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6); 18364 if (isBadRegT(rD) || rN == 13 || msb < lsb) { 18365 /* undecodable; fall through */ 18366 } else { 18367 IRTemp src = newTemp(Ity_I32); 18368 IRTemp olddst = newTemp(Ity_I32); 18369 IRTemp newdst = newTemp(Ity_I32); 18370 UInt mask = 1 << (msb - lsb); 18371 mask = (mask - 1) + mask; 18372 vassert(mask != 0); // guaranteed by "msb < lsb" check above 18373 mask <<= lsb; 18374 18375 assign(src, rN == 15 ? mkU32(0) : getIRegT(rN)); 18376 assign(olddst, getIRegT(rD)); 18377 assign(newdst, 18378 binop(Iop_Or32, 18379 binop(Iop_And32, 18380 binop(Iop_Shl32, mkexpr(src), mkU8(lsb)), 18381 mkU32(mask)), 18382 binop(Iop_And32, 18383 mkexpr(olddst), 18384 mkU32(~mask))) 18385 ); 18386 18387 putIRegT(rD, mkexpr(newdst), condT); 18388 18389 if (rN == 15) { 18390 DIP("bfc r%u, #%u, #%u\n", 18391 rD, lsb, msb-lsb+1); 18392 } else { 18393 DIP("bfi r%u, r%u, #%u, #%u\n", 18394 rD, rN, lsb, msb-lsb+1); 18395 } 18396 goto decode_success; 18397 } 18398 } 18399 18400 /* ------------------- (T1) SXTAH ------------------- */ 18401 /* ------------------- (T1) UXTAH ------------------- */ 18402 if ((INSN0(15,4) == 0xFA1 // UXTAH 18403 || INSN0(15,4) == 0xFA0) // SXTAH 18404 && INSN1(15,12) == BITS4(1,1,1,1) 18405 && INSN1(7,6) == BITS2(1,0)) { 18406 Bool isU = INSN0(15,4) == 0xFA1; 18407 UInt rN = INSN0(3,0); 18408 UInt rD = INSN1(11,8); 18409 UInt rM = INSN1(3,0); 18410 UInt rot = INSN1(5,4); 18411 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 18412 IRTemp srcL = newTemp(Ity_I32); 18413 IRTemp srcR = newTemp(Ity_I32); 18414 IRTemp res = newTemp(Ity_I32); 18415 assign(srcR, getIRegT(rM)); 18416 assign(srcL, getIRegT(rN)); 18417 assign(res, binop(Iop_Add32, 18418 mkexpr(srcL), 18419 unop(isU ? Iop_16Uto32 : Iop_16Sto32, 18420 unop(Iop_32to16, 18421 genROR32(srcR, 8 * rot))))); 18422 putIRegT(rD, mkexpr(res), condT); 18423 DIP("%cxtah r%u, r%u, r%u, ror #%u\n", 18424 isU ? 'u' : 's', rD, rN, rM, rot); 18425 goto decode_success; 18426 } 18427 } 18428 18429 /* ------------------- (T1) SXTAB ------------------- */ 18430 /* ------------------- (T1) UXTAB ------------------- */ 18431 if ((INSN0(15,4) == 0xFA5 // UXTAB 18432 || INSN0(15,4) == 0xFA4) // SXTAB 18433 && INSN1(15,12) == BITS4(1,1,1,1) 18434 && INSN1(7,6) == BITS2(1,0)) { 18435 Bool isU = INSN0(15,4) == 0xFA5; 18436 UInt rN = INSN0(3,0); 18437 UInt rD = INSN1(11,8); 18438 UInt rM = INSN1(3,0); 18439 UInt rot = INSN1(5,4); 18440 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 18441 IRTemp srcL = newTemp(Ity_I32); 18442 IRTemp srcR = newTemp(Ity_I32); 18443 IRTemp res = newTemp(Ity_I32); 18444 assign(srcR, getIRegT(rM)); 18445 assign(srcL, getIRegT(rN)); 18446 assign(res, binop(Iop_Add32, 18447 mkexpr(srcL), 18448 unop(isU ? Iop_8Uto32 : Iop_8Sto32, 18449 unop(Iop_32to8, 18450 genROR32(srcR, 8 * rot))))); 18451 putIRegT(rD, mkexpr(res), condT); 18452 DIP("%cxtab r%u, r%u, r%u, ror #%u\n", 18453 isU ? 'u' : 's', rD, rN, rM, rot); 18454 goto decode_success; 18455 } 18456 } 18457 18458 /* ------------------- (T1) CLZ ------------------- */ 18459 if (INSN0(15,4) == 0xFAB 18460 && INSN1(15,12) == BITS4(1,1,1,1) 18461 && INSN1(7,4) == BITS4(1,0,0,0)) { 18462 UInt rM1 = INSN0(3,0); 18463 UInt rD = INSN1(11,8); 18464 UInt rM2 = INSN1(3,0); 18465 if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) { 18466 IRTemp arg = newTemp(Ity_I32); 18467 IRTemp res = newTemp(Ity_I32); 18468 assign(arg, getIRegT(rM1)); 18469 assign(res, IRExpr_Mux0X( 18470 unop(Iop_1Uto8,binop(Iop_CmpEQ32, 18471 mkexpr(arg), 18472 mkU32(0))), 18473 unop(Iop_Clz32, mkexpr(arg)), 18474 mkU32(32) 18475 )); 18476 putIRegT(rD, mkexpr(res), condT); 18477 DIP("clz r%u, r%u\n", rD, rM1); 18478 goto decode_success; 18479 } 18480 } 18481 18482 /* ------------------- (T1) RBIT ------------------- */ 18483 if (INSN0(15,4) == 0xFA9 18484 && INSN1(15,12) == BITS4(1,1,1,1) 18485 && INSN1(7,4) == BITS4(1,0,1,0)) { 18486 UInt rM1 = INSN0(3,0); 18487 UInt rD = INSN1(11,8); 18488 UInt rM2 = INSN1(3,0); 18489 if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) { 18490 IRTemp arg = newTemp(Ity_I32); 18491 assign(arg, getIRegT(rM1)); 18492 IRTemp res = gen_BITREV(arg); 18493 putIRegT(rD, mkexpr(res), condT); 18494 DIP("rbit r%u, r%u\n", rD, rM1); 18495 goto decode_success; 18496 } 18497 } 18498 18499 /* ------------------- (T2) REV ------------------- */ 18500 /* ------------------- (T2) REV16 ------------------- */ 18501 if (INSN0(15,4) == 0xFA9 18502 && INSN1(15,12) == BITS4(1,1,1,1) 18503 && ( INSN1(7,4) == BITS4(1,0,0,0) // REV 18504 || INSN1(7,4) == BITS4(1,0,0,1))) { // REV16 18505 UInt rM1 = INSN0(3,0); 18506 UInt rD = INSN1(11,8); 18507 UInt rM2 = INSN1(3,0); 18508 Bool isREV = INSN1(7,4) == BITS4(1,0,0,0); 18509 if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) { 18510 IRTemp arg = newTemp(Ity_I32); 18511 assign(arg, getIRegT(rM1)); 18512 IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg); 18513 putIRegT(rD, mkexpr(res), condT); 18514 DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM1); 18515 goto decode_success; 18516 } 18517 } 18518 18519 /* -------------- (T1) MSR apsr, reg -------------- */ 18520 if (INSN0(15,4) == 0xF38 18521 && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) { 18522 UInt rN = INSN0(3,0); 18523 UInt write_ge = INSN1(10,10); 18524 UInt write_nzcvq = INSN1(11,11); 18525 if (!isBadRegT(rN) && (write_nzcvq || write_ge)) { 18526 IRTemp rNt = newTemp(Ity_I32); 18527 assign(rNt, getIRegT(rN)); 18528 desynthesise_APSR( write_nzcvq, write_ge, rNt, condT ); 18529 DIP("msr cpsr_%s%s, r%u\n", 18530 write_nzcvq ? "f" : "", write_ge ? "g" : "", rN); 18531 goto decode_success; 18532 } 18533 } 18534 18535 /* -------------- (T1) MRS reg, apsr -------------- */ 18536 if (INSN0(15,0) == 0xF3EF 18537 && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(7,0) == 0x00) { 18538 UInt rD = INSN1(11,8); 18539 if (!isBadRegT(rD)) { 18540 IRTemp apsr = synthesise_APSR(); 18541 putIRegT( rD, mkexpr(apsr), condT ); 18542 DIP("mrs r%u, cpsr\n", rD); 18543 goto decode_success; 18544 } 18545 } 18546 18547 /* ----------------- (T1) LDREX ----------------- */ 18548 if (INSN0(15,4) == 0xE85 && INSN1(11,8) == BITS4(1,1,1,1)) { 18549 UInt rN = INSN0(3,0); 18550 UInt rT = INSN1(15,12); 18551 UInt imm8 = INSN1(7,0); 18552 if (!isBadRegT(rT) && rN != 15) { 18553 IRTemp res; 18554 // go uncond 18555 mk_skip_over_T32_if_cond_is_false( condT ); 18556 // now uncond 18557 res = newTemp(Ity_I32); 18558 stmt( IRStmt_LLSC(Iend_LE, 18559 res, 18560 binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)), 18561 NULL/*this is a load*/ )); 18562 putIRegT(rT, mkexpr(res), IRTemp_INVALID); 18563 DIP("ldrex r%u, [r%u, #+%u]\n", rT, rN, imm8 * 4); 18564 goto decode_success; 18565 } 18566 } 18567 18568 /* --------------- (T1) LDREX{B,H} --------------- */ 18569 if (INSN0(15,4) == 0xE8D 18570 && (INSN1(11,0) == 0xF4F || INSN1(11,0) == 0xF5F)) { 18571 UInt rN = INSN0(3,0); 18572 UInt rT = INSN1(15,12); 18573 Bool isH = INSN1(11,0) == 0xF5F; 18574 if (!isBadRegT(rT) && rN != 15) { 18575 IRTemp res; 18576 // go uncond 18577 mk_skip_over_T32_if_cond_is_false( condT ); 18578 // now uncond 18579 res = newTemp(isH ? Ity_I16 : Ity_I8); 18580 stmt( IRStmt_LLSC(Iend_LE, res, getIRegT(rN), 18581 NULL/*this is a load*/ )); 18582 putIRegT(rT, unop(isH ? Iop_16Uto32 : Iop_8Uto32, mkexpr(res)), 18583 IRTemp_INVALID); 18584 DIP("ldrex%c r%u, [r%u]\n", isH ? 'h' : 'b', rT, rN); 18585 goto decode_success; 18586 } 18587 } 18588 18589 /* --------------- (T1) LDREXD --------------- */ 18590 if (INSN0(15,4) == 0xE8D && INSN1(7,0) == 0x7F) { 18591 UInt rN = INSN0(3,0); 18592 UInt rT = INSN1(15,12); 18593 UInt rT2 = INSN1(11,8); 18594 if (!isBadRegT(rT) && !isBadRegT(rT2) && rT != rT2 && rN != 15) { 18595 IRTemp res; 18596 // go uncond 18597 mk_skip_over_T32_if_cond_is_false( condT ); 18598 // now uncond 18599 res = newTemp(Ity_I64); 18600 // FIXME: assumes little-endian guest 18601 stmt( IRStmt_LLSC(Iend_LE, res, getIRegT(rN), 18602 NULL/*this is a load*/ )); 18603 // FIXME: assumes little-endian guest 18604 putIRegT(rT, unop(Iop_64to32, mkexpr(res)), IRTemp_INVALID); 18605 putIRegT(rT2, unop(Iop_64HIto32, mkexpr(res)), IRTemp_INVALID); 18606 DIP("ldrexd r%u, r%u, [r%u]\n", rT, rT2, rN); 18607 goto decode_success; 18608 } 18609 } 18610 18611 /* ----------------- (T1) STREX ----------------- */ 18612 if (INSN0(15,4) == 0xE84) { 18613 UInt rN = INSN0(3,0); 18614 UInt rT = INSN1(15,12); 18615 UInt rD = INSN1(11,8); 18616 UInt imm8 = INSN1(7,0); 18617 if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15 18618 && rD != rN && rD != rT) { 18619 IRTemp resSC1, resSC32; 18620 // go uncond 18621 mk_skip_over_T32_if_cond_is_false( condT ); 18622 // now uncond 18623 /* Ok, now we're unconditional. Do the store. */ 18624 resSC1 = newTemp(Ity_I1); 18625 stmt( IRStmt_LLSC(Iend_LE, 18626 resSC1, 18627 binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)), 18628 getIRegT(rT)) ); 18629 /* Set rD to 1 on failure, 0 on success. Currently we have 18630 resSC1 == 0 on failure, 1 on success. */ 18631 resSC32 = newTemp(Ity_I32); 18632 assign(resSC32, 18633 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1)))); 18634 putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID); 18635 DIP("strex r%u, r%u, [r%u, #+%u]\n", rD, rT, rN, imm8 * 4); 18636 goto decode_success; 18637 } 18638 } 18639 18640 /* --------------- (T1) STREX{B,H} --------------- */ 18641 if (INSN0(15,4) == 0xE8C 18642 && (INSN1(11,4) == 0xF4 || INSN1(11,4) == 0xF5)) { 18643 UInt rN = INSN0(3,0); 18644 UInt rT = INSN1(15,12); 18645 UInt rD = INSN1(3,0); 18646 Bool isH = INSN1(11,4) == 0xF5; 18647 if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15 18648 && rD != rN && rD != rT) { 18649 IRTemp resSC1, resSC32; 18650 // go uncond 18651 mk_skip_over_T32_if_cond_is_false( condT ); 18652 // now uncond 18653 /* Ok, now we're unconditional. Do the store. */ 18654 resSC1 = newTemp(Ity_I1); 18655 stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegT(rN), 18656 unop(isH ? Iop_32to16 : Iop_32to8, 18657 getIRegT(rT))) ); 18658 /* Set rD to 1 on failure, 0 on success. Currently we have 18659 resSC1 == 0 on failure, 1 on success. */ 18660 resSC32 = newTemp(Ity_I32); 18661 assign(resSC32, 18662 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1)))); 18663 putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID); 18664 DIP("strex%c r%u, r%u, [r%u]\n", isH ? 'h' : 'b', rD, rT, rN); 18665 goto decode_success; 18666 } 18667 } 18668 18669 /* ---------------- (T1) STREXD ---------------- */ 18670 if (INSN0(15,4) == 0xE8C && INSN1(7,4) == BITS4(0,1,1,1)) { 18671 UInt rN = INSN0(3,0); 18672 UInt rT = INSN1(15,12); 18673 UInt rT2 = INSN1(11,8); 18674 UInt rD = INSN1(3,0); 18675 if (!isBadRegT(rD) && !isBadRegT(rT) && !isBadRegT(rT2) 18676 && rN != 15 && rD != rN && rD != rT && rD != rT) { 18677 IRTemp resSC1, resSC32, data; 18678 // go uncond 18679 mk_skip_over_T32_if_cond_is_false( condT ); 18680 // now uncond 18681 /* Ok, now we're unconditional. Do the store. */ 18682 resSC1 = newTemp(Ity_I1); 18683 data = newTemp(Ity_I64); 18684 // FIXME: assumes little-endian guest 18685 assign(data, binop(Iop_32HLto64, getIRegT(rT2), getIRegT(rT))); 18686 // FIXME: assumes little-endian guest 18687 stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegT(rN), mkexpr(data))); 18688 /* Set rD to 1 on failure, 0 on success. Currently we have 18689 resSC1 == 0 on failure, 1 on success. */ 18690 resSC32 = newTemp(Ity_I32); 18691 assign(resSC32, 18692 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1)))); 18693 putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID); 18694 DIP("strexd r%u, r%u, r%u, [r%u]\n", rD, rT, rT2, rN); 18695 goto decode_success; 18696 } 18697 } 18698 /* -------------- v7 barrier insns -------------- */ 18699 if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) { 18700 /* FIXME: should this be unconditional? */ 18701 /* XXX this isn't really right, is it? The generated IR does 18702 them unconditionally. I guess it doesn't matter since it 18703 doesn't do any harm to do them even when the guarding 18704 condition is false -- it's just a performance loss. */ 18705 switch (INSN1(7,0)) { 18706 case 0x4F: /* DSB sy */ 18707 case 0x4E: /* DSB st */ 18708 case 0x4B: /* DSB ish */ 18709 case 0x4A: /* DSB ishst */ 18710 case 0x47: /* DSB nsh */ 18711 case 0x46: /* DSB nshst */ 18712 case 0x43: /* DSB osh */ 18713 case 0x42: /* DSB oshst */ 18714 stmt( IRStmt_MBE(Imbe_Fence) ); 18715 DIP("DSB\n"); 18716 goto decode_success; 18717 case 0x5F: /* DMB sy */ 18718 case 0x5E: /* DMB st */ 18719 case 0x5B: /* DMB ish */ 18720 case 0x5A: /* DMB ishst */ 18721 case 0x57: /* DMB nsh */ 18722 case 0x56: /* DMB nshst */ 18723 case 0x53: /* DMB osh */ 18724 case 0x52: /* DMB oshst */ 18725 stmt( IRStmt_MBE(Imbe_Fence) ); 18726 DIP("DMB\n"); 18727 goto decode_success; 18728 case 0x6F: /* ISB */ 18729 stmt( IRStmt_MBE(Imbe_Fence) ); 18730 DIP("ISB\n"); 18731 goto decode_success; 18732 default: 18733 break; 18734 } 18735 } 18736 18737 /* ---------------------- PLD{,W} ---------------------- */ 18738 if ((INSN0(15,4) & 0xFFD) == 0xF89 && INSN1(15,12) == 0xF) { 18739 /* FIXME: should this be unconditional? */ 18740 /* PLD/PLDW immediate, encoding T1 */ 18741 UInt rN = INSN0(3,0); 18742 UInt bW = INSN0(5,5); 18743 UInt imm12 = INSN1(11,0); 18744 DIP("pld%s [r%u, #%u]\n", bW ? "w" : "", rN, imm12); 18745 goto decode_success; 18746 } 18747 18748 if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,8) == 0xFC) { 18749 /* FIXME: should this be unconditional? */ 18750 /* PLD/PLDW immediate, encoding T2 */ 18751 UInt rN = INSN0(3,0); 18752 UInt bW = INSN0(5,5); 18753 UInt imm8 = INSN1(7,0); 18754 DIP("pld%s [r%u, #-%u]\n", bW ? "w" : "", rN, imm8); 18755 goto decode_success; 18756 } 18757 18758 if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,6) == 0x3C0) { 18759 /* FIXME: should this be unconditional? */ 18760 /* PLD/PLDW register, encoding T1 */ 18761 UInt rN = INSN0(3,0); 18762 UInt rM = INSN1(3,0); 18763 UInt bW = INSN0(5,5); 18764 UInt imm2 = INSN1(5,4); 18765 if (!isBadRegT(rM)) { 18766 DIP("pld%s [r%u, r%u, lsl %d]\n", bW ? "w" : "", rN, rM, imm2); 18767 goto decode_success; 18768 } 18769 /* fall through */ 18770 } 18771 18772 /* -------------- read CP15 TPIDRURO register ------------- */ 18773 /* mrc p15, 0, r0, c13, c0, 3 up to 18774 mrc p15, 0, r14, c13, c0, 3 18775 */ 18776 /* I don't know whether this is really v7-only. But anyway, we 18777 have to support it since arm-linux uses TPIDRURO as a thread 18778 state register. */ 18779 if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) { 18780 /* FIXME: should this be unconditional? */ 18781 UInt rD = INSN1(15,12); 18782 if (!isBadRegT(rD)) { 18783 putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), IRTemp_INVALID); 18784 DIP("mrc p15,0, r%u, c13, c0, 3\n", rD); 18785 goto decode_success; 18786 } 18787 /* fall through */ 18788 } 18789 18790 /* ------------------- CLREX ------------------ */ 18791 if (INSN0(15,0) == 0xF3BF && INSN1(15,0) == 0x8F2F) { 18792 /* AFAICS, this simply cancels a (all?) reservations made by a 18793 (any?) preceding LDREX(es). Arrange to hand it through to 18794 the back end. */ 18795 mk_skip_over_T32_if_cond_is_false( condT ); 18796 stmt( IRStmt_MBE(Imbe_CancelReservation) ); 18797 DIP("clrex\n"); 18798 goto decode_success; 18799 } 18800 18801 /* ------------------- NOP ------------------ */ 18802 if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) { 18803 DIP("nop\n"); 18804 goto decode_success; 18805 } 18806 18807 /* ------------------- (T1) SMMUL{R} ------------------ */ 18808 if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0) 18809 && INSN0(6,4) == BITS3(1,0,1) 18810 && INSN1(15,12) == BITS4(1,1,1,1) 18811 && INSN1(7,5) == BITS3(0,0,0)) { 18812 UInt bitR = INSN1(4,4); 18813 UInt rD = INSN1(11,8); 18814 UInt rM = INSN1(3,0); 18815 UInt rN = INSN0(3,0); 18816 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 18817 IRExpr* res 18818 = unop(Iop_64HIto32, 18819 binop(Iop_Add64, 18820 binop(Iop_MullS32, getIRegT(rN), getIRegT(rM)), 18821 mkU64(bitR ? 0x80000000ULL : 0ULL))); 18822 putIRegT(rD, res, condT); 18823 DIP("smmul%s r%u, r%u, r%u\n", 18824 bitR ? "r" : "", rD, rN, rM); 18825 goto decode_success; 18826 } 18827 } 18828 18829 /* ------------------- (T1) SMMLA{R} ------------------ */ 18830 if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0) 18831 && INSN0(6,4) == BITS3(1,0,1) 18832 && INSN1(7,5) == BITS3(0,0,0)) { 18833 UInt bitR = INSN1(4,4); 18834 UInt rA = INSN1(15,12); 18835 UInt rD = INSN1(11,8); 18836 UInt rM = INSN1(3,0); 18837 UInt rN = INSN0(3,0); 18838 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && (rA != 13)) { 18839 IRExpr* res 18840 = unop(Iop_64HIto32, 18841 binop(Iop_Add64, 18842 binop(Iop_Add64, 18843 binop(Iop_32HLto64, getIRegT(rA), mkU32(0)), 18844 binop(Iop_MullS32, getIRegT(rN), getIRegT(rM))), 18845 mkU64(bitR ? 0x80000000ULL : 0ULL))); 18846 putIRegT(rD, res, condT); 18847 DIP("smmla%s r%u, r%u, r%u, r%u\n", 18848 bitR ? "r" : "", rD, rN, rM, rA); 18849 goto decode_success; 18850 } 18851 } 18852 18853 /* ----------------------------------------------------------- */ 18854 /* -- VFP (CP 10, CP 11) instructions (in Thumb mode) -- */ 18855 /* ----------------------------------------------------------- */ 18856 18857 if (INSN0(15,12) == BITS4(1,1,1,0)) { 18858 UInt insn28 = (INSN0(11,0) << 16) | INSN1(15,0); 18859 Bool ok_vfp = decode_CP10_CP11_instruction ( 18860 &dres, insn28, condT, ARMCondAL/*bogus*/, 18861 True/*isT*/ 18862 ); 18863 if (ok_vfp) 18864 goto decode_success; 18865 } 18866 18867 /* ----------------------------------------------------------- */ 18868 /* -- NEON instructions (in Thumb mode) -- */ 18869 /* ----------------------------------------------------------- */ 18870 18871 if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) { 18872 UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0); 18873 Bool ok_neon = decode_NEON_instruction( 18874 &dres, insn32, condT, True/*isT*/ 18875 ); 18876 if (ok_neon) 18877 goto decode_success; 18878 } 18879 18880 /* ----------------------------------------------------------- */ 18881 /* -- v6 media instructions (in Thumb mode) -- */ 18882 /* ----------------------------------------------------------- */ 18883 18884 { UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0); 18885 Bool ok_v6m = decode_V6MEDIA_instruction( 18886 &dres, insn32, condT, ARMCondAL/*bogus*/, 18887 True/*isT*/ 18888 ); 18889 if (ok_v6m) 18890 goto decode_success; 18891 } 18892 18893 /* ----------------------------------------------------------- */ 18894 /* -- Undecodable -- */ 18895 /* ----------------------------------------------------------- */ 18896 18897 goto decode_failure; 18898 /*NOTREACHED*/ 18899 18900 decode_failure: 18901 /* All decode failures end up here. */ 18902 vex_printf("disInstr(thumb): unhandled instruction: " 18903 "0x%04x 0x%04x\n", (UInt)insn0, (UInt)insn1); 18904 18905 /* Back up ITSTATE to the initial value for this instruction. 18906 If we don't do that, any subsequent restart of the instruction 18907 will restart with the wrong value. */ 18908 if (old_itstate != IRTemp_INVALID) 18909 put_ITSTATE(old_itstate); 18910 18911 /* Tell the dispatcher that this insn cannot be decoded, and so has 18912 not been executed, and (is currently) the next to be executed. 18913 R15 should be up-to-date since it made so at the start of each 18914 insn, but nevertheless be paranoid and update it again right 18915 now. */ 18916 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 18917 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) ); 18918 dres.whatNext = Dis_StopHere; 18919 dres.jk_StopHere = Ijk_NoDecode; 18920 dres.len = 0; 18921 return dres; 18922 18923 decode_success: 18924 /* All decode successes end up here. */ 18925 vassert(dres.len == 4 || dres.len == 2 || dres.len == 20); 18926 switch (dres.whatNext) { 18927 case Dis_Continue: 18928 llPutIReg(15, mkU32(dres.len + (guest_R15_curr_instr_notENC | 1))); 18929 break; 18930 case Dis_ResteerU: 18931 case Dis_ResteerC: 18932 llPutIReg(15, mkU32(dres.continueAt)); 18933 break; 18934 case Dis_StopHere: 18935 break; 18936 default: 18937 vassert(0); 18938 } 18939 18940 DIP("\n"); 18941 18942 return dres; 18943 18944 # undef INSN0 18945 # undef INSN1 18946 } 18947 18948 #undef DIP 18949 #undef DIS 18950 18951 18952 /* Helper table for figuring out how many insns an IT insn 18953 conditionalises. 18954 18955 An ITxyz instruction of the format "1011 1111 firstcond mask" 18956 conditionalises some number of instructions, as indicated by the 18957 following table. A value of zero indicates the instruction is 18958 invalid in some way. 18959 18960 mask = 0 means this isn't an IT instruction 18961 fc = 15 (NV) means unpredictable 18962 18963 The line fc = 14 (AL) is different from the others; there are 18964 additional constraints in this case. 18965 18966 mask(0 .. 15) 18967 +-------------------------------- 18968 fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18969 .. | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18970 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18971 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18972 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18973 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18974 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18975 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18976 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18977 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18978 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18979 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18980 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18981 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18982 | 0 4 3 0 2 0 0 0 1 0 0 0 0 0 0 0 18983 15) | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18984 18985 To be conservative with the analysis, let's rule out the mask = 0 18986 case, since that isn't an IT insn at all. But for all the other 18987 cases where the table contains zero, that means unpredictable, so 18988 let's say 4 to be conservative. Hence we have a safe value for any 18989 IT (mask,fc) pair that the CPU would actually identify as an IT 18990 instruction. The final table is 18991 18992 mask(0 .. 15) 18993 +-------------------------------- 18994 fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18995 .. | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18996 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18997 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18998 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 18999 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 19000 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 19001 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 19002 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 19003 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 19004 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 19005 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 19006 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 19007 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 19008 | 0 4 3 4 2 4 4 4 1 4 4 4 4 4 4 4 19009 15) | 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 19010 */ 19011 static const UChar it_length_table[256] 19012 = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19013 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19014 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19015 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19016 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19017 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19018 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19019 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19020 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19021 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19022 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19023 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19024 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19025 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 19026 0, 4, 3, 4, 2, 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4, 19027 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 19028 }; 19029 19030 19031 /*------------------------------------------------------------*/ 19032 /*--- Top-level fn ---*/ 19033 /*------------------------------------------------------------*/ 19034 19035 /* Disassemble a single instruction into IR. The instruction 19036 is located in host memory at &guest_code[delta]. */ 19037 19038 DisResult disInstr_ARM ( IRSB* irsb_IN, 19039 Bool (*resteerOkFn) ( void*, Addr64 ), 19040 Bool resteerCisOk, 19041 void* callback_opaque, 19042 UChar* guest_code_IN, 19043 Long delta_ENCODED, 19044 Addr64 guest_IP_ENCODED, 19045 VexArch guest_arch, 19046 VexArchInfo* archinfo, 19047 VexAbiInfo* abiinfo, 19048 Bool host_bigendian_IN ) 19049 { 19050 DisResult dres; 19051 Bool isThumb = (Bool)(guest_IP_ENCODED & 1); 19052 19053 /* Set globals (see top of this file) */ 19054 vassert(guest_arch == VexArchARM); 19055 19056 irsb = irsb_IN; 19057 host_is_bigendian = host_bigendian_IN; 19058 __curr_is_Thumb = isThumb; 19059 19060 if (isThumb) { 19061 guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED - 1; 19062 } else { 19063 guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED; 19064 } 19065 19066 if (isThumb) { 19067 dres = disInstr_THUMB_WRK ( resteerOkFn, 19068 resteerCisOk, callback_opaque, 19069 &guest_code_IN[delta_ENCODED - 1], 19070 archinfo, abiinfo ); 19071 } else { 19072 dres = disInstr_ARM_WRK ( resteerOkFn, 19073 resteerCisOk, callback_opaque, 19074 &guest_code_IN[delta_ENCODED], 19075 archinfo, abiinfo ); 19076 } 19077 19078 return dres; 19079 } 19080 19081 /* Test program for the conversion of IRCmpF64Result values to VFP 19082 nzcv values. See handling of FCMPD et al above. */ 19083 /* 19084 UInt foo ( UInt x ) 19085 { 19086 UInt ix = ((x >> 5) & 3) | (x & 1); 19087 UInt termL = (((((ix ^ 1) << 30) - 1) >> 29) + 1); 19088 UInt termR = (ix & (ix >> 1) & 1); 19089 return termL - termR; 19090 } 19091 19092 void try ( char* s, UInt ir, UInt req ) 19093 { 19094 UInt act = foo(ir); 19095 printf("%s 0x%02x -> req %d%d%d%d act %d%d%d%d (0x%x)\n", 19096 s, ir, (req >> 3) & 1, (req >> 2) & 1, 19097 (req >> 1) & 1, (req >> 0) & 1, 19098 (act >> 3) & 1, (act >> 2) & 1, 19099 (act >> 1) & 1, (act >> 0) & 1, act); 19100 19101 } 19102 19103 int main ( void ) 19104 { 19105 printf("\n"); 19106 try("UN", 0x45, 0b0011); 19107 try("LT", 0x01, 0b1000); 19108 try("GT", 0x00, 0b0010); 19109 try("EQ", 0x40, 0b0110); 19110 printf("\n"); 19111 return 0; 19112 } 19113 */ 19114 19115 /*--------------------------------------------------------------------*/ 19116 /*--- end guest_arm_toIR.c ---*/ 19117 /*--------------------------------------------------------------------*/ 19118