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-2010 OpenWorks LLP 11 info (at) open-works.net 12 13 NEON support is 14 Copyright (C) 2010-2010 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 1092 bits are nonzero. However, obviously we can't assert for 1093 that. */ 1094 1095 /* So what we're constructing for the first argument is 1096 "(cond << 4) | stored-operation-operation". However, 1097 as per comments above, must be supplied pre-shifted to this 1098 function. 1099 1100 This pairing scheme requires that the ARM_CC_OP_ values all fit 1101 in 4 bits. Hence we are passing a (COND, OP) pair in the lowest 1102 8 bits of the first argument. */ 1103 IRExpr** args 1104 = mkIRExprVec_4( 1105 binop(Iop_Or32, IRExpr_Get(OFFB_CC_OP, Ity_I32), cond), 1106 IRExpr_Get(OFFB_CC_DEP1, Ity_I32), 1107 IRExpr_Get(OFFB_CC_DEP2, Ity_I32), 1108 IRExpr_Get(OFFB_CC_NDEP, Ity_I32) 1109 ); 1110 IRExpr* call 1111 = mkIRExprCCall( 1112 Ity_I32, 1113 0/*regparm*/, 1114 "armg_calculate_condition", &armg_calculate_condition, 1115 args 1116 ); 1117 1118 /* Exclude the requested condition, OP and NDEP from definedness 1119 checking. We're only interested in DEP1 and DEP2. */ 1120 call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3); 1121 return call; 1122 } 1123 1124 1125 /* Build IR to calculate some particular condition from stored 1126 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression of type 1127 Ity_I32, suitable for narrowing. Although the return type is 1128 Ity_I32, the returned value is either 0 or 1. 1129 */ 1130 static IRExpr* mk_armg_calculate_condition ( ARMCondcode cond ) 1131 { 1132 /* First arg is "(cond << 4) | condition". This requires that the 1133 ARM_CC_OP_ values all fit in 4 bits. Hence we are passing a 1134 (COND, OP) pair in the lowest 8 bits of the first argument. */ 1135 vassert(cond >= 0 && cond <= 15); 1136 return mk_armg_calculate_condition_dyn( mkU32(cond << 4) ); 1137 } 1138 1139 1140 /* Build IR to calculate just the carry flag from stored 1141 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression :: 1142 Ity_I32. */ 1143 static IRExpr* mk_armg_calculate_flag_c ( void ) 1144 { 1145 IRExpr** args 1146 = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP, Ity_I32), 1147 IRExpr_Get(OFFB_CC_DEP1, Ity_I32), 1148 IRExpr_Get(OFFB_CC_DEP2, Ity_I32), 1149 IRExpr_Get(OFFB_CC_NDEP, Ity_I32) ); 1150 IRExpr* call 1151 = mkIRExprCCall( 1152 Ity_I32, 1153 0/*regparm*/, 1154 "armg_calculate_flag_c", &armg_calculate_flag_c, 1155 args 1156 ); 1157 /* Exclude OP and NDEP from definedness checking. We're only 1158 interested in DEP1 and DEP2. */ 1159 call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3); 1160 return call; 1161 } 1162 1163 1164 /* Build IR to calculate just the overflow flag from stored 1165 CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression :: 1166 Ity_I32. */ 1167 static IRExpr* mk_armg_calculate_flag_v ( void ) 1168 { 1169 IRExpr** args 1170 = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP, Ity_I32), 1171 IRExpr_Get(OFFB_CC_DEP1, Ity_I32), 1172 IRExpr_Get(OFFB_CC_DEP2, Ity_I32), 1173 IRExpr_Get(OFFB_CC_NDEP, Ity_I32) ); 1174 IRExpr* call 1175 = mkIRExprCCall( 1176 Ity_I32, 1177 0/*regparm*/, 1178 "armg_calculate_flag_v", &armg_calculate_flag_v, 1179 args 1180 ); 1181 /* Exclude OP and NDEP from definedness checking. We're only 1182 interested in DEP1 and DEP2. */ 1183 call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3); 1184 return call; 1185 } 1186 1187 1188 /* Build IR to calculate N Z C V in bits 31:28 of the 1189 returned word. */ 1190 static IRExpr* mk_armg_calculate_flags_nzcv ( void ) 1191 { 1192 IRExpr** args 1193 = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP, Ity_I32), 1194 IRExpr_Get(OFFB_CC_DEP1, Ity_I32), 1195 IRExpr_Get(OFFB_CC_DEP2, Ity_I32), 1196 IRExpr_Get(OFFB_CC_NDEP, Ity_I32) ); 1197 IRExpr* call 1198 = mkIRExprCCall( 1199 Ity_I32, 1200 0/*regparm*/, 1201 "armg_calculate_flags_nzcv", &armg_calculate_flags_nzcv, 1202 args 1203 ); 1204 /* Exclude OP and NDEP from definedness checking. We're only 1205 interested in DEP1 and DEP2. */ 1206 call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3); 1207 return call; 1208 } 1209 1210 static IRExpr* mk_armg_calculate_flag_qc ( IRExpr* resL, IRExpr* resR, Bool Q ) 1211 { 1212 IRExpr** args1; 1213 IRExpr** args2; 1214 IRExpr *call1, *call2, *res; 1215 1216 if (Q) { 1217 args1 = mkIRExprVec_4 ( binop(Iop_GetElem32x4, resL, mkU8(0)), 1218 binop(Iop_GetElem32x4, resL, mkU8(1)), 1219 binop(Iop_GetElem32x4, resR, mkU8(0)), 1220 binop(Iop_GetElem32x4, resR, mkU8(1)) ); 1221 args2 = mkIRExprVec_4 ( binop(Iop_GetElem32x4, resL, mkU8(2)), 1222 binop(Iop_GetElem32x4, resL, mkU8(3)), 1223 binop(Iop_GetElem32x4, resR, mkU8(2)), 1224 binop(Iop_GetElem32x4, resR, mkU8(3)) ); 1225 } else { 1226 args1 = mkIRExprVec_4 ( binop(Iop_GetElem32x2, resL, mkU8(0)), 1227 binop(Iop_GetElem32x2, resL, mkU8(1)), 1228 binop(Iop_GetElem32x2, resR, mkU8(0)), 1229 binop(Iop_GetElem32x2, resR, mkU8(1)) ); 1230 } 1231 1232 #if 1 1233 call1 = mkIRExprCCall( 1234 Ity_I32, 1235 0/*regparm*/, 1236 "armg_calculate_flag_qc", &armg_calculate_flag_qc, 1237 args1 1238 ); 1239 if (Q) { 1240 call2 = mkIRExprCCall( 1241 Ity_I32, 1242 0/*regparm*/, 1243 "armg_calculate_flag_qc", &armg_calculate_flag_qc, 1244 args2 1245 ); 1246 } 1247 if (Q) { 1248 res = binop(Iop_Or32, call1, call2); 1249 } else { 1250 res = call1; 1251 } 1252 #else 1253 if (Q) { 1254 res = unop(Iop_1Uto32, 1255 binop(Iop_CmpNE32, 1256 binop(Iop_Or32, 1257 binop(Iop_Or32, 1258 binop(Iop_Xor32, 1259 args1[0], 1260 args1[2]), 1261 binop(Iop_Xor32, 1262 args1[1], 1263 args1[3])), 1264 binop(Iop_Or32, 1265 binop(Iop_Xor32, 1266 args2[0], 1267 args2[2]), 1268 binop(Iop_Xor32, 1269 args2[1], 1270 args2[3]))), 1271 mkU32(0))); 1272 } else { 1273 res = unop(Iop_1Uto32, 1274 binop(Iop_CmpNE32, 1275 binop(Iop_Or32, 1276 binop(Iop_Xor32, 1277 args1[0], 1278 args1[2]), 1279 binop(Iop_Xor32, 1280 args1[1], 1281 args1[3])), 1282 mkU32(0))); 1283 } 1284 #endif 1285 return res; 1286 } 1287 1288 // FIXME: this is named wrongly .. looks like a sticky set of 1289 // QC, not a write to it. 1290 static void setFlag_QC ( IRExpr* resL, IRExpr* resR, Bool Q, 1291 IRTemp condT ) 1292 { 1293 putMiscReg32 (OFFB_FPSCR, 1294 binop(Iop_Or32, 1295 IRExpr_Get(OFFB_FPSCR, Ity_I32), 1296 binop(Iop_Shl32, 1297 mk_armg_calculate_flag_qc(resL, resR, Q), 1298 mkU8(27))), 1299 condT); 1300 } 1301 1302 /* Build IR to conditionally set the flags thunk. As with putIReg, if 1303 guard is IRTemp_INVALID then it's unconditional, else it holds a 1304 condition :: Ity_I32. */ 1305 static 1306 void setFlags_D1_D2_ND ( UInt cc_op, IRTemp t_dep1, 1307 IRTemp t_dep2, IRTemp t_ndep, 1308 IRTemp guardT /* :: Ity_I32, 0 or 1 */ ) 1309 { 1310 IRTemp c8; 1311 vassert(typeOfIRTemp(irsb->tyenv, t_dep1 == Ity_I32)); 1312 vassert(typeOfIRTemp(irsb->tyenv, t_dep2 == Ity_I32)); 1313 vassert(typeOfIRTemp(irsb->tyenv, t_ndep == Ity_I32)); 1314 vassert(cc_op >= ARMG_CC_OP_COPY && cc_op < ARMG_CC_OP_NUMBER); 1315 if (guardT == IRTemp_INVALID) { 1316 /* unconditional */ 1317 stmt( IRStmt_Put( OFFB_CC_OP, mkU32(cc_op) )); 1318 stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(t_dep1) )); 1319 stmt( IRStmt_Put( OFFB_CC_DEP2, mkexpr(t_dep2) )); 1320 stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(t_ndep) )); 1321 } else { 1322 /* conditional */ 1323 c8 = newTemp(Ity_I8); 1324 assign( c8, unop(Iop_32to8, mkexpr(guardT)) ); 1325 stmt( IRStmt_Put( 1326 OFFB_CC_OP, 1327 IRExpr_Mux0X( mkexpr(c8), 1328 IRExpr_Get(OFFB_CC_OP, Ity_I32), 1329 mkU32(cc_op) ))); 1330 stmt( IRStmt_Put( 1331 OFFB_CC_DEP1, 1332 IRExpr_Mux0X( mkexpr(c8), 1333 IRExpr_Get(OFFB_CC_DEP1, Ity_I32), 1334 mkexpr(t_dep1) ))); 1335 stmt( IRStmt_Put( 1336 OFFB_CC_DEP2, 1337 IRExpr_Mux0X( mkexpr(c8), 1338 IRExpr_Get(OFFB_CC_DEP2, Ity_I32), 1339 mkexpr(t_dep2) ))); 1340 stmt( IRStmt_Put( 1341 OFFB_CC_NDEP, 1342 IRExpr_Mux0X( mkexpr(c8), 1343 IRExpr_Get(OFFB_CC_NDEP, Ity_I32), 1344 mkexpr(t_ndep) ))); 1345 } 1346 } 1347 1348 1349 /* Minor variant of the above that sets NDEP to zero (if it 1350 sets it at all) */ 1351 static void setFlags_D1_D2 ( UInt cc_op, IRTemp t_dep1, 1352 IRTemp t_dep2, 1353 IRTemp guardT /* :: Ity_I32, 0 or 1 */ ) 1354 { 1355 IRTemp z32 = newTemp(Ity_I32); 1356 assign( z32, mkU32(0) ); 1357 setFlags_D1_D2_ND( cc_op, t_dep1, t_dep2, z32, guardT ); 1358 } 1359 1360 1361 /* Minor variant of the above that sets DEP2 to zero (if it 1362 sets it at all) */ 1363 static void setFlags_D1_ND ( UInt cc_op, IRTemp t_dep1, 1364 IRTemp t_ndep, 1365 IRTemp guardT /* :: Ity_I32, 0 or 1 */ ) 1366 { 1367 IRTemp z32 = newTemp(Ity_I32); 1368 assign( z32, mkU32(0) ); 1369 setFlags_D1_D2_ND( cc_op, t_dep1, z32, t_ndep, guardT ); 1370 } 1371 1372 1373 /* Minor variant of the above that sets DEP2 and NDEP to zero (if it 1374 sets them at all) */ 1375 static void setFlags_D1 ( UInt cc_op, IRTemp t_dep1, 1376 IRTemp guardT /* :: Ity_I32, 0 or 1 */ ) 1377 { 1378 IRTemp z32 = newTemp(Ity_I32); 1379 assign( z32, mkU32(0) ); 1380 setFlags_D1_D2_ND( cc_op, t_dep1, z32, z32, guardT ); 1381 } 1382 1383 1384 /* ARM only */ 1385 /* Generate a side-exit to the next instruction, if the given guard 1386 expression :: Ity_I32 is 0 (note! the side exit is taken if the 1387 condition is false!) This is used to skip over conditional 1388 instructions which we can't generate straight-line code for, either 1389 because they are too complex or (more likely) they potentially 1390 generate exceptions. 1391 */ 1392 static void mk_skip_over_A32_if_cond_is_false ( 1393 IRTemp guardT /* :: Ity_I32, 0 or 1 */ 1394 ) 1395 { 1396 ASSERT_IS_ARM; 1397 vassert(guardT != IRTemp_INVALID); 1398 vassert(0 == (guest_R15_curr_instr_notENC & 3)); 1399 stmt( IRStmt_Exit( 1400 unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))), 1401 Ijk_Boring, 1402 IRConst_U32(toUInt(guest_R15_curr_instr_notENC + 4)) 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 )); 1420 } 1421 1422 1423 /* Thumb32 only */ 1424 /* ditto, but jump over a 32-bit thumb insn */ 1425 static void mk_skip_over_T32_if_cond_is_false ( 1426 IRTemp guardT /* :: Ity_I32, 0 or 1 */ 1427 ) 1428 { 1429 ASSERT_IS_THUMB; 1430 vassert(guardT != IRTemp_INVALID); 1431 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 1432 stmt( IRStmt_Exit( 1433 unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))), 1434 Ijk_Boring, 1435 IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 4) | 1)) 1436 )); 1437 } 1438 1439 1440 /* Thumb16 and Thumb32 only 1441 Generate a SIGILL followed by a restart of the current instruction 1442 if the given temp is nonzero. */ 1443 static void gen_SIGILL_T_if_nonzero ( IRTemp t /* :: Ity_I32 */ ) 1444 { 1445 ASSERT_IS_THUMB; 1446 vassert(t != IRTemp_INVALID); 1447 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 1448 stmt( 1449 IRStmt_Exit( 1450 binop(Iop_CmpNE32, mkexpr(t), mkU32(0)), 1451 Ijk_NoDecode, 1452 IRConst_U32(toUInt(guest_R15_curr_instr_notENC | 1)) 1453 ) 1454 ); 1455 } 1456 1457 1458 /* Inspect the old_itstate, and generate a SIGILL if it indicates that 1459 we are currently in an IT block and are not the last in the block. 1460 This also rolls back guest_ITSTATE to its old value before the exit 1461 and restores it to its new value afterwards. This is so that if 1462 the exit is taken, we have an up to date version of ITSTATE 1463 available. Without doing that, we have no hope of making precise 1464 exceptions work. */ 1465 static void gen_SIGILL_T_if_in_but_NLI_ITBlock ( 1466 IRTemp old_itstate /* :: Ity_I32 */, 1467 IRTemp new_itstate /* :: Ity_I32 */ 1468 ) 1469 { 1470 ASSERT_IS_THUMB; 1471 put_ITSTATE(old_itstate); // backout 1472 IRTemp guards_for_next3 = newTemp(Ity_I32); 1473 assign(guards_for_next3, 1474 binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8))); 1475 gen_SIGILL_T_if_nonzero(guards_for_next3); 1476 put_ITSTATE(new_itstate); //restore 1477 } 1478 1479 1480 /* Simpler version of the above, which generates a SIGILL if 1481 we're anywhere within an IT block. */ 1482 static void gen_SIGILL_T_if_in_ITBlock ( 1483 IRTemp old_itstate /* :: Ity_I32 */, 1484 IRTemp new_itstate /* :: Ity_I32 */ 1485 ) 1486 { 1487 put_ITSTATE(old_itstate); // backout 1488 gen_SIGILL_T_if_nonzero(old_itstate); 1489 put_ITSTATE(new_itstate); //restore 1490 } 1491 1492 1493 /* Generate an APSR value, from the NZCV thunk, and 1494 from QFLAG32 and GEFLAG0 .. GEFLAG3. */ 1495 static IRTemp synthesise_APSR ( void ) 1496 { 1497 IRTemp res1 = newTemp(Ity_I32); 1498 // Get NZCV 1499 assign( res1, mk_armg_calculate_flags_nzcv() ); 1500 // OR in the Q value 1501 IRTemp res2 = newTemp(Ity_I32); 1502 assign( 1503 res2, 1504 binop(Iop_Or32, 1505 mkexpr(res1), 1506 binop(Iop_Shl32, 1507 unop(Iop_1Uto32, 1508 binop(Iop_CmpNE32, 1509 mkexpr(get_QFLAG32()), 1510 mkU32(0))), 1511 mkU8(ARMG_CC_SHIFT_Q))) 1512 ); 1513 // OR in GE0 .. GE3 1514 IRExpr* ge0 1515 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(0), mkU32(0))); 1516 IRExpr* ge1 1517 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(1), mkU32(0))); 1518 IRExpr* ge2 1519 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(2), mkU32(0))); 1520 IRExpr* ge3 1521 = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(3), mkU32(0))); 1522 IRTemp res3 = newTemp(Ity_I32); 1523 assign(res3, 1524 binop(Iop_Or32, 1525 mkexpr(res2), 1526 binop(Iop_Or32, 1527 binop(Iop_Or32, 1528 binop(Iop_Shl32, ge0, mkU8(16)), 1529 binop(Iop_Shl32, ge1, mkU8(17))), 1530 binop(Iop_Or32, 1531 binop(Iop_Shl32, ge2, mkU8(18)), 1532 binop(Iop_Shl32, ge3, mkU8(19))) ))); 1533 return res3; 1534 } 1535 1536 1537 /* and the inverse transformation: given an APSR value, 1538 set the NZCV thunk, the Q flag, and the GE flags. */ 1539 static void desynthesise_APSR ( Bool write_nzcvq, Bool write_ge, 1540 IRTemp apsrT, IRTemp condT ) 1541 { 1542 vassert(write_nzcvq || write_ge); 1543 if (write_nzcvq) { 1544 // Do NZCV 1545 IRTemp immT = newTemp(Ity_I32); 1546 assign(immT, binop(Iop_And32, mkexpr(apsrT), mkU32(0xF0000000)) ); 1547 setFlags_D1(ARMG_CC_OP_COPY, immT, condT); 1548 // Do Q 1549 IRTemp qnewT = newTemp(Ity_I32); 1550 assign(qnewT, binop(Iop_And32, mkexpr(apsrT), mkU32(ARMG_CC_MASK_Q))); 1551 put_QFLAG32(qnewT, condT); 1552 } 1553 if (write_ge) { 1554 // Do GE3..0 1555 put_GEFLAG32(0, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<16)), 1556 condT); 1557 put_GEFLAG32(1, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<17)), 1558 condT); 1559 put_GEFLAG32(2, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<18)), 1560 condT); 1561 put_GEFLAG32(3, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<19)), 1562 condT); 1563 } 1564 } 1565 1566 1567 /*------------------------------------------------------------*/ 1568 /*--- Helpers for saturation ---*/ 1569 /*------------------------------------------------------------*/ 1570 1571 /* FIXME: absolutely the only diff. between (a) armUnsignedSatQ and 1572 (b) armSignedSatQ is that in (a) the floor is set to 0, whereas in 1573 (b) the floor is computed from the value of imm5. these two fnsn 1574 should be commoned up. */ 1575 1576 /* UnsignedSatQ(): 'clamp' each value so it lies between 0 <= x <= (2^N)-1 1577 Optionally return flag resQ saying whether saturation occurred. 1578 See definition in manual, section A2.2.1, page 41 1579 (bits(N), boolean) UnsignedSatQ( integer i, integer N ) 1580 { 1581 if ( i > (2^N)-1 ) { result = (2^N)-1; saturated = TRUE; } 1582 elsif ( i < 0 ) { result = 0; saturated = TRUE; } 1583 else { result = i; saturated = FALSE; } 1584 return ( result<N-1:0>, saturated ); 1585 } 1586 */ 1587 static void armUnsignedSatQ( IRTemp* res, /* OUT - Ity_I32 */ 1588 IRTemp* resQ, /* OUT - Ity_I32 */ 1589 IRTemp regT, /* value to clamp - Ity_I32 */ 1590 UInt imm5 ) /* saturation ceiling */ 1591 { 1592 UInt ceil = (1 << imm5) - 1; // (2^imm5)-1 1593 UInt floor = 0; 1594 1595 IRTemp node0 = newTemp(Ity_I32); 1596 IRTemp node1 = newTemp(Ity_I32); 1597 IRTemp node2 = newTemp(Ity_I1); 1598 IRTemp node3 = newTemp(Ity_I32); 1599 IRTemp node4 = newTemp(Ity_I32); 1600 IRTemp node5 = newTemp(Ity_I1); 1601 IRTemp node6 = newTemp(Ity_I32); 1602 1603 assign( node0, mkexpr(regT) ); 1604 assign( node1, mkU32(ceil) ); 1605 assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) ); 1606 assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)), 1607 mkexpr(node0), 1608 mkexpr(node1) ) ); 1609 assign( node4, mkU32(floor) ); 1610 assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) ); 1611 assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)), 1612 mkexpr(node3), 1613 mkexpr(node4) ) ); 1614 assign( *res, mkexpr(node6) ); 1615 1616 /* if saturation occurred, then resQ is set to some nonzero value 1617 if sat did not occur, resQ is guaranteed to be zero. */ 1618 if (resQ) { 1619 assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) ); 1620 } 1621 } 1622 1623 1624 /* SignedSatQ(): 'clamp' each value so it lies between -2^N <= x <= (2^N) - 1 1625 Optionally return flag resQ saying whether saturation occurred. 1626 - see definition in manual, section A2.2.1, page 41 1627 (bits(N), boolean ) SignedSatQ( integer i, integer N ) 1628 { 1629 if ( i > 2^(N-1) - 1 ) { result = 2^(N-1) - 1; saturated = TRUE; } 1630 elsif ( i < -(2^(N-1)) ) { result = -(2^(N-1)); saturated = FALSE; } 1631 else { result = i; saturated = FALSE; } 1632 return ( result[N-1:0], saturated ); 1633 } 1634 */ 1635 static void armSignedSatQ( IRTemp regT, /* value to clamp - Ity_I32 */ 1636 UInt imm5, /* saturation ceiling */ 1637 IRTemp* res, /* OUT - Ity_I32 */ 1638 IRTemp* resQ ) /* OUT - Ity_I32 */ 1639 { 1640 Int ceil = (1 << (imm5-1)) - 1; // (2^(imm5-1))-1 1641 Int floor = -(1 << (imm5-1)); // -(2^(imm5-1)) 1642 1643 IRTemp node0 = newTemp(Ity_I32); 1644 IRTemp node1 = newTemp(Ity_I32); 1645 IRTemp node2 = newTemp(Ity_I1); 1646 IRTemp node3 = newTemp(Ity_I32); 1647 IRTemp node4 = newTemp(Ity_I32); 1648 IRTemp node5 = newTemp(Ity_I1); 1649 IRTemp node6 = newTemp(Ity_I32); 1650 1651 assign( node0, mkexpr(regT) ); 1652 assign( node1, mkU32(ceil) ); 1653 assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) ); 1654 assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)), 1655 mkexpr(node0), mkexpr(node1) ) ); 1656 assign( node4, mkU32(floor) ); 1657 assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) ); 1658 assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)), 1659 mkexpr(node3), mkexpr(node4) ) ); 1660 assign( *res, mkexpr(node6) ); 1661 1662 /* if saturation occurred, then resQ is set to some nonzero value 1663 if sat did not occur, resQ is guaranteed to be zero. */ 1664 if (resQ) { 1665 assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) ); 1666 } 1667 } 1668 1669 1670 /* Compute a value 0 :: I32 or 1 :: I32, indicating whether signed 1671 overflow occurred for 32-bit addition. Needs both args and the 1672 result. HD p27. */ 1673 static 1674 IRExpr* signed_overflow_after_Add32 ( IRExpr* resE, 1675 IRTemp argL, IRTemp argR ) 1676 { 1677 IRTemp res = newTemp(Ity_I32); 1678 assign(res, resE); 1679 return 1680 binop( Iop_Shr32, 1681 binop( Iop_And32, 1682 binop( Iop_Xor32, mkexpr(res), mkexpr(argL) ), 1683 binop( Iop_Xor32, mkexpr(res), mkexpr(argR) )), 1684 mkU8(31) ); 1685 } 1686 1687 1688 /*------------------------------------------------------------*/ 1689 /*--- Larger helpers ---*/ 1690 /*------------------------------------------------------------*/ 1691 1692 /* Compute both the result and new C flag value for a LSL by an imm5 1693 or by a register operand. May generate reads of the old C value 1694 (hence only safe to use before any writes to guest state happen). 1695 Are factored out so can be used by both ARM and Thumb. 1696 1697 Note that in compute_result_and_C_after_{LSL,LSR,ASR}_by{imm5,reg}, 1698 "res" (the result) is a.k.a. "shop", shifter operand 1699 "newC" (the new C) is a.k.a. "shco", shifter carry out 1700 1701 The calling convention for res and newC is a bit funny. They could 1702 be passed by value, but instead are passed by ref. 1703 */ 1704 1705 static void compute_result_and_C_after_LSL_by_imm5 ( 1706 /*OUT*/HChar* buf, 1707 IRTemp* res, 1708 IRTemp* newC, 1709 IRTemp rMt, UInt shift_amt, /* operands */ 1710 UInt rM /* only for debug printing */ 1711 ) 1712 { 1713 if (shift_amt == 0) { 1714 if (newC) { 1715 assign( *newC, mk_armg_calculate_flag_c() ); 1716 } 1717 assign( *res, mkexpr(rMt) ); 1718 DIS(buf, "r%u", rM); 1719 } else { 1720 vassert(shift_amt >= 1 && shift_amt <= 31); 1721 if (newC) { 1722 assign( *newC, 1723 binop(Iop_And32, 1724 binop(Iop_Shr32, mkexpr(rMt), 1725 mkU8(32 - shift_amt)), 1726 mkU32(1))); 1727 } 1728 assign( *res, 1729 binop(Iop_Shl32, mkexpr(rMt), mkU8(shift_amt)) ); 1730 DIS(buf, "r%u, LSL #%u", rM, shift_amt); 1731 } 1732 } 1733 1734 1735 static void compute_result_and_C_after_LSL_by_reg ( 1736 /*OUT*/HChar* buf, 1737 IRTemp* res, 1738 IRTemp* newC, 1739 IRTemp rMt, IRTemp rSt, /* operands */ 1740 UInt rM, UInt rS /* only for debug printing */ 1741 ) 1742 { 1743 // shift left in range 0 .. 255 1744 // amt = rS & 255 1745 // res = amt < 32 ? Rm << amt : 0 1746 // newC = amt == 0 ? oldC : 1747 // amt in 1..32 ? Rm[32-amt] : 0 1748 IRTemp amtT = newTemp(Ity_I32); 1749 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) ); 1750 if (newC) { 1751 /* mux0X(amt == 0, 1752 mux0X(amt < 32, 1753 0, 1754 Rm[(32-amt) & 31]) 1755 oldC) 1756 */ 1757 /* About the best you can do is pray that iropt is able 1758 to nuke most or all of the following junk. */ 1759 IRTemp oldC = newTemp(Ity_I32); 1760 assign(oldC, mk_armg_calculate_flag_c() ); 1761 assign( 1762 *newC, 1763 IRExpr_Mux0X( 1764 unop(Iop_1Uto8, 1765 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))), 1766 IRExpr_Mux0X( 1767 unop(Iop_1Uto8, 1768 binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))), 1769 mkU32(0), 1770 binop(Iop_Shr32, 1771 mkexpr(rMt), 1772 unop(Iop_32to8, 1773 binop(Iop_And32, 1774 binop(Iop_Sub32, 1775 mkU32(32), 1776 mkexpr(amtT)), 1777 mkU32(31) 1778 ) 1779 ) 1780 ) 1781 ), 1782 mkexpr(oldC) 1783 ) 1784 ); 1785 } 1786 // (Rm << (Rs & 31)) & (((Rs & 255) - 32) >>s 31) 1787 // Lhs of the & limits the shift to 31 bits, so as to 1788 // give known IR semantics. Rhs of the & is all 1s for 1789 // Rs <= 31 and all 0s for Rs >= 32. 1790 assign( 1791 *res, 1792 binop( 1793 Iop_And32, 1794 binop(Iop_Shl32, 1795 mkexpr(rMt), 1796 unop(Iop_32to8, 1797 binop(Iop_And32, mkexpr(rSt), mkU32(31)))), 1798 binop(Iop_Sar32, 1799 binop(Iop_Sub32, 1800 mkexpr(amtT), 1801 mkU32(32)), 1802 mkU8(31)))); 1803 DIS(buf, "r%u, LSL r%u", rM, rS); 1804 } 1805 1806 1807 static void compute_result_and_C_after_LSR_by_imm5 ( 1808 /*OUT*/HChar* buf, 1809 IRTemp* res, 1810 IRTemp* newC, 1811 IRTemp rMt, UInt shift_amt, /* operands */ 1812 UInt rM /* only for debug printing */ 1813 ) 1814 { 1815 if (shift_amt == 0) { 1816 // conceptually a 32-bit shift, however: 1817 // res = 0 1818 // newC = Rm[31] 1819 if (newC) { 1820 assign( *newC, 1821 binop(Iop_And32, 1822 binop(Iop_Shr32, mkexpr(rMt), mkU8(31)), 1823 mkU32(1))); 1824 } 1825 assign( *res, mkU32(0) ); 1826 DIS(buf, "r%u, LSR #0(a.k.a. 32)", rM); 1827 } else { 1828 // shift in range 1..31 1829 // res = Rm >>u shift_amt 1830 // newC = Rm[shift_amt - 1] 1831 vassert(shift_amt >= 1 && shift_amt <= 31); 1832 if (newC) { 1833 assign( *newC, 1834 binop(Iop_And32, 1835 binop(Iop_Shr32, mkexpr(rMt), 1836 mkU8(shift_amt - 1)), 1837 mkU32(1))); 1838 } 1839 assign( *res, 1840 binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)) ); 1841 DIS(buf, "r%u, LSR #%u", rM, shift_amt); 1842 } 1843 } 1844 1845 1846 static void compute_result_and_C_after_LSR_by_reg ( 1847 /*OUT*/HChar* buf, 1848 IRTemp* res, 1849 IRTemp* newC, 1850 IRTemp rMt, IRTemp rSt, /* operands */ 1851 UInt rM, UInt rS /* only for debug printing */ 1852 ) 1853 { 1854 // shift right in range 0 .. 255 1855 // amt = rS & 255 1856 // res = amt < 32 ? Rm >>u amt : 0 1857 // newC = amt == 0 ? oldC : 1858 // amt in 1..32 ? Rm[amt-1] : 0 1859 IRTemp amtT = newTemp(Ity_I32); 1860 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) ); 1861 if (newC) { 1862 /* mux0X(amt == 0, 1863 mux0X(amt < 32, 1864 0, 1865 Rm[(amt-1) & 31]) 1866 oldC) 1867 */ 1868 IRTemp oldC = newTemp(Ity_I32); 1869 assign(oldC, mk_armg_calculate_flag_c() ); 1870 assign( 1871 *newC, 1872 IRExpr_Mux0X( 1873 unop(Iop_1Uto8, 1874 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))), 1875 IRExpr_Mux0X( 1876 unop(Iop_1Uto8, 1877 binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))), 1878 mkU32(0), 1879 binop(Iop_Shr32, 1880 mkexpr(rMt), 1881 unop(Iop_32to8, 1882 binop(Iop_And32, 1883 binop(Iop_Sub32, 1884 mkexpr(amtT), 1885 mkU32(1)), 1886 mkU32(31) 1887 ) 1888 ) 1889 ) 1890 ), 1891 mkexpr(oldC) 1892 ) 1893 ); 1894 } 1895 // (Rm >>u (Rs & 31)) & (((Rs & 255) - 32) >>s 31) 1896 // Lhs of the & limits the shift to 31 bits, so as to 1897 // give known IR semantics. Rhs of the & is all 1s for 1898 // Rs <= 31 and all 0s for Rs >= 32. 1899 assign( 1900 *res, 1901 binop( 1902 Iop_And32, 1903 binop(Iop_Shr32, 1904 mkexpr(rMt), 1905 unop(Iop_32to8, 1906 binop(Iop_And32, mkexpr(rSt), mkU32(31)))), 1907 binop(Iop_Sar32, 1908 binop(Iop_Sub32, 1909 mkexpr(amtT), 1910 mkU32(32)), 1911 mkU8(31)))); 1912 DIS(buf, "r%u, LSR r%u", rM, rS); 1913 } 1914 1915 1916 static void compute_result_and_C_after_ASR_by_imm5 ( 1917 /*OUT*/HChar* buf, 1918 IRTemp* res, 1919 IRTemp* newC, 1920 IRTemp rMt, UInt shift_amt, /* operands */ 1921 UInt rM /* only for debug printing */ 1922 ) 1923 { 1924 if (shift_amt == 0) { 1925 // conceptually a 32-bit shift, however: 1926 // res = Rm >>s 31 1927 // newC = Rm[31] 1928 if (newC) { 1929 assign( *newC, 1930 binop(Iop_And32, 1931 binop(Iop_Shr32, mkexpr(rMt), mkU8(31)), 1932 mkU32(1))); 1933 } 1934 assign( *res, binop(Iop_Sar32, mkexpr(rMt), mkU8(31)) ); 1935 DIS(buf, "r%u, ASR #0(a.k.a. 32)", rM); 1936 } else { 1937 // shift in range 1..31 1938 // res = Rm >>s shift_amt 1939 // newC = Rm[shift_amt - 1] 1940 vassert(shift_amt >= 1 && shift_amt <= 31); 1941 if (newC) { 1942 assign( *newC, 1943 binop(Iop_And32, 1944 binop(Iop_Shr32, mkexpr(rMt), 1945 mkU8(shift_amt - 1)), 1946 mkU32(1))); 1947 } 1948 assign( *res, 1949 binop(Iop_Sar32, mkexpr(rMt), mkU8(shift_amt)) ); 1950 DIS(buf, "r%u, ASR #%u", rM, shift_amt); 1951 } 1952 } 1953 1954 1955 static void compute_result_and_C_after_ASR_by_reg ( 1956 /*OUT*/HChar* buf, 1957 IRTemp* res, 1958 IRTemp* newC, 1959 IRTemp rMt, IRTemp rSt, /* operands */ 1960 UInt rM, UInt rS /* only for debug printing */ 1961 ) 1962 { 1963 // arithmetic shift right in range 0 .. 255 1964 // amt = rS & 255 1965 // res = amt < 32 ? Rm >>s amt : Rm >>s 31 1966 // newC = amt == 0 ? oldC : 1967 // amt in 1..32 ? Rm[amt-1] : Rm[31] 1968 IRTemp amtT = newTemp(Ity_I32); 1969 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) ); 1970 if (newC) { 1971 /* mux0X(amt == 0, 1972 mux0X(amt < 32, 1973 Rm[31], 1974 Rm[(amt-1) & 31]) 1975 oldC) 1976 */ 1977 IRTemp oldC = newTemp(Ity_I32); 1978 assign(oldC, mk_armg_calculate_flag_c() ); 1979 assign( 1980 *newC, 1981 IRExpr_Mux0X( 1982 unop(Iop_1Uto8, 1983 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))), 1984 IRExpr_Mux0X( 1985 unop(Iop_1Uto8, 1986 binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))), 1987 binop(Iop_Shr32, 1988 mkexpr(rMt), 1989 mkU8(31) 1990 ), 1991 binop(Iop_Shr32, 1992 mkexpr(rMt), 1993 unop(Iop_32to8, 1994 binop(Iop_And32, 1995 binop(Iop_Sub32, 1996 mkexpr(amtT), 1997 mkU32(1)), 1998 mkU32(31) 1999 ) 2000 ) 2001 ) 2002 ), 2003 mkexpr(oldC) 2004 ) 2005 ); 2006 } 2007 // (Rm >>s (amt <u 32 ? amt : 31)) 2008 assign( 2009 *res, 2010 binop( 2011 Iop_Sar32, 2012 mkexpr(rMt), 2013 unop( 2014 Iop_32to8, 2015 IRExpr_Mux0X( 2016 unop( 2017 Iop_1Uto8, 2018 binop(Iop_CmpLT32U, mkexpr(amtT), mkU32(32))), 2019 mkU32(31), 2020 mkexpr(amtT))))); 2021 DIS(buf, "r%u, ASR r%u", rM, rS); 2022 } 2023 2024 2025 static void compute_result_and_C_after_ROR_by_reg ( 2026 /*OUT*/HChar* buf, 2027 IRTemp* res, 2028 IRTemp* newC, 2029 IRTemp rMt, IRTemp rSt, /* operands */ 2030 UInt rM, UInt rS /* only for debug printing */ 2031 ) 2032 { 2033 // rotate right in range 0 .. 255 2034 // amt = rS & 255 2035 // shop = Rm `ror` (amt & 31) 2036 // shco = amt == 0 ? oldC : Rm[(amt-1) & 31] 2037 IRTemp amtT = newTemp(Ity_I32); 2038 assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) ); 2039 IRTemp amt5T = newTemp(Ity_I32); 2040 assign( amt5T, binop(Iop_And32, mkexpr(rSt), mkU32(31)) ); 2041 IRTemp oldC = newTemp(Ity_I32); 2042 assign(oldC, mk_armg_calculate_flag_c() ); 2043 if (newC) { 2044 assign( 2045 *newC, 2046 IRExpr_Mux0X( 2047 unop(Iop_32to8, mkexpr(amtT)), 2048 mkexpr(oldC), 2049 binop(Iop_And32, 2050 binop(Iop_Shr32, 2051 mkexpr(rMt), 2052 unop(Iop_32to8, 2053 binop(Iop_And32, 2054 binop(Iop_Sub32, 2055 mkexpr(amtT), 2056 mkU32(1) 2057 ), 2058 mkU32(31) 2059 ) 2060 ) 2061 ), 2062 mkU32(1) 2063 ) 2064 ) 2065 ); 2066 } 2067 assign( 2068 *res, 2069 IRExpr_Mux0X( 2070 unop(Iop_32to8, mkexpr(amt5T)), mkexpr(rMt), 2071 binop(Iop_Or32, 2072 binop(Iop_Shr32, 2073 mkexpr(rMt), 2074 unop(Iop_32to8, mkexpr(amt5T)) 2075 ), 2076 binop(Iop_Shl32, 2077 mkexpr(rMt), 2078 unop(Iop_32to8, 2079 binop(Iop_Sub32, mkU32(32), mkexpr(amt5T)) 2080 ) 2081 ) 2082 ) 2083 ) 2084 ); 2085 DIS(buf, "r%u, ROR r#%u", rM, rS); 2086 } 2087 2088 2089 /* Generate an expression corresponding to the immediate-shift case of 2090 a shifter operand. This is used both for ARM and Thumb2. 2091 2092 Bind it to a temporary, and return that via *res. If newC is 2093 non-NULL, also compute a value for the shifter's carry out (in the 2094 LSB of a word), bind it to a temporary, and return that via *shco. 2095 2096 Generates GETs from the guest state and is therefore not safe to 2097 use once we start doing PUTs to it, for any given instruction. 2098 2099 'how' is encoded thusly: 2100 00b LSL, 01b LSR, 10b ASR, 11b ROR 2101 Most but not all ARM and Thumb integer insns use this encoding. 2102 Be careful to ensure the right value is passed here. 2103 */ 2104 static void compute_result_and_C_after_shift_by_imm5 ( 2105 /*OUT*/HChar* buf, 2106 /*OUT*/IRTemp* res, 2107 /*OUT*/IRTemp* newC, 2108 IRTemp rMt, /* reg to shift */ 2109 UInt how, /* what kind of shift */ 2110 UInt shift_amt, /* shift amount (0..31) */ 2111 UInt rM /* only for debug printing */ 2112 ) 2113 { 2114 vassert(shift_amt < 32); 2115 vassert(how < 4); 2116 2117 switch (how) { 2118 2119 case 0: 2120 compute_result_and_C_after_LSL_by_imm5( 2121 buf, res, newC, rMt, shift_amt, rM 2122 ); 2123 break; 2124 2125 case 1: 2126 compute_result_and_C_after_LSR_by_imm5( 2127 buf, res, newC, rMt, shift_amt, rM 2128 ); 2129 break; 2130 2131 case 2: 2132 compute_result_and_C_after_ASR_by_imm5( 2133 buf, res, newC, rMt, shift_amt, rM 2134 ); 2135 break; 2136 2137 case 3: 2138 if (shift_amt == 0) { 2139 IRTemp oldcT = newTemp(Ity_I32); 2140 // rotate right 1 bit through carry (?) 2141 // RRX -- described at ARM ARM A5-17 2142 // res = (oldC << 31) | (Rm >>u 1) 2143 // newC = Rm[0] 2144 if (newC) { 2145 assign( *newC, 2146 binop(Iop_And32, mkexpr(rMt), mkU32(1))); 2147 } 2148 assign( oldcT, mk_armg_calculate_flag_c() ); 2149 assign( *res, 2150 binop(Iop_Or32, 2151 binop(Iop_Shl32, mkexpr(oldcT), mkU8(31)), 2152 binop(Iop_Shr32, mkexpr(rMt), mkU8(1))) ); 2153 DIS(buf, "r%u, RRX", rM); 2154 } else { 2155 // rotate right in range 1..31 2156 // res = Rm `ror` shift_amt 2157 // newC = Rm[shift_amt - 1] 2158 vassert(shift_amt >= 1 && shift_amt <= 31); 2159 if (newC) { 2160 assign( *newC, 2161 binop(Iop_And32, 2162 binop(Iop_Shr32, mkexpr(rMt), 2163 mkU8(shift_amt - 1)), 2164 mkU32(1))); 2165 } 2166 assign( *res, 2167 binop(Iop_Or32, 2168 binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)), 2169 binop(Iop_Shl32, mkexpr(rMt), 2170 mkU8(32-shift_amt)))); 2171 DIS(buf, "r%u, ROR #%u", rM, shift_amt); 2172 } 2173 break; 2174 2175 default: 2176 /*NOTREACHED*/ 2177 vassert(0); 2178 } 2179 } 2180 2181 2182 /* Generate an expression corresponding to the register-shift case of 2183 a shifter operand. This is used both for ARM and Thumb2. 2184 2185 Bind it to a temporary, and return that via *res. If newC is 2186 non-NULL, also compute a value for the shifter's carry out (in the 2187 LSB of a word), bind it to a temporary, and return that via *shco. 2188 2189 Generates GETs from the guest state and is therefore not safe to 2190 use once we start doing PUTs to it, for any given instruction. 2191 2192 'how' is encoded thusly: 2193 00b LSL, 01b LSR, 10b ASR, 11b ROR 2194 Most but not all ARM and Thumb integer insns use this encoding. 2195 Be careful to ensure the right value is passed here. 2196 */ 2197 static void compute_result_and_C_after_shift_by_reg ( 2198 /*OUT*/HChar* buf, 2199 /*OUT*/IRTemp* res, 2200 /*OUT*/IRTemp* newC, 2201 IRTemp rMt, /* reg to shift */ 2202 UInt how, /* what kind of shift */ 2203 IRTemp rSt, /* shift amount */ 2204 UInt rM, /* only for debug printing */ 2205 UInt rS /* only for debug printing */ 2206 ) 2207 { 2208 vassert(how < 4); 2209 switch (how) { 2210 case 0: { /* LSL */ 2211 compute_result_and_C_after_LSL_by_reg( 2212 buf, res, newC, rMt, rSt, rM, rS 2213 ); 2214 break; 2215 } 2216 case 1: { /* LSR */ 2217 compute_result_and_C_after_LSR_by_reg( 2218 buf, res, newC, rMt, rSt, rM, rS 2219 ); 2220 break; 2221 } 2222 case 2: { /* ASR */ 2223 compute_result_and_C_after_ASR_by_reg( 2224 buf, res, newC, rMt, rSt, rM, rS 2225 ); 2226 break; 2227 } 2228 case 3: { /* ROR */ 2229 compute_result_and_C_after_ROR_by_reg( 2230 buf, res, newC, rMt, rSt, rM, rS 2231 ); 2232 break; 2233 } 2234 default: 2235 /*NOTREACHED*/ 2236 vassert(0); 2237 } 2238 } 2239 2240 2241 /* Generate an expression corresponding to a shifter_operand, bind it 2242 to a temporary, and return that via *shop. If shco is non-NULL, 2243 also compute a value for the shifter's carry out (in the LSB of a 2244 word), bind it to a temporary, and return that via *shco. 2245 2246 If for some reason we can't come up with a shifter operand (missing 2247 case? not really a shifter operand?) return False. 2248 2249 Generates GETs from the guest state and is therefore not safe to 2250 use once we start doing PUTs to it, for any given instruction. 2251 2252 For ARM insns only; not for Thumb. 2253 */ 2254 static Bool mk_shifter_operand ( UInt insn_25, UInt insn_11_0, 2255 /*OUT*/IRTemp* shop, 2256 /*OUT*/IRTemp* shco, 2257 /*OUT*/HChar* buf ) 2258 { 2259 UInt insn_4 = (insn_11_0 >> 4) & 1; 2260 UInt insn_7 = (insn_11_0 >> 7) & 1; 2261 vassert(insn_25 <= 0x1); 2262 vassert(insn_11_0 <= 0xFFF); 2263 2264 vassert(shop && *shop == IRTemp_INVALID); 2265 *shop = newTemp(Ity_I32); 2266 2267 if (shco) { 2268 vassert(*shco == IRTemp_INVALID); 2269 *shco = newTemp(Ity_I32); 2270 } 2271 2272 /* 32-bit immediate */ 2273 2274 if (insn_25 == 1) { 2275 /* immediate: (7:0) rotated right by 2 * (11:8) */ 2276 UInt imm = (insn_11_0 >> 0) & 0xFF; 2277 UInt rot = 2 * ((insn_11_0 >> 8) & 0xF); 2278 vassert(rot <= 30); 2279 imm = ROR32(imm, rot); 2280 if (shco) { 2281 if (rot == 0) { 2282 assign( *shco, mk_armg_calculate_flag_c() ); 2283 } else { 2284 assign( *shco, mkU32( (imm >> 31) & 1 ) ); 2285 } 2286 } 2287 DIS(buf, "#0x%x", imm); 2288 assign( *shop, mkU32(imm) ); 2289 return True; 2290 } 2291 2292 /* Shift/rotate by immediate */ 2293 2294 if (insn_25 == 0 && insn_4 == 0) { 2295 /* Rm (3:0) shifted (6:5) by immediate (11:7) */ 2296 UInt shift_amt = (insn_11_0 >> 7) & 0x1F; 2297 UInt rM = (insn_11_0 >> 0) & 0xF; 2298 UInt how = (insn_11_0 >> 5) & 3; 2299 /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */ 2300 IRTemp rMt = newTemp(Ity_I32); 2301 assign(rMt, getIRegA(rM)); 2302 2303 vassert(shift_amt <= 31); 2304 2305 compute_result_and_C_after_shift_by_imm5( 2306 buf, shop, shco, rMt, how, shift_amt, rM 2307 ); 2308 return True; 2309 } 2310 2311 /* Shift/rotate by register */ 2312 if (insn_25 == 0 && insn_4 == 1) { 2313 /* Rm (3:0) shifted (6:5) by Rs (11:8) */ 2314 UInt rM = (insn_11_0 >> 0) & 0xF; 2315 UInt rS = (insn_11_0 >> 8) & 0xF; 2316 UInt how = (insn_11_0 >> 5) & 3; 2317 /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */ 2318 IRTemp rMt = newTemp(Ity_I32); 2319 IRTemp rSt = newTemp(Ity_I32); 2320 2321 if (insn_7 == 1) 2322 return False; /* not really a shifter operand */ 2323 2324 assign(rMt, getIRegA(rM)); 2325 assign(rSt, getIRegA(rS)); 2326 2327 compute_result_and_C_after_shift_by_reg( 2328 buf, shop, shco, rMt, how, rSt, rM, rS 2329 ); 2330 return True; 2331 } 2332 2333 vex_printf("mk_shifter_operand(0x%x,0x%x)\n", insn_25, insn_11_0 ); 2334 return False; 2335 } 2336 2337 2338 /* ARM only */ 2339 static 2340 IRExpr* mk_EA_reg_plusminus_imm12 ( UInt rN, UInt bU, UInt imm12, 2341 /*OUT*/HChar* buf ) 2342 { 2343 vassert(rN < 16); 2344 vassert(bU < 2); 2345 vassert(imm12 < 0x1000); 2346 UChar opChar = bU == 1 ? '+' : '-'; 2347 DIS(buf, "[r%u, #%c%u]", rN, opChar, imm12); 2348 return 2349 binop( (bU == 1 ? Iop_Add32 : Iop_Sub32), 2350 getIRegA(rN), 2351 mkU32(imm12) ); 2352 } 2353 2354 2355 /* ARM only. 2356 NB: This is "DecodeImmShift" in newer versions of the the ARM ARM. 2357 */ 2358 static 2359 IRExpr* mk_EA_reg_plusminus_shifted_reg ( UInt rN, UInt bU, UInt rM, 2360 UInt sh2, UInt imm5, 2361 /*OUT*/HChar* buf ) 2362 { 2363 vassert(rN < 16); 2364 vassert(bU < 2); 2365 vassert(rM < 16); 2366 vassert(sh2 < 4); 2367 vassert(imm5 < 32); 2368 UChar opChar = bU == 1 ? '+' : '-'; 2369 IRExpr* index = NULL; 2370 switch (sh2) { 2371 case 0: /* LSL */ 2372 /* imm5 can be in the range 0 .. 31 inclusive. */ 2373 index = binop(Iop_Shl32, getIRegA(rM), mkU8(imm5)); 2374 DIS(buf, "[r%u, %c r%u LSL #%u]", rN, opChar, rM, imm5); 2375 break; 2376 case 1: /* LSR */ 2377 if (imm5 == 0) { 2378 index = mkU32(0); 2379 vassert(0); // ATC 2380 } else { 2381 index = binop(Iop_Shr32, getIRegA(rM), mkU8(imm5)); 2382 } 2383 DIS(buf, "[r%u, %cr%u, LSR #%u]", 2384 rN, opChar, rM, imm5 == 0 ? 32 : imm5); 2385 break; 2386 case 2: /* ASR */ 2387 /* Doesn't this just mean that the behaviour with imm5 == 0 2388 is the same as if it had been 31 ? */ 2389 if (imm5 == 0) { 2390 index = binop(Iop_Sar32, getIRegA(rM), mkU8(31)); 2391 vassert(0); // ATC 2392 } else { 2393 index = binop(Iop_Sar32, getIRegA(rM), mkU8(imm5)); 2394 } 2395 DIS(buf, "[r%u, %cr%u, ASR #%u]", 2396 rN, opChar, rM, imm5 == 0 ? 32 : imm5); 2397 break; 2398 case 3: /* ROR or RRX */ 2399 if (imm5 == 0) { 2400 IRTemp rmT = newTemp(Ity_I32); 2401 IRTemp cflagT = newTemp(Ity_I32); 2402 assign(rmT, getIRegA(rM)); 2403 assign(cflagT, mk_armg_calculate_flag_c()); 2404 index = binop(Iop_Or32, 2405 binop(Iop_Shl32, mkexpr(cflagT), mkU8(31)), 2406 binop(Iop_Shr32, mkexpr(rmT), mkU8(1))); 2407 DIS(buf, "[r%u, %cr%u, RRX]", rN, opChar, rM); 2408 } else { 2409 IRTemp rmT = newTemp(Ity_I32); 2410 assign(rmT, getIRegA(rM)); 2411 vassert(imm5 >= 1 && imm5 <= 31); 2412 index = binop(Iop_Or32, 2413 binop(Iop_Shl32, mkexpr(rmT), mkU8(32-imm5)), 2414 binop(Iop_Shr32, mkexpr(rmT), mkU8(imm5))); 2415 DIS(buf, "[r%u, %cr%u, ROR #%u]", rN, opChar, rM, imm5); 2416 } 2417 break; 2418 default: 2419 vassert(0); 2420 } 2421 vassert(index); 2422 return binop(bU == 1 ? Iop_Add32 : Iop_Sub32, 2423 getIRegA(rN), index); 2424 } 2425 2426 2427 /* ARM only */ 2428 static 2429 IRExpr* mk_EA_reg_plusminus_imm8 ( UInt rN, UInt bU, UInt imm8, 2430 /*OUT*/HChar* buf ) 2431 { 2432 vassert(rN < 16); 2433 vassert(bU < 2); 2434 vassert(imm8 < 0x100); 2435 UChar opChar = bU == 1 ? '+' : '-'; 2436 DIS(buf, "[r%u, #%c%u]", rN, opChar, imm8); 2437 return 2438 binop( (bU == 1 ? Iop_Add32 : Iop_Sub32), 2439 getIRegA(rN), 2440 mkU32(imm8) ); 2441 } 2442 2443 2444 /* ARM only */ 2445 static 2446 IRExpr* mk_EA_reg_plusminus_reg ( UInt rN, UInt bU, UInt rM, 2447 /*OUT*/HChar* buf ) 2448 { 2449 vassert(rN < 16); 2450 vassert(bU < 2); 2451 vassert(rM < 16); 2452 UChar opChar = bU == 1 ? '+' : '-'; 2453 IRExpr* index = getIRegA(rM); 2454 DIS(buf, "[r%u, %c r%u]", rN, opChar, rM); 2455 return binop(bU == 1 ? Iop_Add32 : Iop_Sub32, 2456 getIRegA(rN), index); 2457 } 2458 2459 2460 /* irRes :: Ity_I32 holds a floating point comparison result encoded 2461 as an IRCmpF64Result. Generate code to convert it to an 2462 ARM-encoded (N,Z,C,V) group in the lowest 4 bits of an I32 value. 2463 Assign a new temp to hold that value, and return the temp. */ 2464 static 2465 IRTemp mk_convert_IRCmpF64Result_to_NZCV ( IRTemp irRes ) 2466 { 2467 IRTemp ix = newTemp(Ity_I32); 2468 IRTemp termL = newTemp(Ity_I32); 2469 IRTemp termR = newTemp(Ity_I32); 2470 IRTemp nzcv = newTemp(Ity_I32); 2471 2472 /* This is where the fun starts. We have to convert 'irRes' from 2473 an IR-convention return result (IRCmpF64Result) to an 2474 ARM-encoded (N,Z,C,V) group. The final result is in the bottom 2475 4 bits of 'nzcv'. */ 2476 /* Map compare result from IR to ARM(nzcv) */ 2477 /* 2478 FP cmp result | IR | ARM(nzcv) 2479 -------------------------------- 2480 UN 0x45 0011 2481 LT 0x01 1000 2482 GT 0x00 0010 2483 EQ 0x40 0110 2484 */ 2485 /* Now since you're probably wondering WTF .. 2486 2487 ix fishes the useful bits out of the IR value, bits 6 and 0, and 2488 places them side by side, giving a number which is 0, 1, 2 or 3. 2489 2490 termL is a sequence cooked up by GNU superopt. It converts ix 2491 into an almost correct value NZCV value (incredibly), except 2492 for the case of UN, where it produces 0100 instead of the 2493 required 0011. 2494 2495 termR is therefore a correction term, also computed from ix. It 2496 is 1 in the UN case and 0 for LT, GT and UN. Hence, to get 2497 the final correct value, we subtract termR from termL. 2498 2499 Don't take my word for it. There's a test program at the bottom 2500 of this file, to try this out with. 2501 */ 2502 assign( 2503 ix, 2504 binop(Iop_Or32, 2505 binop(Iop_And32, 2506 binop(Iop_Shr32, mkexpr(irRes), mkU8(5)), 2507 mkU32(3)), 2508 binop(Iop_And32, mkexpr(irRes), mkU32(1)))); 2509 2510 assign( 2511 termL, 2512 binop(Iop_Add32, 2513 binop(Iop_Shr32, 2514 binop(Iop_Sub32, 2515 binop(Iop_Shl32, 2516 binop(Iop_Xor32, mkexpr(ix), mkU32(1)), 2517 mkU8(30)), 2518 mkU32(1)), 2519 mkU8(29)), 2520 mkU32(1))); 2521 2522 assign( 2523 termR, 2524 binop(Iop_And32, 2525 binop(Iop_And32, 2526 mkexpr(ix), 2527 binop(Iop_Shr32, mkexpr(ix), mkU8(1))), 2528 mkU32(1))); 2529 2530 assign(nzcv, binop(Iop_Sub32, mkexpr(termL), mkexpr(termR))); 2531 return nzcv; 2532 } 2533 2534 2535 /* Thumb32 only. This is "ThumbExpandImm" in the ARM ARM. If 2536 updatesC is non-NULL, a boolean is written to it indicating whether 2537 or not the C flag is updated, as per ARM ARM "ThumbExpandImm_C". 2538 */ 2539 static UInt thumbExpandImm ( Bool* updatesC, 2540 UInt imm1, UInt imm3, UInt imm8 ) 2541 { 2542 vassert(imm1 < (1<<1)); 2543 vassert(imm3 < (1<<3)); 2544 vassert(imm8 < (1<<8)); 2545 UInt i_imm3_a = (imm1 << 4) | (imm3 << 1) | ((imm8 >> 7) & 1); 2546 UInt abcdefgh = imm8; 2547 UInt lbcdefgh = imm8 | 0x80; 2548 if (updatesC) { 2549 *updatesC = i_imm3_a >= 8; 2550 } 2551 switch (i_imm3_a) { 2552 case 0: case 1: 2553 return abcdefgh; 2554 case 2: case 3: 2555 return (abcdefgh << 16) | abcdefgh; 2556 case 4: case 5: 2557 return (abcdefgh << 24) | (abcdefgh << 8); 2558 case 6: case 7: 2559 return (abcdefgh << 24) | (abcdefgh << 16) 2560 | (abcdefgh << 8) | abcdefgh; 2561 case 8 ... 31: 2562 return lbcdefgh << (32 - i_imm3_a); 2563 default: 2564 break; 2565 } 2566 /*NOTREACHED*/vassert(0); 2567 } 2568 2569 2570 /* Version of thumbExpandImm where we simply feed it the 2571 instruction halfwords (the lowest addressed one is I0). */ 2572 static UInt thumbExpandImm_from_I0_I1 ( Bool* updatesC, 2573 UShort i0s, UShort i1s ) 2574 { 2575 UInt i0 = (UInt)i0s; 2576 UInt i1 = (UInt)i1s; 2577 UInt imm1 = SLICE_UInt(i0,10,10); 2578 UInt imm3 = SLICE_UInt(i1,14,12); 2579 UInt imm8 = SLICE_UInt(i1,7,0); 2580 return thumbExpandImm(updatesC, imm1, imm3, imm8); 2581 } 2582 2583 2584 /* Thumb16 only. Given the firstcond and mask fields from an IT 2585 instruction, compute the 32-bit ITSTATE value implied, as described 2586 in libvex_guest_arm.h. This is not the ARM ARM representation. 2587 Also produce the t/e chars for the 2nd, 3rd, 4th insns, for 2588 disassembly printing. Returns False if firstcond or mask 2589 denote something invalid. 2590 2591 The number and conditions for the instructions to be 2592 conditionalised depend on firstcond and mask: 2593 2594 mask cond 1 cond 2 cond 3 cond 4 2595 2596 1000 fc[3:0] 2597 x100 fc[3:0] fc[3:1]:x 2598 xy10 fc[3:0] fc[3:1]:x fc[3:1]:y 2599 xyz1 fc[3:0] fc[3:1]:x fc[3:1]:y fc[3:1]:z 2600 2601 The condition fields are assembled in *itstate backwards (cond 4 at 2602 the top, cond 1 at the bottom). Conditions are << 4'd and then 2603 ^0xE'd, and those fields that correspond to instructions in the IT 2604 block are tagged with a 1 bit. 2605 */ 2606 static Bool compute_ITSTATE ( /*OUT*/UInt* itstate, 2607 /*OUT*/UChar* ch1, 2608 /*OUT*/UChar* ch2, 2609 /*OUT*/UChar* ch3, 2610 UInt firstcond, UInt mask ) 2611 { 2612 vassert(firstcond <= 0xF); 2613 vassert(mask <= 0xF); 2614 *itstate = 0; 2615 *ch1 = *ch2 = *ch3 = '.'; 2616 if (mask == 0) 2617 return False; /* the logic below actually ensures this anyway, 2618 but clearer to make it explicit. */ 2619 if (firstcond == 0xF) 2620 return False; /* NV is not allowed */ 2621 if (firstcond == 0xE && popcount32(mask) != 1) 2622 return False; /* if firstcond is AL then all the rest must be too */ 2623 2624 UInt m3 = (mask >> 3) & 1; 2625 UInt m2 = (mask >> 2) & 1; 2626 UInt m1 = (mask >> 1) & 1; 2627 UInt m0 = (mask >> 0) & 1; 2628 2629 UInt fc = (firstcond << 4) | 1/*in-IT-block*/; 2630 UInt ni = (0xE/*AL*/ << 4) | 0/*not-in-IT-block*/; 2631 2632 if (m3 == 1 && (m2|m1|m0) == 0) { 2633 *itstate = (ni << 24) | (ni << 16) | (ni << 8) | fc; 2634 *itstate ^= 0xE0E0E0E0; 2635 return True; 2636 } 2637 2638 if (m2 == 1 && (m1|m0) == 0) { 2639 *itstate = (ni << 24) | (ni << 16) | (setbit32(fc, 4, m3) << 8) | fc; 2640 *itstate ^= 0xE0E0E0E0; 2641 *ch1 = m3 == (firstcond & 1) ? 't' : 'e'; 2642 return True; 2643 } 2644 2645 if (m1 == 1 && m0 == 0) { 2646 *itstate = (ni << 24) 2647 | (setbit32(fc, 4, m2) << 16) 2648 | (setbit32(fc, 4, m3) << 8) | fc; 2649 *itstate ^= 0xE0E0E0E0; 2650 *ch1 = m3 == (firstcond & 1) ? 't' : 'e'; 2651 *ch2 = m2 == (firstcond & 1) ? 't' : 'e'; 2652 return True; 2653 } 2654 2655 if (m0 == 1) { 2656 *itstate = (setbit32(fc, 4, m1) << 24) 2657 | (setbit32(fc, 4, m2) << 16) 2658 | (setbit32(fc, 4, m3) << 8) | fc; 2659 *itstate ^= 0xE0E0E0E0; 2660 *ch1 = m3 == (firstcond & 1) ? 't' : 'e'; 2661 *ch2 = m2 == (firstcond & 1) ? 't' : 'e'; 2662 *ch3 = m1 == (firstcond & 1) ? 't' : 'e'; 2663 return True; 2664 } 2665 2666 return False; 2667 } 2668 2669 2670 /* Generate IR to do 32-bit bit reversal, a la Hacker's Delight 2671 Chapter 7 Section 1. */ 2672 static IRTemp gen_BITREV ( IRTemp x0 ) 2673 { 2674 IRTemp x1 = newTemp(Ity_I32); 2675 IRTemp x2 = newTemp(Ity_I32); 2676 IRTemp x3 = newTemp(Ity_I32); 2677 IRTemp x4 = newTemp(Ity_I32); 2678 IRTemp x5 = newTemp(Ity_I32); 2679 UInt c1 = 0x55555555; 2680 UInt c2 = 0x33333333; 2681 UInt c3 = 0x0F0F0F0F; 2682 UInt c4 = 0x00FF00FF; 2683 UInt c5 = 0x0000FFFF; 2684 assign(x1, 2685 binop(Iop_Or32, 2686 binop(Iop_Shl32, 2687 binop(Iop_And32, mkexpr(x0), mkU32(c1)), 2688 mkU8(1)), 2689 binop(Iop_Shr32, 2690 binop(Iop_And32, mkexpr(x0), mkU32(~c1)), 2691 mkU8(1)) 2692 )); 2693 assign(x2, 2694 binop(Iop_Or32, 2695 binop(Iop_Shl32, 2696 binop(Iop_And32, mkexpr(x1), mkU32(c2)), 2697 mkU8(2)), 2698 binop(Iop_Shr32, 2699 binop(Iop_And32, mkexpr(x1), mkU32(~c2)), 2700 mkU8(2)) 2701 )); 2702 assign(x3, 2703 binop(Iop_Or32, 2704 binop(Iop_Shl32, 2705 binop(Iop_And32, mkexpr(x2), mkU32(c3)), 2706 mkU8(4)), 2707 binop(Iop_Shr32, 2708 binop(Iop_And32, mkexpr(x2), mkU32(~c3)), 2709 mkU8(4)) 2710 )); 2711 assign(x4, 2712 binop(Iop_Or32, 2713 binop(Iop_Shl32, 2714 binop(Iop_And32, mkexpr(x3), mkU32(c4)), 2715 mkU8(8)), 2716 binop(Iop_Shr32, 2717 binop(Iop_And32, mkexpr(x3), mkU32(~c4)), 2718 mkU8(8)) 2719 )); 2720 assign(x5, 2721 binop(Iop_Or32, 2722 binop(Iop_Shl32, 2723 binop(Iop_And32, mkexpr(x4), mkU32(c5)), 2724 mkU8(16)), 2725 binop(Iop_Shr32, 2726 binop(Iop_And32, mkexpr(x4), mkU32(~c5)), 2727 mkU8(16)) 2728 )); 2729 return x5; 2730 } 2731 2732 2733 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order 2734 0:1:2:3 (aka byte-swap). */ 2735 static IRTemp gen_REV ( IRTemp arg ) 2736 { 2737 IRTemp res = newTemp(Ity_I32); 2738 assign(res, 2739 binop(Iop_Or32, 2740 binop(Iop_Shl32, mkexpr(arg), mkU8(24)), 2741 binop(Iop_Or32, 2742 binop(Iop_And32, binop(Iop_Shl32, mkexpr(arg), mkU8(8)), 2743 mkU32(0x00FF0000)), 2744 binop(Iop_Or32, 2745 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(8)), 2746 mkU32(0x0000FF00)), 2747 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(24)), 2748 mkU32(0x000000FF) ) 2749 )))); 2750 return res; 2751 } 2752 2753 2754 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order 2755 2:3:0:1 (swap within lo and hi halves). */ 2756 static IRTemp gen_REV16 ( IRTemp arg ) 2757 { 2758 IRTemp res = newTemp(Ity_I32); 2759 assign(res, 2760 binop(Iop_Or32, 2761 binop(Iop_And32, 2762 binop(Iop_Shl32, mkexpr(arg), mkU8(8)), 2763 mkU32(0xFF00FF00)), 2764 binop(Iop_And32, 2765 binop(Iop_Shr32, mkexpr(arg), mkU8(8)), 2766 mkU32(0x00FF00FF)))); 2767 return res; 2768 } 2769 2770 2771 /*------------------------------------------------------------*/ 2772 /*--- Advanced SIMD (NEON) instructions ---*/ 2773 /*------------------------------------------------------------*/ 2774 2775 /*------------------------------------------------------------*/ 2776 /*--- NEON data processing ---*/ 2777 /*------------------------------------------------------------*/ 2778 2779 /* For all NEON DP ops, we use the normal scheme to handle conditional 2780 writes to registers -- pass in condT and hand that on to the 2781 put*Reg functions. In ARM mode condT is always IRTemp_INVALID 2782 since NEON is unconditional for ARM. In Thumb mode condT is 2783 derived from the ITSTATE shift register in the normal way. */ 2784 2785 static 2786 UInt get_neon_d_regno(UInt theInstr) 2787 { 2788 UInt x = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF); 2789 if (theInstr & 0x40) { 2790 if (x & 1) { 2791 x = x + 0x100; 2792 } else { 2793 x = x >> 1; 2794 } 2795 } 2796 return x; 2797 } 2798 2799 static 2800 UInt get_neon_n_regno(UInt theInstr) 2801 { 2802 UInt x = ((theInstr >> 3) & 0x10) | ((theInstr >> 16) & 0xF); 2803 if (theInstr & 0x40) { 2804 if (x & 1) { 2805 x = x + 0x100; 2806 } else { 2807 x = x >> 1; 2808 } 2809 } 2810 return x; 2811 } 2812 2813 static 2814 UInt get_neon_m_regno(UInt theInstr) 2815 { 2816 UInt x = ((theInstr >> 1) & 0x10) | (theInstr & 0xF); 2817 if (theInstr & 0x40) { 2818 if (x & 1) { 2819 x = x + 0x100; 2820 } else { 2821 x = x >> 1; 2822 } 2823 } 2824 return x; 2825 } 2826 2827 static 2828 Bool dis_neon_vext ( UInt theInstr, IRTemp condT ) 2829 { 2830 UInt dreg = get_neon_d_regno(theInstr); 2831 UInt mreg = get_neon_m_regno(theInstr); 2832 UInt nreg = get_neon_n_regno(theInstr); 2833 UInt imm4 = (theInstr >> 8) & 0xf; 2834 UInt Q = (theInstr >> 6) & 1; 2835 HChar reg_t = Q ? 'q' : 'd'; 2836 2837 if (Q) { 2838 putQReg(dreg, triop(Iop_ExtractV128, getQReg(nreg), 2839 getQReg(mreg), mkU8(imm4)), condT); 2840 } else { 2841 putDRegI64(dreg, triop(Iop_Extract64, getDRegI64(nreg), 2842 getDRegI64(mreg), mkU8(imm4)), condT); 2843 } 2844 DIP("vext.8 %c%d, %c%d, %c%d, #%d\n", reg_t, dreg, reg_t, nreg, 2845 reg_t, mreg, imm4); 2846 return True; 2847 } 2848 2849 /* VTBL, VTBX */ 2850 static 2851 Bool dis_neon_vtb ( UInt theInstr, IRTemp condT ) 2852 { 2853 UInt op = (theInstr >> 6) & 1; 2854 UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6)); 2855 UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6)); 2856 UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6)); 2857 UInt len = (theInstr >> 8) & 3; 2858 Int i; 2859 IROp cmp; 2860 ULong imm; 2861 IRTemp arg_l; 2862 IRTemp old_mask, new_mask, cur_mask; 2863 IRTemp old_res, new_res; 2864 IRTemp old_arg, new_arg; 2865 2866 if (dreg >= 0x100 || mreg >= 0x100 || nreg >= 0x100) 2867 return False; 2868 if (nreg + len > 31) 2869 return False; 2870 2871 cmp = Iop_CmpGT8Ux8; 2872 2873 old_mask = newTemp(Ity_I64); 2874 old_res = newTemp(Ity_I64); 2875 old_arg = newTemp(Ity_I64); 2876 assign(old_mask, mkU64(0)); 2877 assign(old_res, mkU64(0)); 2878 assign(old_arg, getDRegI64(mreg)); 2879 imm = 8; 2880 imm = (imm << 8) | imm; 2881 imm = (imm << 16) | imm; 2882 imm = (imm << 32) | imm; 2883 2884 for (i = 0; i <= len; i++) { 2885 arg_l = newTemp(Ity_I64); 2886 new_mask = newTemp(Ity_I64); 2887 cur_mask = newTemp(Ity_I64); 2888 new_res = newTemp(Ity_I64); 2889 new_arg = newTemp(Ity_I64); 2890 assign(arg_l, getDRegI64(nreg+i)); 2891 assign(new_arg, binop(Iop_Sub8x8, mkexpr(old_arg), mkU64(imm))); 2892 assign(cur_mask, binop(cmp, mkU64(imm), mkexpr(old_arg))); 2893 assign(new_mask, binop(Iop_Or64, mkexpr(old_mask), mkexpr(cur_mask))); 2894 assign(new_res, binop(Iop_Or64, 2895 mkexpr(old_res), 2896 binop(Iop_And64, 2897 binop(Iop_Perm8x8, 2898 mkexpr(arg_l), 2899 binop(Iop_And64, 2900 mkexpr(old_arg), 2901 mkexpr(cur_mask))), 2902 mkexpr(cur_mask)))); 2903 2904 old_arg = new_arg; 2905 old_mask = new_mask; 2906 old_res = new_res; 2907 } 2908 if (op) { 2909 new_res = newTemp(Ity_I64); 2910 assign(new_res, binop(Iop_Or64, 2911 binop(Iop_And64, 2912 getDRegI64(dreg), 2913 unop(Iop_Not64, mkexpr(old_mask))), 2914 mkexpr(old_res))); 2915 old_res = new_res; 2916 } 2917 2918 putDRegI64(dreg, mkexpr(old_res), condT); 2919 DIP("vtb%c.8 d%u, {", op ? 'x' : 'l', dreg); 2920 if (len > 0) { 2921 DIP("d%u-d%u", nreg, nreg + len); 2922 } else { 2923 DIP("d%u", nreg); 2924 } 2925 DIP("}, d%u\n", mreg); 2926 return True; 2927 } 2928 2929 /* VDUP (scalar) */ 2930 static 2931 Bool dis_neon_vdup ( UInt theInstr, IRTemp condT ) 2932 { 2933 UInt Q = (theInstr >> 6) & 1; 2934 UInt dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF); 2935 UInt mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF); 2936 UInt imm4 = (theInstr >> 16) & 0xF; 2937 UInt index; 2938 UInt size; 2939 IRTemp arg_m; 2940 IRTemp res; 2941 IROp op, op2; 2942 2943 if ((imm4 == 0) || (imm4 == 8)) 2944 return False; 2945 if ((Q == 1) && ((dreg & 1) == 1)) 2946 return False; 2947 if (Q) 2948 dreg >>= 1; 2949 arg_m = newTemp(Ity_I64); 2950 assign(arg_m, getDRegI64(mreg)); 2951 if (Q) 2952 res = newTemp(Ity_V128); 2953 else 2954 res = newTemp(Ity_I64); 2955 if ((imm4 & 1) == 1) { 2956 op = Q ? Iop_Dup8x16 : Iop_Dup8x8; 2957 op2 = Iop_GetElem8x8; 2958 index = imm4 >> 1; 2959 size = 8; 2960 } else if ((imm4 & 3) == 2) { 2961 op = Q ? Iop_Dup16x8 : Iop_Dup16x4; 2962 op2 = Iop_GetElem16x4; 2963 index = imm4 >> 2; 2964 size = 16; 2965 } else if ((imm4 & 7) == 4) { 2966 op = Q ? Iop_Dup32x4 : Iop_Dup32x2; 2967 op2 = Iop_GetElem32x2; 2968 index = imm4 >> 3; 2969 size = 32; 2970 } else { 2971 return False; // can this ever happen? 2972 } 2973 assign(res, unop(op, binop(op2, mkexpr(arg_m), mkU8(index)))); 2974 if (Q) { 2975 putQReg(dreg, mkexpr(res), condT); 2976 } else { 2977 putDRegI64(dreg, mkexpr(res), condT); 2978 } 2979 DIP("vdup.%d %c%d, d%d[%d]\n", size, Q ? 'q' : 'd', dreg, mreg, index); 2980 return True; 2981 } 2982 2983 /* A7.4.1 Three registers of the same length */ 2984 static 2985 Bool dis_neon_data_3same ( UInt theInstr, IRTemp condT ) 2986 { 2987 UInt Q = (theInstr >> 6) & 1; 2988 UInt dreg = get_neon_d_regno(theInstr); 2989 UInt nreg = get_neon_n_regno(theInstr); 2990 UInt mreg = get_neon_m_regno(theInstr); 2991 UInt A = (theInstr >> 8) & 0xF; 2992 UInt B = (theInstr >> 4) & 1; 2993 UInt C = (theInstr >> 20) & 0x3; 2994 UInt U = (theInstr >> 24) & 1; 2995 UInt size = C; 2996 2997 IRTemp arg_n; 2998 IRTemp arg_m; 2999 IRTemp res; 3000 3001 if (Q) { 3002 arg_n = newTemp(Ity_V128); 3003 arg_m = newTemp(Ity_V128); 3004 res = newTemp(Ity_V128); 3005 assign(arg_n, getQReg(nreg)); 3006 assign(arg_m, getQReg(mreg)); 3007 } else { 3008 arg_n = newTemp(Ity_I64); 3009 arg_m = newTemp(Ity_I64); 3010 res = newTemp(Ity_I64); 3011 assign(arg_n, getDRegI64(nreg)); 3012 assign(arg_m, getDRegI64(mreg)); 3013 } 3014 3015 switch(A) { 3016 case 0: 3017 if (B == 0) { 3018 /* VHADD */ 3019 ULong imm = 0; 3020 IRExpr *imm_val; 3021 IROp addOp; 3022 IROp andOp; 3023 IROp shOp; 3024 char regType = Q ? 'q' : 'd'; 3025 3026 if (size == 3) 3027 return False; 3028 switch(size) { 3029 case 0: imm = 0x101010101010101LL; break; 3030 case 1: imm = 0x1000100010001LL; break; 3031 case 2: imm = 0x100000001LL; break; 3032 default: vassert(0); 3033 } 3034 if (Q) { 3035 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)); 3036 andOp = Iop_AndV128; 3037 } else { 3038 imm_val = mkU64(imm); 3039 andOp = Iop_And64; 3040 } 3041 if (U) { 3042 switch(size) { 3043 case 0: 3044 addOp = Q ? Iop_Add8x16 : Iop_Add8x8; 3045 shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3046 break; 3047 case 1: 3048 addOp = Q ? Iop_Add16x8 : Iop_Add16x4; 3049 shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3050 break; 3051 case 2: 3052 addOp = Q ? Iop_Add32x4 : Iop_Add32x2; 3053 shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3054 break; 3055 default: 3056 vassert(0); 3057 } 3058 } else { 3059 switch(size) { 3060 case 0: 3061 addOp = Q ? Iop_Add8x16 : Iop_Add8x8; 3062 shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8; 3063 break; 3064 case 1: 3065 addOp = Q ? Iop_Add16x8 : Iop_Add16x4; 3066 shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4; 3067 break; 3068 case 2: 3069 addOp = Q ? Iop_Add32x4 : Iop_Add32x2; 3070 shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2; 3071 break; 3072 default: 3073 vassert(0); 3074 } 3075 } 3076 assign(res, 3077 binop(addOp, 3078 binop(addOp, 3079 binop(shOp, mkexpr(arg_m), mkU8(1)), 3080 binop(shOp, mkexpr(arg_n), mkU8(1))), 3081 binop(shOp, 3082 binop(addOp, 3083 binop(andOp, mkexpr(arg_m), imm_val), 3084 binop(andOp, mkexpr(arg_n), imm_val)), 3085 mkU8(1)))); 3086 DIP("vhadd.%c%d %c%d, %c%d, %c%d\n", 3087 U ? 'u' : 's', 8 << size, regType, 3088 dreg, regType, nreg, regType, mreg); 3089 } else { 3090 /* VQADD */ 3091 IROp op, op2; 3092 IRTemp tmp; 3093 char reg_t = Q ? 'q' : 'd'; 3094 if (Q) { 3095 switch (size) { 3096 case 0: 3097 op = U ? Iop_QAdd8Ux16 : Iop_QAdd8Sx16; 3098 op2 = Iop_Add8x16; 3099 break; 3100 case 1: 3101 op = U ? Iop_QAdd16Ux8 : Iop_QAdd16Sx8; 3102 op2 = Iop_Add16x8; 3103 break; 3104 case 2: 3105 op = U ? Iop_QAdd32Ux4 : Iop_QAdd32Sx4; 3106 op2 = Iop_Add32x4; 3107 break; 3108 case 3: 3109 op = U ? Iop_QAdd64Ux2 : Iop_QAdd64Sx2; 3110 op2 = Iop_Add64x2; 3111 break; 3112 default: 3113 vassert(0); 3114 } 3115 } else { 3116 switch (size) { 3117 case 0: 3118 op = U ? Iop_QAdd8Ux8 : Iop_QAdd8Sx8; 3119 op2 = Iop_Add8x8; 3120 break; 3121 case 1: 3122 op = U ? Iop_QAdd16Ux4 : Iop_QAdd16Sx4; 3123 op2 = Iop_Add16x4; 3124 break; 3125 case 2: 3126 op = U ? Iop_QAdd32Ux2 : Iop_QAdd32Sx2; 3127 op2 = Iop_Add32x2; 3128 break; 3129 case 3: 3130 op = U ? Iop_QAdd64Ux1 : Iop_QAdd64Sx1; 3131 op2 = Iop_Add64; 3132 break; 3133 default: 3134 vassert(0); 3135 } 3136 } 3137 if (Q) { 3138 tmp = newTemp(Ity_V128); 3139 } else { 3140 tmp = newTemp(Ity_I64); 3141 } 3142 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 3143 #ifndef DISABLE_QC_FLAG 3144 assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m))); 3145 setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT); 3146 #endif 3147 DIP("vqadd.%c%d %c%d, %c%d, %c%d\n", 3148 U ? 'u' : 's', 3149 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg); 3150 } 3151 break; 3152 case 1: 3153 if (B == 0) { 3154 /* VRHADD */ 3155 /* VRHADD C, A, B ::= 3156 C = (A >> 1) + (B >> 1) + (((A & 1) + (B & 1) + 1) >> 1) */ 3157 IROp shift_op, add_op; 3158 IRTemp cc; 3159 ULong one = 1; 3160 HChar reg_t = Q ? 'q' : 'd'; 3161 switch (size) { 3162 case 0: one = (one << 8) | one; /* fall through */ 3163 case 1: one = (one << 16) | one; /* fall through */ 3164 case 2: one = (one << 32) | one; break; 3165 case 3: return False; 3166 default: vassert(0); 3167 } 3168 if (Q) { 3169 switch (size) { 3170 case 0: 3171 shift_op = U ? Iop_ShrN8x16 : Iop_SarN8x16; 3172 add_op = Iop_Add8x16; 3173 break; 3174 case 1: 3175 shift_op = U ? Iop_ShrN16x8 : Iop_SarN16x8; 3176 add_op = Iop_Add16x8; 3177 break; 3178 case 2: 3179 shift_op = U ? Iop_ShrN32x4 : Iop_SarN32x4; 3180 add_op = Iop_Add32x4; 3181 break; 3182 case 3: 3183 return False; 3184 default: 3185 vassert(0); 3186 } 3187 } else { 3188 switch (size) { 3189 case 0: 3190 shift_op = U ? Iop_ShrN8x8 : Iop_SarN8x8; 3191 add_op = Iop_Add8x8; 3192 break; 3193 case 1: 3194 shift_op = U ? Iop_ShrN16x4 : Iop_SarN16x4; 3195 add_op = Iop_Add16x4; 3196 break; 3197 case 2: 3198 shift_op = U ? Iop_ShrN32x2 : Iop_SarN32x2; 3199 add_op = Iop_Add32x2; 3200 break; 3201 case 3: 3202 return False; 3203 default: 3204 vassert(0); 3205 } 3206 } 3207 if (Q) { 3208 cc = newTemp(Ity_V128); 3209 assign(cc, binop(shift_op, 3210 binop(add_op, 3211 binop(add_op, 3212 binop(Iop_AndV128, 3213 mkexpr(arg_n), 3214 binop(Iop_64HLtoV128, 3215 mkU64(one), 3216 mkU64(one))), 3217 binop(Iop_AndV128, 3218 mkexpr(arg_m), 3219 binop(Iop_64HLtoV128, 3220 mkU64(one), 3221 mkU64(one)))), 3222 binop(Iop_64HLtoV128, 3223 mkU64(one), 3224 mkU64(one))), 3225 mkU8(1))); 3226 assign(res, binop(add_op, 3227 binop(add_op, 3228 binop(shift_op, 3229 mkexpr(arg_n), 3230 mkU8(1)), 3231 binop(shift_op, 3232 mkexpr(arg_m), 3233 mkU8(1))), 3234 mkexpr(cc))); 3235 } else { 3236 cc = newTemp(Ity_I64); 3237 assign(cc, binop(shift_op, 3238 binop(add_op, 3239 binop(add_op, 3240 binop(Iop_And64, 3241 mkexpr(arg_n), 3242 mkU64(one)), 3243 binop(Iop_And64, 3244 mkexpr(arg_m), 3245 mkU64(one))), 3246 mkU64(one)), 3247 mkU8(1))); 3248 assign(res, binop(add_op, 3249 binop(add_op, 3250 binop(shift_op, 3251 mkexpr(arg_n), 3252 mkU8(1)), 3253 binop(shift_op, 3254 mkexpr(arg_m), 3255 mkU8(1))), 3256 mkexpr(cc))); 3257 } 3258 DIP("vrhadd.%c%d %c%d, %c%d, %c%d\n", 3259 U ? 'u' : 's', 3260 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg); 3261 } else { 3262 if (U == 0) { 3263 switch(C) { 3264 case 0: { 3265 /* VAND */ 3266 HChar reg_t = Q ? 'q' : 'd'; 3267 if (Q) { 3268 assign(res, binop(Iop_AndV128, mkexpr(arg_n), 3269 mkexpr(arg_m))); 3270 } else { 3271 assign(res, binop(Iop_And64, mkexpr(arg_n), 3272 mkexpr(arg_m))); 3273 } 3274 DIP("vand %c%d, %c%d, %c%d\n", 3275 reg_t, dreg, reg_t, nreg, reg_t, mreg); 3276 break; 3277 } 3278 case 1: { 3279 /* VBIC */ 3280 HChar reg_t = Q ? 'q' : 'd'; 3281 if (Q) { 3282 assign(res, binop(Iop_AndV128,mkexpr(arg_n), 3283 unop(Iop_NotV128, mkexpr(arg_m)))); 3284 } else { 3285 assign(res, binop(Iop_And64, mkexpr(arg_n), 3286 unop(Iop_Not64, mkexpr(arg_m)))); 3287 } 3288 DIP("vbic %c%d, %c%d, %c%d\n", 3289 reg_t, dreg, reg_t, nreg, reg_t, mreg); 3290 break; 3291 } 3292 case 2: 3293 if ( nreg != mreg) { 3294 /* VORR */ 3295 HChar reg_t = Q ? 'q' : 'd'; 3296 if (Q) { 3297 assign(res, binop(Iop_OrV128, mkexpr(arg_n), 3298 mkexpr(arg_m))); 3299 } else { 3300 assign(res, binop(Iop_Or64, mkexpr(arg_n), 3301 mkexpr(arg_m))); 3302 } 3303 DIP("vorr %c%d, %c%d, %c%d\n", 3304 reg_t, dreg, reg_t, nreg, reg_t, mreg); 3305 } else { 3306 /* VMOV */ 3307 HChar reg_t = Q ? 'q' : 'd'; 3308 assign(res, mkexpr(arg_m)); 3309 DIP("vmov %c%d, %c%d\n", reg_t, dreg, reg_t, mreg); 3310 } 3311 break; 3312 case 3:{ 3313 /* VORN */ 3314 HChar reg_t = Q ? 'q' : 'd'; 3315 if (Q) { 3316 assign(res, binop(Iop_OrV128,mkexpr(arg_n), 3317 unop(Iop_NotV128, mkexpr(arg_m)))); 3318 } else { 3319 assign(res, binop(Iop_Or64, mkexpr(arg_n), 3320 unop(Iop_Not64, mkexpr(arg_m)))); 3321 } 3322 DIP("vorn %c%d, %c%d, %c%d\n", 3323 reg_t, dreg, reg_t, nreg, reg_t, mreg); 3324 break; 3325 } 3326 } 3327 } else { 3328 switch(C) { 3329 case 0: 3330 /* VEOR (XOR) */ 3331 if (Q) { 3332 assign(res, binop(Iop_XorV128, mkexpr(arg_n), 3333 mkexpr(arg_m))); 3334 } else { 3335 assign(res, binop(Iop_Xor64, mkexpr(arg_n), 3336 mkexpr(arg_m))); 3337 } 3338 DIP("veor %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg, 3339 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 3340 break; 3341 case 1: 3342 /* VBSL */ 3343 if (Q) { 3344 IRTemp reg_d = newTemp(Ity_V128); 3345 assign(reg_d, getQReg(dreg)); 3346 assign(res, 3347 binop(Iop_OrV128, 3348 binop(Iop_AndV128, mkexpr(arg_n), 3349 mkexpr(reg_d)), 3350 binop(Iop_AndV128, 3351 mkexpr(arg_m), 3352 unop(Iop_NotV128, 3353 mkexpr(reg_d)) ) ) ); 3354 } else { 3355 IRTemp reg_d = newTemp(Ity_I64); 3356 assign(reg_d, getDRegI64(dreg)); 3357 assign(res, 3358 binop(Iop_Or64, 3359 binop(Iop_And64, mkexpr(arg_n), 3360 mkexpr(reg_d)), 3361 binop(Iop_And64, 3362 mkexpr(arg_m), 3363 unop(Iop_Not64, mkexpr(reg_d))))); 3364 } 3365 DIP("vbsl %c%u, %c%u, %c%u\n", 3366 Q ? 'q' : 'd', dreg, 3367 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 3368 break; 3369 case 2: 3370 /* VBIT */ 3371 if (Q) { 3372 IRTemp reg_d = newTemp(Ity_V128); 3373 assign(reg_d, getQReg(dreg)); 3374 assign(res, 3375 binop(Iop_OrV128, 3376 binop(Iop_AndV128, mkexpr(arg_n), 3377 mkexpr(arg_m)), 3378 binop(Iop_AndV128, 3379 mkexpr(reg_d), 3380 unop(Iop_NotV128, mkexpr(arg_m))))); 3381 } else { 3382 IRTemp reg_d = newTemp(Ity_I64); 3383 assign(reg_d, getDRegI64(dreg)); 3384 assign(res, 3385 binop(Iop_Or64, 3386 binop(Iop_And64, mkexpr(arg_n), 3387 mkexpr(arg_m)), 3388 binop(Iop_And64, 3389 mkexpr(reg_d), 3390 unop(Iop_Not64, mkexpr(arg_m))))); 3391 } 3392 DIP("vbit %c%u, %c%u, %c%u\n", 3393 Q ? 'q' : 'd', dreg, 3394 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 3395 break; 3396 case 3: 3397 /* VBIF */ 3398 if (Q) { 3399 IRTemp reg_d = newTemp(Ity_V128); 3400 assign(reg_d, getQReg(dreg)); 3401 assign(res, 3402 binop(Iop_OrV128, 3403 binop(Iop_AndV128, mkexpr(reg_d), 3404 mkexpr(arg_m)), 3405 binop(Iop_AndV128, 3406 mkexpr(arg_n), 3407 unop(Iop_NotV128, mkexpr(arg_m))))); 3408 } else { 3409 IRTemp reg_d = newTemp(Ity_I64); 3410 assign(reg_d, getDRegI64(dreg)); 3411 assign(res, 3412 binop(Iop_Or64, 3413 binop(Iop_And64, mkexpr(reg_d), 3414 mkexpr(arg_m)), 3415 binop(Iop_And64, 3416 mkexpr(arg_n), 3417 unop(Iop_Not64, mkexpr(arg_m))))); 3418 } 3419 DIP("vbif %c%u, %c%u, %c%u\n", 3420 Q ? 'q' : 'd', dreg, 3421 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 3422 break; 3423 } 3424 } 3425 } 3426 break; 3427 case 2: 3428 if (B == 0) { 3429 /* VHSUB */ 3430 /* (A >> 1) - (B >> 1) - (NOT (A) & B & 1) */ 3431 ULong imm = 0; 3432 IRExpr *imm_val; 3433 IROp subOp; 3434 IROp notOp; 3435 IROp andOp; 3436 IROp shOp; 3437 if (size == 3) 3438 return False; 3439 switch(size) { 3440 case 0: imm = 0x101010101010101LL; break; 3441 case 1: imm = 0x1000100010001LL; break; 3442 case 2: imm = 0x100000001LL; break; 3443 default: vassert(0); 3444 } 3445 if (Q) { 3446 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)); 3447 andOp = Iop_AndV128; 3448 notOp = Iop_NotV128; 3449 } else { 3450 imm_val = mkU64(imm); 3451 andOp = Iop_And64; 3452 notOp = Iop_Not64; 3453 } 3454 if (U) { 3455 switch(size) { 3456 case 0: 3457 subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8; 3458 shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3459 break; 3460 case 1: 3461 subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4; 3462 shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3463 break; 3464 case 2: 3465 subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2; 3466 shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3467 break; 3468 default: 3469 vassert(0); 3470 } 3471 } else { 3472 switch(size) { 3473 case 0: 3474 subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8; 3475 shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8; 3476 break; 3477 case 1: 3478 subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4; 3479 shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4; 3480 break; 3481 case 2: 3482 subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2; 3483 shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2; 3484 break; 3485 default: 3486 vassert(0); 3487 } 3488 } 3489 assign(res, 3490 binop(subOp, 3491 binop(subOp, 3492 binop(shOp, mkexpr(arg_n), mkU8(1)), 3493 binop(shOp, mkexpr(arg_m), mkU8(1))), 3494 binop(andOp, 3495 binop(andOp, 3496 unop(notOp, mkexpr(arg_n)), 3497 mkexpr(arg_m)), 3498 imm_val))); 3499 DIP("vhsub.%c%u %c%u, %c%u, %c%u\n", 3500 U ? 'u' : 's', 8 << size, 3501 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 3502 mreg); 3503 } else { 3504 /* VQSUB */ 3505 IROp op, op2; 3506 IRTemp tmp; 3507 if (Q) { 3508 switch (size) { 3509 case 0: 3510 op = U ? Iop_QSub8Ux16 : Iop_QSub8Sx16; 3511 op2 = Iop_Sub8x16; 3512 break; 3513 case 1: 3514 op = U ? Iop_QSub16Ux8 : Iop_QSub16Sx8; 3515 op2 = Iop_Sub16x8; 3516 break; 3517 case 2: 3518 op = U ? Iop_QSub32Ux4 : Iop_QSub32Sx4; 3519 op2 = Iop_Sub32x4; 3520 break; 3521 case 3: 3522 op = U ? Iop_QSub64Ux2 : Iop_QSub64Sx2; 3523 op2 = Iop_Sub64x2; 3524 break; 3525 default: 3526 vassert(0); 3527 } 3528 } else { 3529 switch (size) { 3530 case 0: 3531 op = U ? Iop_QSub8Ux8 : Iop_QSub8Sx8; 3532 op2 = Iop_Sub8x8; 3533 break; 3534 case 1: 3535 op = U ? Iop_QSub16Ux4 : Iop_QSub16Sx4; 3536 op2 = Iop_Sub16x4; 3537 break; 3538 case 2: 3539 op = U ? Iop_QSub32Ux2 : Iop_QSub32Sx2; 3540 op2 = Iop_Sub32x2; 3541 break; 3542 case 3: 3543 op = U ? Iop_QSub64Ux1 : Iop_QSub64Sx1; 3544 op2 = Iop_Sub64; 3545 break; 3546 default: 3547 vassert(0); 3548 } 3549 } 3550 if (Q) 3551 tmp = newTemp(Ity_V128); 3552 else 3553 tmp = newTemp(Ity_I64); 3554 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 3555 #ifndef DISABLE_QC_FLAG 3556 assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m))); 3557 setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT); 3558 #endif 3559 DIP("vqsub.%c%u %c%u, %c%u, %c%u\n", 3560 U ? 'u' : 's', 8 << size, 3561 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 3562 mreg); 3563 } 3564 break; 3565 case 3: { 3566 IROp op; 3567 if (Q) { 3568 switch (size) { 3569 case 0: op = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; break; 3570 case 1: op = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; break; 3571 case 2: op = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; break; 3572 case 3: return False; 3573 default: vassert(0); 3574 } 3575 } else { 3576 switch (size) { 3577 case 0: op = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; break; 3578 case 1: op = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; break; 3579 case 2: op = U ? Iop_CmpGT32Ux2: Iop_CmpGT32Sx2; break; 3580 case 3: return False; 3581 default: vassert(0); 3582 } 3583 } 3584 if (B == 0) { 3585 /* VCGT */ 3586 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 3587 DIP("vcgt.%c%u %c%u, %c%u, %c%u\n", 3588 U ? 'u' : 's', 8 << size, 3589 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 3590 mreg); 3591 } else { 3592 /* VCGE */ 3593 /* VCGE res, argn, argm 3594 is equal to 3595 VCGT tmp, argm, argn 3596 VNOT res, tmp */ 3597 assign(res, 3598 unop(Q ? Iop_NotV128 : Iop_Not64, 3599 binop(op, mkexpr(arg_m), mkexpr(arg_n)))); 3600 DIP("vcge.%c%u %c%u, %c%u, %c%u\n", 3601 U ? 'u' : 's', 8 << size, 3602 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 3603 mreg); 3604 } 3605 } 3606 break; 3607 case 4: 3608 if (B == 0) { 3609 /* VSHL */ 3610 IROp op, sub_op; 3611 IRTemp tmp; 3612 if (U) { 3613 switch (size) { 3614 case 0: op = Q ? Iop_Shl8x16 : Iop_Shl8x8; break; 3615 case 1: op = Q ? Iop_Shl16x8 : Iop_Shl16x4; break; 3616 case 2: op = Q ? Iop_Shl32x4 : Iop_Shl32x2; break; 3617 case 3: op = Q ? Iop_Shl64x2 : Iop_Shl64; break; 3618 default: vassert(0); 3619 } 3620 } else { 3621 tmp = newTemp(Q ? Ity_V128 : Ity_I64); 3622 switch (size) { 3623 case 0: 3624 op = Q ? Iop_Sar8x16 : Iop_Sar8x8; 3625 sub_op = Q ? Iop_Sub8x16 : Iop_Sub8x8; 3626 break; 3627 case 1: 3628 op = Q ? Iop_Sar16x8 : Iop_Sar16x4; 3629 sub_op = Q ? Iop_Sub16x8 : Iop_Sub16x4; 3630 break; 3631 case 2: 3632 op = Q ? Iop_Sar32x4 : Iop_Sar32x2; 3633 sub_op = Q ? Iop_Sub32x4 : Iop_Sub32x2; 3634 break; 3635 case 3: 3636 op = Q ? Iop_Sar64x2 : Iop_Sar64; 3637 sub_op = Q ? Iop_Sub64x2 : Iop_Sub64; 3638 break; 3639 default: 3640 vassert(0); 3641 } 3642 } 3643 if (U) { 3644 if (!Q && (size == 3)) 3645 assign(res, binop(op, mkexpr(arg_m), 3646 unop(Iop_64to8, mkexpr(arg_n)))); 3647 else 3648 assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n))); 3649 } else { 3650 if (Q) 3651 assign(tmp, binop(sub_op, 3652 binop(Iop_64HLtoV128, mkU64(0), mkU64(0)), 3653 mkexpr(arg_n))); 3654 else 3655 assign(tmp, binop(sub_op, mkU64(0), mkexpr(arg_n))); 3656 if (!Q && (size == 3)) 3657 assign(res, binop(op, mkexpr(arg_m), 3658 unop(Iop_64to8, mkexpr(tmp)))); 3659 else 3660 assign(res, binop(op, mkexpr(arg_m), mkexpr(tmp))); 3661 } 3662 DIP("vshl.%c%u %c%u, %c%u, %c%u\n", 3663 U ? 'u' : 's', 8 << size, 3664 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd', 3665 nreg); 3666 } else { 3667 /* VQSHL */ 3668 IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt; 3669 IRTemp tmp, shval, mask, old_shval; 3670 UInt i; 3671 ULong esize; 3672 cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; 3673 cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; 3674 if (U) { 3675 switch (size) { 3676 case 0: 3677 op = Q ? Iop_QShl8x16 : Iop_QShl8x8; 3678 op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8; 3679 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3680 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 3681 break; 3682 case 1: 3683 op = Q ? Iop_QShl16x8 : Iop_QShl16x4; 3684 op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4; 3685 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3686 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 3687 break; 3688 case 2: 3689 op = Q ? Iop_QShl32x4 : Iop_QShl32x2; 3690 op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2; 3691 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3692 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; 3693 break; 3694 case 3: 3695 op = Q ? Iop_QShl64x2 : Iop_QShl64x1; 3696 op_rev = Q ? Iop_Shr64x2 : Iop_Shr64; 3697 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 3698 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 3699 break; 3700 default: 3701 vassert(0); 3702 } 3703 } else { 3704 switch (size) { 3705 case 0: 3706 op = Q ? Iop_QSal8x16 : Iop_QSal8x8; 3707 op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8; 3708 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3709 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 3710 break; 3711 case 1: 3712 op = Q ? Iop_QSal16x8 : Iop_QSal16x4; 3713 op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4; 3714 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3715 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 3716 break; 3717 case 2: 3718 op = Q ? Iop_QSal32x4 : Iop_QSal32x2; 3719 op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2; 3720 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3721 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; 3722 break; 3723 case 3: 3724 op = Q ? Iop_QSal64x2 : Iop_QSal64x1; 3725 op_rev = Q ? Iop_Sar64x2 : Iop_Sar64; 3726 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 3727 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 3728 break; 3729 default: 3730 vassert(0); 3731 } 3732 } 3733 if (Q) { 3734 tmp = newTemp(Ity_V128); 3735 shval = newTemp(Ity_V128); 3736 mask = newTemp(Ity_V128); 3737 } else { 3738 tmp = newTemp(Ity_I64); 3739 shval = newTemp(Ity_I64); 3740 mask = newTemp(Ity_I64); 3741 } 3742 assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n))); 3743 #ifndef DISABLE_QC_FLAG 3744 /* Only least significant byte from second argument is used. 3745 Copy this byte to the whole vector element. */ 3746 assign(shval, binop(op_shrn, 3747 binop(op_shln, 3748 mkexpr(arg_n), 3749 mkU8((8 << size) - 8)), 3750 mkU8((8 << size) - 8))); 3751 for(i = 0; i < size; i++) { 3752 old_shval = shval; 3753 shval = newTemp(Q ? Ity_V128 : Ity_I64); 3754 assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64, 3755 mkexpr(old_shval), 3756 binop(op_shln, 3757 mkexpr(old_shval), 3758 mkU8(8 << i)))); 3759 } 3760 /* If shift is greater or equal to the element size and 3761 element is non-zero, then QC flag should be set. */ 3762 esize = (8 << size) - 1; 3763 esize = (esize << 8) | esize; 3764 esize = (esize << 16) | esize; 3765 esize = (esize << 32) | esize; 3766 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 3767 binop(cmp_gt, mkexpr(shval), 3768 Q ? mkU128(esize) : mkU64(esize)), 3769 unop(cmp_neq, mkexpr(arg_m))), 3770 Q ? mkU128(0) : mkU64(0), 3771 Q, condT); 3772 /* Othervise QC flag should be set if shift value is positive and 3773 result beign rightshifted the same value is not equal to left 3774 argument. */ 3775 assign(mask, binop(cmp_gt, mkexpr(shval), 3776 Q ? mkU128(0) : mkU64(0))); 3777 if (!Q && size == 3) 3778 assign(tmp, binop(op_rev, mkexpr(res), 3779 unop(Iop_64to8, mkexpr(arg_n)))); 3780 else 3781 assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n))); 3782 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 3783 mkexpr(tmp), mkexpr(mask)), 3784 binop(Q ? Iop_AndV128 : Iop_And64, 3785 mkexpr(arg_m), mkexpr(mask)), 3786 Q, condT); 3787 #endif 3788 DIP("vqshl.%c%u %c%u, %c%u, %c%u\n", 3789 U ? 'u' : 's', 8 << size, 3790 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd', 3791 nreg); 3792 } 3793 break; 3794 case 5: 3795 if (B == 0) { 3796 /* VRSHL */ 3797 IROp op, op_shrn, op_shln, cmp_gt, op_sub, op_add; 3798 IRTemp shval, old_shval, imm_val, round; 3799 UInt i; 3800 ULong imm; 3801 cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; 3802 imm = 1L; 3803 switch (size) { 3804 case 0: imm = (imm << 8) | imm; /* fall through */ 3805 case 1: imm = (imm << 16) | imm; /* fall through */ 3806 case 2: imm = (imm << 32) | imm; /* fall through */ 3807 case 3: break; 3808 default: vassert(0); 3809 } 3810 imm_val = newTemp(Q ? Ity_V128 : Ity_I64); 3811 round = newTemp(Q ? Ity_V128 : Ity_I64); 3812 assign(imm_val, Q ? mkU128(imm) : mkU64(imm)); 3813 if (U) { 3814 switch (size) { 3815 case 0: 3816 op = Q ? Iop_Shl8x16 : Iop_Shl8x8; 3817 op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8; 3818 op_add = Q ? Iop_Add8x16 : Iop_Add8x8; 3819 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3820 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 3821 break; 3822 case 1: 3823 op = Q ? Iop_Shl16x8 : Iop_Shl16x4; 3824 op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4; 3825 op_add = Q ? Iop_Add16x8 : Iop_Add16x4; 3826 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3827 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 3828 break; 3829 case 2: 3830 op = Q ? Iop_Shl32x4 : Iop_Shl32x2; 3831 op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2; 3832 op_add = Q ? Iop_Add32x4 : Iop_Add32x2; 3833 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3834 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; 3835 break; 3836 case 3: 3837 op = Q ? Iop_Shl64x2 : Iop_Shl64; 3838 op_sub = Q ? Iop_Sub64x2 : Iop_Sub64; 3839 op_add = Q ? Iop_Add64x2 : Iop_Add64; 3840 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 3841 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 3842 break; 3843 default: 3844 vassert(0); 3845 } 3846 } else { 3847 switch (size) { 3848 case 0: 3849 op = Q ? Iop_Sal8x16 : Iop_Sal8x8; 3850 op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8; 3851 op_add = Q ? Iop_Add8x16 : Iop_Add8x8; 3852 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3853 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 3854 break; 3855 case 1: 3856 op = Q ? Iop_Sal16x8 : Iop_Sal16x4; 3857 op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4; 3858 op_add = Q ? Iop_Add16x8 : Iop_Add16x4; 3859 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3860 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 3861 break; 3862 case 2: 3863 op = Q ? Iop_Sal32x4 : Iop_Sal32x2; 3864 op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2; 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_Sal64x2 : Iop_Sal64x1; 3871 op_sub = Q ? Iop_Sub64x2 : Iop_Sub64; 3872 op_add = Q ? Iop_Add64x2 : Iop_Add64; 3873 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 3874 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 3875 break; 3876 default: 3877 vassert(0); 3878 } 3879 } 3880 if (Q) { 3881 shval = newTemp(Ity_V128); 3882 } else { 3883 shval = newTemp(Ity_I64); 3884 } 3885 /* Only least significant byte from second argument is used. 3886 Copy this byte to the whole vector element. */ 3887 assign(shval, binop(op_shrn, 3888 binop(op_shln, 3889 mkexpr(arg_n), 3890 mkU8((8 << size) - 8)), 3891 mkU8((8 << size) - 8))); 3892 for (i = 0; i < size; i++) { 3893 old_shval = shval; 3894 shval = newTemp(Q ? Ity_V128 : Ity_I64); 3895 assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64, 3896 mkexpr(old_shval), 3897 binop(op_shln, 3898 mkexpr(old_shval), 3899 mkU8(8 << i)))); 3900 } 3901 /* Compute the result */ 3902 if (!Q && size == 3 && U) { 3903 assign(round, binop(Q ? Iop_AndV128 : Iop_And64, 3904 binop(op, 3905 mkexpr(arg_m), 3906 unop(Iop_64to8, 3907 binop(op_add, 3908 mkexpr(arg_n), 3909 mkexpr(imm_val)))), 3910 binop(Q ? Iop_AndV128 : Iop_And64, 3911 mkexpr(imm_val), 3912 binop(cmp_gt, 3913 Q ? mkU128(0) : mkU64(0), 3914 mkexpr(arg_n))))); 3915 assign(res, binop(op_add, 3916 binop(op, 3917 mkexpr(arg_m), 3918 unop(Iop_64to8, mkexpr(arg_n))), 3919 mkexpr(round))); 3920 } else { 3921 assign(round, binop(Q ? Iop_AndV128 : Iop_And64, 3922 binop(op, 3923 mkexpr(arg_m), 3924 binop(op_add, 3925 mkexpr(arg_n), 3926 mkexpr(imm_val))), 3927 binop(Q ? Iop_AndV128 : Iop_And64, 3928 mkexpr(imm_val), 3929 binop(cmp_gt, 3930 Q ? mkU128(0) : mkU64(0), 3931 mkexpr(arg_n))))); 3932 assign(res, binop(op_add, 3933 binop(op, mkexpr(arg_m), mkexpr(arg_n)), 3934 mkexpr(round))); 3935 } 3936 DIP("vrshl.%c%u %c%u, %c%u, %c%u\n", 3937 U ? 'u' : 's', 8 << size, 3938 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd', 3939 nreg); 3940 } else { 3941 /* VQRSHL */ 3942 IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt, op_sub, op_add; 3943 IRTemp tmp, shval, mask, old_shval, imm_val, round; 3944 UInt i; 3945 ULong esize, imm; 3946 cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; 3947 cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; 3948 imm = 1L; 3949 switch (size) { 3950 case 0: imm = (imm << 8) | imm; /* fall through */ 3951 case 1: imm = (imm << 16) | imm; /* fall through */ 3952 case 2: imm = (imm << 32) | imm; /* fall through */ 3953 case 3: break; 3954 default: vassert(0); 3955 } 3956 imm_val = newTemp(Q ? Ity_V128 : Ity_I64); 3957 round = newTemp(Q ? Ity_V128 : Ity_I64); 3958 assign(imm_val, Q ? mkU128(imm) : mkU64(imm)); 3959 if (U) { 3960 switch (size) { 3961 case 0: 3962 op = Q ? Iop_QShl8x16 : Iop_QShl8x8; 3963 op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8; 3964 op_add = Q ? Iop_Add8x16 : Iop_Add8x8; 3965 op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8; 3966 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 3967 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 3968 break; 3969 case 1: 3970 op = Q ? Iop_QShl16x8 : Iop_QShl16x4; 3971 op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4; 3972 op_add = Q ? Iop_Add16x8 : Iop_Add16x4; 3973 op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4; 3974 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 3975 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 3976 break; 3977 case 2: 3978 op = Q ? Iop_QShl32x4 : Iop_QShl32x2; 3979 op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2; 3980 op_add = Q ? Iop_Add32x4 : Iop_Add32x2; 3981 op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2; 3982 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 3983 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; 3984 break; 3985 case 3: 3986 op = Q ? Iop_QShl64x2 : Iop_QShl64x1; 3987 op_sub = Q ? Iop_Sub64x2 : Iop_Sub64; 3988 op_add = Q ? Iop_Add64x2 : Iop_Add64; 3989 op_rev = Q ? Iop_Shr64x2 : Iop_Shr64; 3990 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 3991 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 3992 break; 3993 default: 3994 vassert(0); 3995 } 3996 } else { 3997 switch (size) { 3998 case 0: 3999 op = Q ? Iop_QSal8x16 : Iop_QSal8x8; 4000 op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8; 4001 op_add = Q ? Iop_Add8x16 : Iop_Add8x8; 4002 op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8; 4003 op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 4004 op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; 4005 break; 4006 case 1: 4007 op = Q ? Iop_QSal16x8 : Iop_QSal16x4; 4008 op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4; 4009 op_add = Q ? Iop_Add16x8 : Iop_Add16x4; 4010 op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4; 4011 op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 4012 op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; 4013 break; 4014 case 2: 4015 op = Q ? Iop_QSal32x4 : Iop_QSal32x2; 4016 op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2; 4017 op_add = Q ? Iop_Add32x4 : Iop_Add32x2; 4018 op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2; 4019 op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 4020 op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; 4021 break; 4022 case 3: 4023 op = Q ? Iop_QSal64x2 : Iop_QSal64x1; 4024 op_sub = Q ? Iop_Sub64x2 : Iop_Sub64; 4025 op_add = Q ? Iop_Add64x2 : Iop_Add64; 4026 op_rev = Q ? Iop_Sar64x2 : Iop_Sar64; 4027 op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64; 4028 op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64; 4029 break; 4030 default: 4031 vassert(0); 4032 } 4033 } 4034 if (Q) { 4035 tmp = newTemp(Ity_V128); 4036 shval = newTemp(Ity_V128); 4037 mask = newTemp(Ity_V128); 4038 } else { 4039 tmp = newTemp(Ity_I64); 4040 shval = newTemp(Ity_I64); 4041 mask = newTemp(Ity_I64); 4042 } 4043 /* Only least significant byte from second argument is used. 4044 Copy this byte to the whole vector element. */ 4045 assign(shval, binop(op_shrn, 4046 binop(op_shln, 4047 mkexpr(arg_n), 4048 mkU8((8 << size) - 8)), 4049 mkU8((8 << size) - 8))); 4050 for (i = 0; i < size; i++) { 4051 old_shval = shval; 4052 shval = newTemp(Q ? Ity_V128 : Ity_I64); 4053 assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64, 4054 mkexpr(old_shval), 4055 binop(op_shln, 4056 mkexpr(old_shval), 4057 mkU8(8 << i)))); 4058 } 4059 /* Compute the result */ 4060 assign(round, binop(Q ? Iop_AndV128 : Iop_And64, 4061 binop(op, 4062 mkexpr(arg_m), 4063 binop(op_add, 4064 mkexpr(arg_n), 4065 mkexpr(imm_val))), 4066 binop(Q ? Iop_AndV128 : Iop_And64, 4067 mkexpr(imm_val), 4068 binop(cmp_gt, 4069 Q ? mkU128(0) : mkU64(0), 4070 mkexpr(arg_n))))); 4071 assign(res, binop(op_add, 4072 binop(op, mkexpr(arg_m), mkexpr(arg_n)), 4073 mkexpr(round))); 4074 #ifndef DISABLE_QC_FLAG 4075 /* If shift is greater or equal to the element size and element is 4076 non-zero, then QC flag should be set. */ 4077 esize = (8 << size) - 1; 4078 esize = (esize << 8) | esize; 4079 esize = (esize << 16) | esize; 4080 esize = (esize << 32) | esize; 4081 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 4082 binop(cmp_gt, mkexpr(shval), 4083 Q ? mkU128(esize) : mkU64(esize)), 4084 unop(cmp_neq, mkexpr(arg_m))), 4085 Q ? mkU128(0) : mkU64(0), 4086 Q, condT); 4087 /* Othervise QC flag should be set if shift value is positive and 4088 result beign rightshifted the same value is not equal to left 4089 argument. */ 4090 assign(mask, binop(cmp_gt, mkexpr(shval), 4091 Q ? mkU128(0) : mkU64(0))); 4092 if (!Q && size == 3) 4093 assign(tmp, binop(op_rev, mkexpr(res), 4094 unop(Iop_64to8, mkexpr(arg_n)))); 4095 else 4096 assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n))); 4097 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 4098 mkexpr(tmp), mkexpr(mask)), 4099 binop(Q ? Iop_AndV128 : Iop_And64, 4100 mkexpr(arg_m), mkexpr(mask)), 4101 Q, condT); 4102 #endif 4103 DIP("vqrshl.%c%u %c%u, %c%u, %c%u\n", 4104 U ? 'u' : 's', 8 << size, 4105 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd', 4106 nreg); 4107 } 4108 break; 4109 case 6: 4110 /* VMAX, VMIN */ 4111 if (B == 0) { 4112 /* VMAX */ 4113 IROp op; 4114 if (U == 0) { 4115 switch (size) { 4116 case 0: op = Q ? Iop_Max8Sx16 : Iop_Max8Sx8; break; 4117 case 1: op = Q ? Iop_Max16Sx8 : Iop_Max16Sx4; break; 4118 case 2: op = Q ? Iop_Max32Sx4 : Iop_Max32Sx2; break; 4119 case 3: return False; 4120 default: vassert(0); 4121 } 4122 } else { 4123 switch (size) { 4124 case 0: op = Q ? Iop_Max8Ux16 : Iop_Max8Ux8; break; 4125 case 1: op = Q ? Iop_Max16Ux8 : Iop_Max16Ux4; break; 4126 case 2: op = Q ? Iop_Max32Ux4 : Iop_Max32Ux2; break; 4127 case 3: return False; 4128 default: vassert(0); 4129 } 4130 } 4131 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4132 DIP("vmax.%c%u %c%u, %c%u, %c%u\n", 4133 U ? 'u' : 's', 8 << size, 4134 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4135 mreg); 4136 } else { 4137 /* VMIN */ 4138 IROp op; 4139 if (U == 0) { 4140 switch (size) { 4141 case 0: op = Q ? Iop_Min8Sx16 : Iop_Min8Sx8; break; 4142 case 1: op = Q ? Iop_Min16Sx8 : Iop_Min16Sx4; break; 4143 case 2: op = Q ? Iop_Min32Sx4 : Iop_Min32Sx2; break; 4144 case 3: return False; 4145 default: vassert(0); 4146 } 4147 } else { 4148 switch (size) { 4149 case 0: op = Q ? Iop_Min8Ux16 : Iop_Min8Ux8; break; 4150 case 1: op = Q ? Iop_Min16Ux8 : Iop_Min16Ux4; break; 4151 case 2: op = Q ? Iop_Min32Ux4 : Iop_Min32Ux2; break; 4152 case 3: return False; 4153 default: vassert(0); 4154 } 4155 } 4156 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4157 DIP("vmin.%c%u %c%u, %c%u, %c%u\n", 4158 U ? 'u' : 's', 8 << size, 4159 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4160 mreg); 4161 } 4162 break; 4163 case 7: 4164 if (B == 0) { 4165 /* VABD */ 4166 IROp op_cmp, op_sub; 4167 IRTemp cond; 4168 if ((theInstr >> 23) & 1) { 4169 vpanic("VABDL should not be in dis_neon_data_3same\n"); 4170 } 4171 if (Q) { 4172 switch (size) { 4173 case 0: 4174 op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; 4175 op_sub = Iop_Sub8x16; 4176 break; 4177 case 1: 4178 op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; 4179 op_sub = Iop_Sub16x8; 4180 break; 4181 case 2: 4182 op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; 4183 op_sub = Iop_Sub32x4; 4184 break; 4185 case 3: 4186 return False; 4187 default: 4188 vassert(0); 4189 } 4190 } else { 4191 switch (size) { 4192 case 0: 4193 op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; 4194 op_sub = Iop_Sub8x8; 4195 break; 4196 case 1: 4197 op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; 4198 op_sub = Iop_Sub16x4; 4199 break; 4200 case 2: 4201 op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2; 4202 op_sub = Iop_Sub32x2; 4203 break; 4204 case 3: 4205 return False; 4206 default: 4207 vassert(0); 4208 } 4209 } 4210 if (Q) { 4211 cond = newTemp(Ity_V128); 4212 } else { 4213 cond = newTemp(Ity_I64); 4214 } 4215 assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m))); 4216 assign(res, binop(Q ? Iop_OrV128 : Iop_Or64, 4217 binop(Q ? Iop_AndV128 : Iop_And64, 4218 binop(op_sub, mkexpr(arg_n), 4219 mkexpr(arg_m)), 4220 mkexpr(cond)), 4221 binop(Q ? Iop_AndV128 : Iop_And64, 4222 binop(op_sub, mkexpr(arg_m), 4223 mkexpr(arg_n)), 4224 unop(Q ? Iop_NotV128 : Iop_Not64, 4225 mkexpr(cond))))); 4226 DIP("vabd.%c%u %c%u, %c%u, %c%u\n", 4227 U ? 'u' : 's', 8 << size, 4228 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4229 mreg); 4230 } else { 4231 /* VABA */ 4232 IROp op_cmp, op_sub, op_add; 4233 IRTemp cond, acc, tmp; 4234 if ((theInstr >> 23) & 1) { 4235 vpanic("VABAL should not be in dis_neon_data_3same"); 4236 } 4237 if (Q) { 4238 switch (size) { 4239 case 0: 4240 op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; 4241 op_sub = Iop_Sub8x16; 4242 op_add = Iop_Add8x16; 4243 break; 4244 case 1: 4245 op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; 4246 op_sub = Iop_Sub16x8; 4247 op_add = Iop_Add16x8; 4248 break; 4249 case 2: 4250 op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; 4251 op_sub = Iop_Sub32x4; 4252 op_add = Iop_Add32x4; 4253 break; 4254 case 3: 4255 return False; 4256 default: 4257 vassert(0); 4258 } 4259 } else { 4260 switch (size) { 4261 case 0: 4262 op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; 4263 op_sub = Iop_Sub8x8; 4264 op_add = Iop_Add8x8; 4265 break; 4266 case 1: 4267 op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; 4268 op_sub = Iop_Sub16x4; 4269 op_add = Iop_Add16x4; 4270 break; 4271 case 2: 4272 op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2; 4273 op_sub = Iop_Sub32x2; 4274 op_add = Iop_Add32x2; 4275 break; 4276 case 3: 4277 return False; 4278 default: 4279 vassert(0); 4280 } 4281 } 4282 if (Q) { 4283 cond = newTemp(Ity_V128); 4284 acc = newTemp(Ity_V128); 4285 tmp = newTemp(Ity_V128); 4286 assign(acc, getQReg(dreg)); 4287 } else { 4288 cond = newTemp(Ity_I64); 4289 acc = newTemp(Ity_I64); 4290 tmp = newTemp(Ity_I64); 4291 assign(acc, getDRegI64(dreg)); 4292 } 4293 assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m))); 4294 assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64, 4295 binop(Q ? Iop_AndV128 : Iop_And64, 4296 binop(op_sub, mkexpr(arg_n), 4297 mkexpr(arg_m)), 4298 mkexpr(cond)), 4299 binop(Q ? Iop_AndV128 : Iop_And64, 4300 binop(op_sub, mkexpr(arg_m), 4301 mkexpr(arg_n)), 4302 unop(Q ? Iop_NotV128 : Iop_Not64, 4303 mkexpr(cond))))); 4304 assign(res, binop(op_add, mkexpr(acc), mkexpr(tmp))); 4305 DIP("vaba.%c%u %c%u, %c%u, %c%u\n", 4306 U ? 'u' : 's', 8 << size, 4307 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4308 mreg); 4309 } 4310 break; 4311 case 8: 4312 if (B == 0) { 4313 IROp op; 4314 if (U == 0) { 4315 /* VADD */ 4316 switch (size) { 4317 case 0: op = Q ? Iop_Add8x16 : Iop_Add8x8; break; 4318 case 1: op = Q ? Iop_Add16x8 : Iop_Add16x4; break; 4319 case 2: op = Q ? Iop_Add32x4 : Iop_Add32x2; break; 4320 case 3: op = Q ? Iop_Add64x2 : Iop_Add64; break; 4321 default: vassert(0); 4322 } 4323 DIP("vadd.i%u %c%u, %c%u, %c%u\n", 4324 8 << size, Q ? 'q' : 'd', 4325 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4326 } else { 4327 /* VSUB */ 4328 switch (size) { 4329 case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break; 4330 case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break; 4331 case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break; 4332 case 3: op = Q ? Iop_Sub64x2 : Iop_Sub64; break; 4333 default: vassert(0); 4334 } 4335 DIP("vsub.i%u %c%u, %c%u, %c%u\n", 4336 8 << size, Q ? 'q' : 'd', 4337 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4338 } 4339 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4340 } else { 4341 IROp op; 4342 switch (size) { 4343 case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break; 4344 case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break; 4345 case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break; 4346 case 3: op = Q ? Iop_CmpNEZ64x2 : Iop_CmpwNEZ64; break; 4347 default: vassert(0); 4348 } 4349 if (U == 0) { 4350 /* VTST */ 4351 assign(res, unop(op, binop(Q ? Iop_AndV128 : Iop_And64, 4352 mkexpr(arg_n), 4353 mkexpr(arg_m)))); 4354 DIP("vtst.%u %c%u, %c%u, %c%u\n", 4355 8 << size, Q ? 'q' : 'd', 4356 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4357 } else { 4358 /* VCEQ */ 4359 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64, 4360 unop(op, 4361 binop(Q ? Iop_XorV128 : Iop_Xor64, 4362 mkexpr(arg_n), 4363 mkexpr(arg_m))))); 4364 DIP("vceq.i%u %c%u, %c%u, %c%u\n", 4365 8 << size, Q ? 'q' : 'd', 4366 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4367 } 4368 } 4369 break; 4370 case 9: 4371 if (B == 0) { 4372 /* VMLA, VMLS (integer) */ 4373 IROp op, op2; 4374 UInt P = (theInstr >> 24) & 1; 4375 if (P) { 4376 switch (size) { 4377 case 0: 4378 op = Q ? Iop_Mul8x16 : Iop_Mul8x8; 4379 op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8; 4380 break; 4381 case 1: 4382 op = Q ? Iop_Mul16x8 : Iop_Mul16x4; 4383 op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4; 4384 break; 4385 case 2: 4386 op = Q ? Iop_Mul32x4 : Iop_Mul32x2; 4387 op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2; 4388 break; 4389 case 3: 4390 return False; 4391 default: 4392 vassert(0); 4393 } 4394 } else { 4395 switch (size) { 4396 case 0: 4397 op = Q ? Iop_Mul8x16 : Iop_Mul8x8; 4398 op2 = Q ? Iop_Add8x16 : Iop_Add8x8; 4399 break; 4400 case 1: 4401 op = Q ? Iop_Mul16x8 : Iop_Mul16x4; 4402 op2 = Q ? Iop_Add16x8 : Iop_Add16x4; 4403 break; 4404 case 2: 4405 op = Q ? Iop_Mul32x4 : Iop_Mul32x2; 4406 op2 = Q ? Iop_Add32x4 : Iop_Add32x2; 4407 break; 4408 case 3: 4409 return False; 4410 default: 4411 vassert(0); 4412 } 4413 } 4414 assign(res, binop(op2, 4415 Q ? getQReg(dreg) : getDRegI64(dreg), 4416 binop(op, mkexpr(arg_n), mkexpr(arg_m)))); 4417 DIP("vml%c.i%u %c%u, %c%u, %c%u\n", 4418 P ? 's' : 'a', 8 << size, 4419 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4420 mreg); 4421 } else { 4422 /* VMUL */ 4423 IROp op; 4424 UInt P = (theInstr >> 24) & 1; 4425 if (P) { 4426 switch (size) { 4427 case 0: 4428 op = Q ? Iop_PolynomialMul8x16 : Iop_PolynomialMul8x8; 4429 break; 4430 case 1: case 2: case 3: return False; 4431 default: vassert(0); 4432 } 4433 } else { 4434 switch (size) { 4435 case 0: op = Q ? Iop_Mul8x16 : Iop_Mul8x8; break; 4436 case 1: op = Q ? Iop_Mul16x8 : Iop_Mul16x4; break; 4437 case 2: op = Q ? Iop_Mul32x4 : Iop_Mul32x2; break; 4438 case 3: return False; 4439 default: vassert(0); 4440 } 4441 } 4442 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4443 DIP("vmul.%c%u %c%u, %c%u, %c%u\n", 4444 P ? 'p' : 'i', 8 << size, 4445 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', 4446 mreg); 4447 } 4448 break; 4449 case 10: { 4450 /* VPMAX, VPMIN */ 4451 UInt P = (theInstr >> 4) & 1; 4452 IROp op; 4453 if (Q) 4454 return False; 4455 if (P) { 4456 switch (size) { 4457 case 0: op = U ? Iop_PwMin8Ux8 : Iop_PwMin8Sx8; break; 4458 case 1: op = U ? Iop_PwMin16Ux4 : Iop_PwMin16Sx4; break; 4459 case 2: op = U ? Iop_PwMin32Ux2 : Iop_PwMin32Sx2; break; 4460 case 3: return False; 4461 default: vassert(0); 4462 } 4463 } else { 4464 switch (size) { 4465 case 0: op = U ? Iop_PwMax8Ux8 : Iop_PwMax8Sx8; break; 4466 case 1: op = U ? Iop_PwMax16Ux4 : Iop_PwMax16Sx4; break; 4467 case 2: op = U ? Iop_PwMax32Ux2 : Iop_PwMax32Sx2; break; 4468 case 3: return False; 4469 default: vassert(0); 4470 } 4471 } 4472 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4473 DIP("vp%s.%c%u %c%u, %c%u, %c%u\n", 4474 P ? "min" : "max", U ? 'u' : 's', 4475 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, 4476 Q ? 'q' : 'd', mreg); 4477 break; 4478 } 4479 case 11: 4480 if (B == 0) { 4481 if (U == 0) { 4482 /* VQDMULH */ 4483 IROp op ,op2; 4484 ULong imm; 4485 switch (size) { 4486 case 0: case 3: 4487 return False; 4488 case 1: 4489 op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4; 4490 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4; 4491 imm = 1LL << 15; 4492 imm = (imm << 16) | imm; 4493 imm = (imm << 32) | imm; 4494 break; 4495 case 2: 4496 op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2; 4497 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2; 4498 imm = 1LL << 31; 4499 imm = (imm << 32) | imm; 4500 break; 4501 default: 4502 vassert(0); 4503 } 4504 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4505 #ifndef DISABLE_QC_FLAG 4506 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 4507 binop(op2, mkexpr(arg_n), 4508 Q ? mkU128(imm) : mkU64(imm)), 4509 binop(op2, mkexpr(arg_m), 4510 Q ? mkU128(imm) : mkU64(imm))), 4511 Q ? mkU128(0) : mkU64(0), 4512 Q, condT); 4513 #endif 4514 DIP("vqdmulh.s%u %c%u, %c%u, %c%u\n", 4515 8 << size, Q ? 'q' : 'd', 4516 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4517 } else { 4518 /* VQRDMULH */ 4519 IROp op ,op2; 4520 ULong imm; 4521 switch(size) { 4522 case 0: case 3: 4523 return False; 4524 case 1: 4525 imm = 1LL << 15; 4526 imm = (imm << 16) | imm; 4527 imm = (imm << 32) | imm; 4528 op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4; 4529 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4; 4530 break; 4531 case 2: 4532 imm = 1LL << 31; 4533 imm = (imm << 32) | imm; 4534 op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2; 4535 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2; 4536 break; 4537 default: 4538 vassert(0); 4539 } 4540 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4541 #ifndef DISABLE_QC_FLAG 4542 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 4543 binop(op2, mkexpr(arg_n), 4544 Q ? mkU128(imm) : mkU64(imm)), 4545 binop(op2, mkexpr(arg_m), 4546 Q ? mkU128(imm) : mkU64(imm))), 4547 Q ? mkU128(0) : mkU64(0), 4548 Q, condT); 4549 #endif 4550 DIP("vqrdmulh.s%u %c%u, %c%u, %c%u\n", 4551 8 << size, Q ? 'q' : 'd', 4552 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4553 } 4554 } else { 4555 if (U == 0) { 4556 /* VPADD */ 4557 IROp op; 4558 if (Q) 4559 return False; 4560 switch (size) { 4561 case 0: op = Q ? Iop_PwAdd8x16 : Iop_PwAdd8x8; break; 4562 case 1: op = Q ? Iop_PwAdd16x8 : Iop_PwAdd16x4; break; 4563 case 2: op = Q ? Iop_PwAdd32x4 : Iop_PwAdd32x2; break; 4564 case 3: return False; 4565 default: vassert(0); 4566 } 4567 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4568 DIP("vpadd.i%d %c%u, %c%u, %c%u\n", 4569 8 << size, Q ? 'q' : 'd', 4570 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4571 } 4572 } 4573 break; 4574 /* Starting from here these are FP SIMD cases */ 4575 case 13: 4576 if (B == 0) { 4577 IROp op; 4578 if (U == 0) { 4579 if ((C >> 1) == 0) { 4580 /* VADD */ 4581 op = Q ? Iop_Add32Fx4 : Iop_Add32Fx2 ; 4582 DIP("vadd.f32 %c%u, %c%u, %c%u\n", 4583 Q ? 'q' : 'd', dreg, 4584 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4585 } else { 4586 /* VSUB */ 4587 op = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2 ; 4588 DIP("vsub.f32 %c%u, %c%u, %c%u\n", 4589 Q ? 'q' : 'd', dreg, 4590 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4591 } 4592 } else { 4593 if ((C >> 1) == 0) { 4594 /* VPADD */ 4595 if (Q) 4596 return False; 4597 op = Iop_PwAdd32Fx2; 4598 DIP("vpadd.f32 d%u, d%u, d%u\n", dreg, nreg, mreg); 4599 } else { 4600 /* VABD */ 4601 if (Q) { 4602 assign(res, unop(Iop_Abs32Fx4, 4603 binop(Iop_Sub32Fx4, 4604 mkexpr(arg_n), 4605 mkexpr(arg_m)))); 4606 } else { 4607 assign(res, unop(Iop_Abs32Fx2, 4608 binop(Iop_Sub32Fx2, 4609 mkexpr(arg_n), 4610 mkexpr(arg_m)))); 4611 } 4612 DIP("vabd.f32 %c%u, %c%u, %c%u\n", 4613 Q ? 'q' : 'd', dreg, 4614 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4615 break; 4616 } 4617 } 4618 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4619 } else { 4620 if (U == 0) { 4621 /* VMLA, VMLS */ 4622 IROp op, op2; 4623 UInt P = (theInstr >> 21) & 1; 4624 if (P) { 4625 switch (size & 1) { 4626 case 0: 4627 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2; 4628 op2 = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2; 4629 break; 4630 case 1: return False; 4631 default: vassert(0); 4632 } 4633 } else { 4634 switch (size & 1) { 4635 case 0: 4636 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2; 4637 op2 = Q ? Iop_Add32Fx4 : Iop_Add32Fx2; 4638 break; 4639 case 1: return False; 4640 default: vassert(0); 4641 } 4642 } 4643 assign(res, binop(op2, 4644 Q ? getQReg(dreg) : getDRegI64(dreg), 4645 binop(op, mkexpr(arg_n), mkexpr(arg_m)))); 4646 4647 DIP("vml%c.f32 %c%u, %c%u, %c%u\n", 4648 P ? 's' : 'a', Q ? 'q' : 'd', 4649 dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4650 } else { 4651 /* VMUL */ 4652 IROp op; 4653 if ((C >> 1) != 0) 4654 return False; 4655 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2 ; 4656 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4657 DIP("vmul.f32 %c%u, %c%u, %c%u\n", 4658 Q ? 'q' : 'd', dreg, 4659 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4660 } 4661 } 4662 break; 4663 case 14: 4664 if (B == 0) { 4665 if (U == 0) { 4666 if ((C >> 1) == 0) { 4667 /* VCEQ */ 4668 IROp op; 4669 if ((theInstr >> 20) & 1) 4670 return False; 4671 op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2; 4672 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4673 DIP("vceq.f32 %c%u, %c%u, %c%u\n", 4674 Q ? 'q' : 'd', dreg, 4675 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4676 } else { 4677 return False; 4678 } 4679 } else { 4680 if ((C >> 1) == 0) { 4681 /* VCGE */ 4682 IROp op; 4683 if ((theInstr >> 20) & 1) 4684 return False; 4685 op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; 4686 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4687 DIP("vcge.f32 %c%u, %c%u, %c%u\n", 4688 Q ? 'q' : 'd', dreg, 4689 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4690 } else { 4691 /* VCGT */ 4692 IROp op; 4693 if ((theInstr >> 20) & 1) 4694 return False; 4695 op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; 4696 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4697 DIP("vcgt.f32 %c%u, %c%u, %c%u\n", 4698 Q ? 'q' : 'd', dreg, 4699 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4700 } 4701 } 4702 } else { 4703 if (U == 1) { 4704 /* VACGE, VACGT */ 4705 UInt op_bit = (theInstr >> 21) & 1; 4706 IROp op, op2; 4707 op2 = Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2; 4708 if (op_bit) { 4709 op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; 4710 assign(res, binop(op, 4711 unop(op2, mkexpr(arg_n)), 4712 unop(op2, mkexpr(arg_m)))); 4713 } else { 4714 op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; 4715 assign(res, binop(op, 4716 unop(op2, mkexpr(arg_n)), 4717 unop(op2, mkexpr(arg_m)))); 4718 } 4719 DIP("vacg%c.f32 %c%u, %c%u, %c%u\n", op_bit ? 't' : 'e', 4720 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, 4721 Q ? 'q' : 'd', mreg); 4722 } 4723 } 4724 break; 4725 case 15: 4726 if (B == 0) { 4727 if (U == 0) { 4728 /* VMAX, VMIN */ 4729 IROp op; 4730 if ((theInstr >> 20) & 1) 4731 return False; 4732 if ((theInstr >> 21) & 1) { 4733 op = Q ? Iop_Min32Fx4 : Iop_Min32Fx2; 4734 DIP("vmin.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg, 4735 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4736 } else { 4737 op = Q ? Iop_Max32Fx4 : Iop_Max32Fx2; 4738 DIP("vmax.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg, 4739 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4740 } 4741 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4742 } else { 4743 /* VPMAX, VPMIN */ 4744 IROp op; 4745 if (Q) 4746 return False; 4747 if ((theInstr >> 20) & 1) 4748 return False; 4749 if ((theInstr >> 21) & 1) { 4750 op = Iop_PwMin32Fx2; 4751 DIP("vpmin.f32 d%u, d%u, d%u\n", dreg, nreg, mreg); 4752 } else { 4753 op = Iop_PwMax32Fx2; 4754 DIP("vpmax.f32 d%u, d%u, d%u\n", dreg, nreg, mreg); 4755 } 4756 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 4757 } 4758 } else { 4759 if (U == 0) { 4760 if ((C >> 1) == 0) { 4761 /* VRECPS */ 4762 if ((theInstr >> 20) & 1) 4763 return False; 4764 assign(res, binop(Q ? Iop_Recps32Fx4 : Iop_Recps32Fx2, 4765 mkexpr(arg_n), 4766 mkexpr(arg_m))); 4767 DIP("vrecps.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg, 4768 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4769 } else { 4770 /* VRSQRTS */ 4771 if ((theInstr >> 20) & 1) 4772 return False; 4773 assign(res, binop(Q ? Iop_Rsqrts32Fx4 : Iop_Rsqrts32Fx2, 4774 mkexpr(arg_n), 4775 mkexpr(arg_m))); 4776 DIP("vrsqrts.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg, 4777 Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg); 4778 } 4779 } 4780 } 4781 break; 4782 } 4783 4784 if (Q) { 4785 putQReg(dreg, mkexpr(res), condT); 4786 } else { 4787 putDRegI64(dreg, mkexpr(res), condT); 4788 } 4789 4790 return True; 4791 } 4792 4793 /* A7.4.2 Three registers of different length */ 4794 static 4795 Bool dis_neon_data_3diff ( UInt theInstr, IRTemp condT ) 4796 { 4797 UInt A = (theInstr >> 8) & 0xf; 4798 UInt B = (theInstr >> 20) & 3; 4799 UInt U = (theInstr >> 24) & 1; 4800 UInt P = (theInstr >> 9) & 1; 4801 UInt mreg = get_neon_m_regno(theInstr); 4802 UInt nreg = get_neon_n_regno(theInstr); 4803 UInt dreg = get_neon_d_regno(theInstr); 4804 UInt size = B; 4805 ULong imm; 4806 IRTemp res, arg_m, arg_n, cond, tmp; 4807 IROp cvt, cvt2, cmp, op, op2, sh, add; 4808 switch (A) { 4809 case 0: case 1: case 2: case 3: 4810 /* VADDL, VADDW, VSUBL, VSUBW */ 4811 if (dreg & 1) 4812 return False; 4813 dreg >>= 1; 4814 size = B; 4815 switch (size) { 4816 case 0: 4817 cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8; 4818 op = (A & 2) ? Iop_Sub16x8 : Iop_Add16x8; 4819 break; 4820 case 1: 4821 cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4; 4822 op = (A & 2) ? Iop_Sub32x4 : Iop_Add32x4; 4823 break; 4824 case 2: 4825 cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2; 4826 op = (A & 2) ? Iop_Sub64x2 : Iop_Add64x2; 4827 break; 4828 case 3: 4829 return False; 4830 default: 4831 vassert(0); 4832 } 4833 arg_n = newTemp(Ity_V128); 4834 arg_m = newTemp(Ity_V128); 4835 if (A & 1) { 4836 if (nreg & 1) 4837 return False; 4838 nreg >>= 1; 4839 assign(arg_n, getQReg(nreg)); 4840 } else { 4841 assign(arg_n, unop(cvt, getDRegI64(nreg))); 4842 } 4843 assign(arg_m, unop(cvt, getDRegI64(mreg))); 4844 putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)), 4845 condT); 4846 DIP("v%s%c.%c%u q%u, %c%u, d%u\n", (A & 2) ? "sub" : "add", 4847 (A & 1) ? 'w' : 'l', U ? 'u' : 's', 8 << size, dreg, 4848 (A & 1) ? 'q' : 'd', nreg, mreg); 4849 return True; 4850 case 4: 4851 /* VADDHN, VRADDHN */ 4852 if (mreg & 1) 4853 return False; 4854 mreg >>= 1; 4855 if (nreg & 1) 4856 return False; 4857 nreg >>= 1; 4858 size = B; 4859 switch (size) { 4860 case 0: 4861 op = Iop_Add16x8; 4862 cvt = Iop_Shorten16x8; 4863 sh = Iop_ShrN16x8; 4864 imm = 1U << 7; 4865 imm = (imm << 16) | imm; 4866 imm = (imm << 32) | imm; 4867 break; 4868 case 1: 4869 op = Iop_Add32x4; 4870 cvt = Iop_Shorten32x4; 4871 sh = Iop_ShrN32x4; 4872 imm = 1U << 15; 4873 imm = (imm << 32) | imm; 4874 break; 4875 case 2: 4876 op = Iop_Add64x2; 4877 cvt = Iop_Shorten64x2; 4878 sh = Iop_ShrN64x2; 4879 imm = 1U << 31; 4880 break; 4881 case 3: 4882 return False; 4883 default: 4884 vassert(0); 4885 } 4886 tmp = newTemp(Ity_V128); 4887 res = newTemp(Ity_V128); 4888 assign(tmp, binop(op, getQReg(nreg), getQReg(mreg))); 4889 if (U) { 4890 /* VRADDHN */ 4891 assign(res, binop(op, mkexpr(tmp), 4892 binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)))); 4893 } else { 4894 assign(res, mkexpr(tmp)); 4895 } 4896 putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))), 4897 condT); 4898 DIP("v%saddhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg, 4899 nreg, mreg); 4900 return True; 4901 case 5: 4902 /* VABAL */ 4903 if (!((theInstr >> 23) & 1)) { 4904 vpanic("VABA should not be in dis_neon_data_3diff\n"); 4905 } 4906 if (dreg & 1) 4907 return False; 4908 dreg >>= 1; 4909 switch (size) { 4910 case 0: 4911 cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; 4912 cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8; 4913 cvt2 = Iop_Longen8Sx8; 4914 op = Iop_Sub16x8; 4915 op2 = Iop_Add16x8; 4916 break; 4917 case 1: 4918 cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; 4919 cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4; 4920 cvt2 = Iop_Longen16Sx4; 4921 op = Iop_Sub32x4; 4922 op2 = Iop_Add32x4; 4923 break; 4924 case 2: 4925 cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2; 4926 cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2; 4927 cvt2 = Iop_Longen32Sx2; 4928 op = Iop_Sub64x2; 4929 op2 = Iop_Add64x2; 4930 break; 4931 case 3: 4932 return False; 4933 default: 4934 vassert(0); 4935 } 4936 arg_n = newTemp(Ity_V128); 4937 arg_m = newTemp(Ity_V128); 4938 cond = newTemp(Ity_V128); 4939 res = newTemp(Ity_V128); 4940 assign(arg_n, unop(cvt, getDRegI64(nreg))); 4941 assign(arg_m, unop(cvt, getDRegI64(mreg))); 4942 assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg), 4943 getDRegI64(mreg)))); 4944 assign(res, binop(op2, 4945 binop(Iop_OrV128, 4946 binop(Iop_AndV128, 4947 binop(op, mkexpr(arg_n), mkexpr(arg_m)), 4948 mkexpr(cond)), 4949 binop(Iop_AndV128, 4950 binop(op, mkexpr(arg_m), mkexpr(arg_n)), 4951 unop(Iop_NotV128, mkexpr(cond)))), 4952 getQReg(dreg))); 4953 putQReg(dreg, mkexpr(res), condT); 4954 DIP("vabal.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg, 4955 nreg, mreg); 4956 return True; 4957 case 6: 4958 /* VSUBHN, VRSUBHN */ 4959 if (mreg & 1) 4960 return False; 4961 mreg >>= 1; 4962 if (nreg & 1) 4963 return False; 4964 nreg >>= 1; 4965 size = B; 4966 switch (size) { 4967 case 0: 4968 op = Iop_Sub16x8; 4969 op2 = Iop_Add16x8; 4970 cvt = Iop_Shorten16x8; 4971 sh = Iop_ShrN16x8; 4972 imm = 1U << 7; 4973 imm = (imm << 16) | imm; 4974 imm = (imm << 32) | imm; 4975 break; 4976 case 1: 4977 op = Iop_Sub32x4; 4978 op2 = Iop_Add32x4; 4979 cvt = Iop_Shorten32x4; 4980 sh = Iop_ShrN32x4; 4981 imm = 1U << 15; 4982 imm = (imm << 32) | imm; 4983 break; 4984 case 2: 4985 op = Iop_Sub64x2; 4986 op2 = Iop_Add64x2; 4987 cvt = Iop_Shorten64x2; 4988 sh = Iop_ShrN64x2; 4989 imm = 1U << 31; 4990 break; 4991 case 3: 4992 return False; 4993 default: 4994 vassert(0); 4995 } 4996 tmp = newTemp(Ity_V128); 4997 res = newTemp(Ity_V128); 4998 assign(tmp, binop(op, getQReg(nreg), getQReg(mreg))); 4999 if (U) { 5000 /* VRSUBHN */ 5001 assign(res, binop(op2, mkexpr(tmp), 5002 binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)))); 5003 } else { 5004 assign(res, mkexpr(tmp)); 5005 } 5006 putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))), 5007 condT); 5008 DIP("v%ssubhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg, 5009 nreg, mreg); 5010 return True; 5011 case 7: 5012 /* VABDL */ 5013 if (!((theInstr >> 23) & 1)) { 5014 vpanic("VABL should not be in dis_neon_data_3diff\n"); 5015 } 5016 if (dreg & 1) 5017 return False; 5018 dreg >>= 1; 5019 switch (size) { 5020 case 0: 5021 cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; 5022 cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8; 5023 cvt2 = Iop_Longen8Sx8; 5024 op = Iop_Sub16x8; 5025 break; 5026 case 1: 5027 cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; 5028 cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4; 5029 cvt2 = Iop_Longen16Sx4; 5030 op = Iop_Sub32x4; 5031 break; 5032 case 2: 5033 cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2; 5034 cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2; 5035 cvt2 = Iop_Longen32Sx2; 5036 op = Iop_Sub64x2; 5037 break; 5038 case 3: 5039 return False; 5040 default: 5041 vassert(0); 5042 } 5043 arg_n = newTemp(Ity_V128); 5044 arg_m = newTemp(Ity_V128); 5045 cond = newTemp(Ity_V128); 5046 res = newTemp(Ity_V128); 5047 assign(arg_n, unop(cvt, getDRegI64(nreg))); 5048 assign(arg_m, unop(cvt, getDRegI64(mreg))); 5049 assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg), 5050 getDRegI64(mreg)))); 5051 assign(res, binop(Iop_OrV128, 5052 binop(Iop_AndV128, 5053 binop(op, mkexpr(arg_n), mkexpr(arg_m)), 5054 mkexpr(cond)), 5055 binop(Iop_AndV128, 5056 binop(op, mkexpr(arg_m), mkexpr(arg_n)), 5057 unop(Iop_NotV128, mkexpr(cond))))); 5058 putQReg(dreg, mkexpr(res), condT); 5059 DIP("vabdl.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg, 5060 nreg, mreg); 5061 return True; 5062 case 8: 5063 case 10: 5064 /* VMLAL, VMLSL (integer) */ 5065 if (dreg & 1) 5066 return False; 5067 dreg >>= 1; 5068 size = B; 5069 switch (size) { 5070 case 0: 5071 op = U ? Iop_Mull8Ux8 : Iop_Mull8Sx8; 5072 op2 = P ? Iop_Sub16x8 : Iop_Add16x8; 5073 break; 5074 case 1: 5075 op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; 5076 op2 = P ? Iop_Sub32x4 : Iop_Add32x4; 5077 break; 5078 case 2: 5079 op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; 5080 op2 = P ? Iop_Sub64x2 : Iop_Add64x2; 5081 break; 5082 case 3: 5083 return False; 5084 default: 5085 vassert(0); 5086 } 5087 res = newTemp(Ity_V128); 5088 assign(res, binop(op, getDRegI64(nreg),getDRegI64(mreg))); 5089 putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT); 5090 DIP("vml%cl.%c%u q%u, d%u, d%u\n", P ? 's' : 'a', U ? 'u' : 's', 5091 8 << size, dreg, nreg, mreg); 5092 return True; 5093 case 9: 5094 case 11: 5095 /* VQDMLAL, VQDMLSL */ 5096 if (U) 5097 return False; 5098 if (dreg & 1) 5099 return False; 5100 dreg >>= 1; 5101 size = B; 5102 switch (size) { 5103 case 0: case 3: 5104 return False; 5105 case 1: 5106 op = Iop_QDMulLong16Sx4; 5107 cmp = Iop_CmpEQ16x4; 5108 add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4; 5109 op2 = P ? Iop_Sub32x4 : Iop_Add32x4; 5110 imm = 1LL << 15; 5111 imm = (imm << 16) | imm; 5112 imm = (imm << 32) | imm; 5113 break; 5114 case 2: 5115 op = Iop_QDMulLong32Sx2; 5116 cmp = Iop_CmpEQ32x2; 5117 add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2; 5118 op2 = P ? Iop_Sub64x2 : Iop_Add64x2; 5119 imm = 1LL << 31; 5120 imm = (imm << 32) | imm; 5121 break; 5122 default: 5123 vassert(0); 5124 } 5125 res = newTemp(Ity_V128); 5126 tmp = newTemp(Ity_V128); 5127 assign(res, binop(op, getDRegI64(nreg), getDRegI64(mreg))); 5128 #ifndef DISABLE_QC_FLAG 5129 assign(tmp, binop(op2, getQReg(dreg), mkexpr(res))); 5130 setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)), 5131 True, condT); 5132 setFlag_QC(binop(Iop_And64, 5133 binop(cmp, getDRegI64(nreg), mkU64(imm)), 5134 binop(cmp, getDRegI64(mreg), mkU64(imm))), 5135 mkU64(0), 5136 False, condT); 5137 #endif 5138 putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT); 5139 DIP("vqdml%cl.s%u q%u, d%u, d%u\n", P ? 's' : 'a', 8 << size, dreg, 5140 nreg, mreg); 5141 return True; 5142 case 12: 5143 case 14: 5144 /* VMULL (integer or polynomial) */ 5145 if (dreg & 1) 5146 return False; 5147 dreg >>= 1; 5148 size = B; 5149 switch (size) { 5150 case 0: 5151 op = (U) ? Iop_Mull8Ux8 : Iop_Mull8Sx8; 5152 if (P) 5153 op = Iop_PolynomialMull8x8; 5154 break; 5155 case 1: 5156 op = (U) ? Iop_Mull16Ux4 : Iop_Mull16Sx4; 5157 break; 5158 case 2: 5159 op = (U) ? Iop_Mull32Ux2 : Iop_Mull32Sx2; 5160 break; 5161 default: 5162 vassert(0); 5163 } 5164 putQReg(dreg, binop(op, getDRegI64(nreg), 5165 getDRegI64(mreg)), condT); 5166 DIP("vmull.%c%u q%u, d%u, d%u\n", P ? 'p' : (U ? 'u' : 's'), 5167 8 << size, dreg, nreg, mreg); 5168 return True; 5169 case 13: 5170 /* VQDMULL */ 5171 if (U) 5172 return False; 5173 if (dreg & 1) 5174 return False; 5175 dreg >>= 1; 5176 size = B; 5177 switch (size) { 5178 case 0: 5179 case 3: 5180 return False; 5181 case 1: 5182 op = Iop_QDMulLong16Sx4; 5183 op2 = Iop_CmpEQ16x4; 5184 imm = 1LL << 15; 5185 imm = (imm << 16) | imm; 5186 imm = (imm << 32) | imm; 5187 break; 5188 case 2: 5189 op = Iop_QDMulLong32Sx2; 5190 op2 = Iop_CmpEQ32x2; 5191 imm = 1LL << 31; 5192 imm = (imm << 32) | imm; 5193 break; 5194 default: 5195 vassert(0); 5196 } 5197 putQReg(dreg, binop(op, getDRegI64(nreg), getDRegI64(mreg)), 5198 condT); 5199 #ifndef DISABLE_QC_FLAG 5200 setFlag_QC(binop(Iop_And64, 5201 binop(op2, getDRegI64(nreg), mkU64(imm)), 5202 binop(op2, getDRegI64(mreg), mkU64(imm))), 5203 mkU64(0), 5204 False, condT); 5205 #endif 5206 DIP("vqdmull.s%u q%u, d%u, d%u\n", 8 << size, dreg, nreg, mreg); 5207 return True; 5208 default: 5209 return False; 5210 } 5211 return False; 5212 } 5213 5214 /* A7.4.3 Two registers and a scalar */ 5215 static 5216 Bool dis_neon_data_2reg_and_scalar ( UInt theInstr, IRTemp condT ) 5217 { 5218 # define INSN(_bMax,_bMin) SLICE_UInt(theInstr, (_bMax), (_bMin)) 5219 UInt U = INSN(24,24); 5220 UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6)); 5221 UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6)); 5222 UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6)); 5223 UInt size = INSN(21,20); 5224 UInt index; 5225 UInt Q = INSN(24,24); 5226 5227 if (INSN(27,25) != 1 || INSN(23,23) != 1 5228 || INSN(6,6) != 1 || INSN(4,4) != 0) 5229 return False; 5230 5231 /* VMLA, VMLS (scalar) */ 5232 if ((INSN(11,8) & BITS4(1,0,1,0)) == BITS4(0,0,0,0)) { 5233 IRTemp res, arg_m, arg_n; 5234 IROp dup, get, op, op2, add, sub; 5235 if (Q) { 5236 if ((dreg & 1) || (nreg & 1)) 5237 return False; 5238 dreg >>= 1; 5239 nreg >>= 1; 5240 res = newTemp(Ity_V128); 5241 arg_m = newTemp(Ity_V128); 5242 arg_n = newTemp(Ity_V128); 5243 assign(arg_n, getQReg(nreg)); 5244 switch(size) { 5245 case 1: 5246 dup = Iop_Dup16x8; 5247 get = Iop_GetElem16x4; 5248 index = mreg >> 3; 5249 mreg &= 7; 5250 break; 5251 case 2: 5252 dup = Iop_Dup32x4; 5253 get = Iop_GetElem32x2; 5254 index = mreg >> 4; 5255 mreg &= 0xf; 5256 break; 5257 case 0: 5258 case 3: 5259 return False; 5260 default: 5261 vassert(0); 5262 } 5263 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5264 } else { 5265 res = newTemp(Ity_I64); 5266 arg_m = newTemp(Ity_I64); 5267 arg_n = newTemp(Ity_I64); 5268 assign(arg_n, getDRegI64(nreg)); 5269 switch(size) { 5270 case 1: 5271 dup = Iop_Dup16x4; 5272 get = Iop_GetElem16x4; 5273 index = mreg >> 3; 5274 mreg &= 7; 5275 break; 5276 case 2: 5277 dup = Iop_Dup32x2; 5278 get = Iop_GetElem32x2; 5279 index = mreg >> 4; 5280 mreg &= 0xf; 5281 break; 5282 case 0: 5283 case 3: 5284 return False; 5285 default: 5286 vassert(0); 5287 } 5288 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5289 } 5290 if (INSN(8,8)) { 5291 switch (size) { 5292 case 2: 5293 op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2; 5294 add = Q ? Iop_Add32Fx4 : Iop_Add32Fx2; 5295 sub = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2; 5296 break; 5297 case 0: 5298 case 1: 5299 case 3: 5300 return False; 5301 default: 5302 vassert(0); 5303 } 5304 } else { 5305 switch (size) { 5306 case 1: 5307 op = Q ? Iop_Mul16x8 : Iop_Mul16x4; 5308 add = Q ? Iop_Add16x8 : Iop_Add16x4; 5309 sub = Q ? Iop_Sub16x8 : Iop_Sub16x4; 5310 break; 5311 case 2: 5312 op = Q ? Iop_Mul32x4 : Iop_Mul32x2; 5313 add = Q ? Iop_Add32x4 : Iop_Add32x2; 5314 sub = Q ? Iop_Sub32x4 : Iop_Sub32x2; 5315 break; 5316 case 0: 5317 case 3: 5318 return False; 5319 default: 5320 vassert(0); 5321 } 5322 } 5323 op2 = INSN(10,10) ? sub : add; 5324 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5325 if (Q) 5326 putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), 5327 condT); 5328 else 5329 putDRegI64(dreg, binop(op2, getDRegI64(dreg), mkexpr(res)), 5330 condT); 5331 DIP("vml%c.%c%u %c%u, %c%u, d%u[%u]\n", INSN(10,10) ? 's' : 'a', 5332 INSN(8,8) ? 'f' : 'i', 8 << size, 5333 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, mreg, index); 5334 return True; 5335 } 5336 5337 /* VMLAL, VMLSL (scalar) */ 5338 if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,0)) { 5339 IRTemp res, arg_m, arg_n; 5340 IROp dup, get, op, op2, add, sub; 5341 if (dreg & 1) 5342 return False; 5343 dreg >>= 1; 5344 res = newTemp(Ity_V128); 5345 arg_m = newTemp(Ity_I64); 5346 arg_n = newTemp(Ity_I64); 5347 assign(arg_n, getDRegI64(nreg)); 5348 switch(size) { 5349 case 1: 5350 dup = Iop_Dup16x4; 5351 get = Iop_GetElem16x4; 5352 index = mreg >> 3; 5353 mreg &= 7; 5354 break; 5355 case 2: 5356 dup = Iop_Dup32x2; 5357 get = Iop_GetElem32x2; 5358 index = mreg >> 4; 5359 mreg &= 0xf; 5360 break; 5361 case 0: 5362 case 3: 5363 return False; 5364 default: 5365 vassert(0); 5366 } 5367 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5368 switch (size) { 5369 case 1: 5370 op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; 5371 add = Iop_Add32x4; 5372 sub = Iop_Sub32x4; 5373 break; 5374 case 2: 5375 op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; 5376 add = Iop_Add64x2; 5377 sub = Iop_Sub64x2; 5378 break; 5379 case 0: 5380 case 3: 5381 return False; 5382 default: 5383 vassert(0); 5384 } 5385 op2 = INSN(10,10) ? sub : add; 5386 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5387 putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT); 5388 DIP("vml%cl.%c%u q%u, d%u, d%u[%u]\n", 5389 INSN(10,10) ? 's' : 'a', U ? 'u' : 's', 5390 8 << size, dreg, nreg, mreg, index); 5391 return True; 5392 } 5393 5394 /* VQDMLAL, VQDMLSL (scalar) */ 5395 if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,1) && !U) { 5396 IRTemp res, arg_m, arg_n, tmp; 5397 IROp dup, get, op, op2, add, cmp; 5398 UInt P = INSN(10,10); 5399 ULong imm; 5400 if (dreg & 1) 5401 return False; 5402 dreg >>= 1; 5403 res = newTemp(Ity_V128); 5404 arg_m = newTemp(Ity_I64); 5405 arg_n = newTemp(Ity_I64); 5406 assign(arg_n, getDRegI64(nreg)); 5407 switch(size) { 5408 case 1: 5409 dup = Iop_Dup16x4; 5410 get = Iop_GetElem16x4; 5411 index = mreg >> 3; 5412 mreg &= 7; 5413 break; 5414 case 2: 5415 dup = Iop_Dup32x2; 5416 get = Iop_GetElem32x2; 5417 index = mreg >> 4; 5418 mreg &= 0xf; 5419 break; 5420 case 0: 5421 case 3: 5422 return False; 5423 default: 5424 vassert(0); 5425 } 5426 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5427 switch (size) { 5428 case 0: 5429 case 3: 5430 return False; 5431 case 1: 5432 op = Iop_QDMulLong16Sx4; 5433 cmp = Iop_CmpEQ16x4; 5434 add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4; 5435 op2 = P ? Iop_Sub32x4 : Iop_Add32x4; 5436 imm = 1LL << 15; 5437 imm = (imm << 16) | imm; 5438 imm = (imm << 32) | imm; 5439 break; 5440 case 2: 5441 op = Iop_QDMulLong32Sx2; 5442 cmp = Iop_CmpEQ32x2; 5443 add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2; 5444 op2 = P ? Iop_Sub64x2 : Iop_Add64x2; 5445 imm = 1LL << 31; 5446 imm = (imm << 32) | imm; 5447 break; 5448 default: 5449 vassert(0); 5450 } 5451 res = newTemp(Ity_V128); 5452 tmp = newTemp(Ity_V128); 5453 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5454 #ifndef DISABLE_QC_FLAG 5455 assign(tmp, binop(op2, getQReg(dreg), mkexpr(res))); 5456 setFlag_QC(binop(Iop_And64, 5457 binop(cmp, mkexpr(arg_n), mkU64(imm)), 5458 binop(cmp, mkexpr(arg_m), mkU64(imm))), 5459 mkU64(0), 5460 False, condT); 5461 setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)), 5462 True, condT); 5463 #endif 5464 putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT); 5465 DIP("vqdml%cl.s%u q%u, d%u, d%u[%u]\n", P ? 's' : 'a', 8 << size, 5466 dreg, nreg, mreg, index); 5467 return True; 5468 } 5469 5470 /* VMUL (by scalar) */ 5471 if ((INSN(11,8) & BITS4(1,1,1,0)) == BITS4(1,0,0,0)) { 5472 IRTemp res, arg_m, arg_n; 5473 IROp dup, get, op; 5474 if (Q) { 5475 if ((dreg & 1) || (nreg & 1)) 5476 return False; 5477 dreg >>= 1; 5478 nreg >>= 1; 5479 res = newTemp(Ity_V128); 5480 arg_m = newTemp(Ity_V128); 5481 arg_n = newTemp(Ity_V128); 5482 assign(arg_n, getQReg(nreg)); 5483 switch(size) { 5484 case 1: 5485 dup = Iop_Dup16x8; 5486 get = Iop_GetElem16x4; 5487 index = mreg >> 3; 5488 mreg &= 7; 5489 break; 5490 case 2: 5491 dup = Iop_Dup32x4; 5492 get = Iop_GetElem32x2; 5493 index = mreg >> 4; 5494 mreg &= 0xf; 5495 break; 5496 case 0: 5497 case 3: 5498 return False; 5499 default: 5500 vassert(0); 5501 } 5502 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5503 } else { 5504 res = newTemp(Ity_I64); 5505 arg_m = newTemp(Ity_I64); 5506 arg_n = newTemp(Ity_I64); 5507 assign(arg_n, getDRegI64(nreg)); 5508 switch(size) { 5509 case 1: 5510 dup = Iop_Dup16x4; 5511 get = Iop_GetElem16x4; 5512 index = mreg >> 3; 5513 mreg &= 7; 5514 break; 5515 case 2: 5516 dup = Iop_Dup32x2; 5517 get = Iop_GetElem32x2; 5518 index = mreg >> 4; 5519 mreg &= 0xf; 5520 break; 5521 case 0: 5522 case 3: 5523 return False; 5524 default: 5525 vassert(0); 5526 } 5527 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5528 } 5529 switch (size) { 5530 case 1: 5531 op = Q ? Iop_Mul16x8 : Iop_Mul16x4; 5532 break; 5533 case 2: 5534 op = Q ? Iop_Mul32x4 : Iop_Mul32x2; 5535 break; 5536 case 0: 5537 case 3: 5538 return False; 5539 default: 5540 vassert(0); 5541 } 5542 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5543 if (Q) 5544 putQReg(dreg, mkexpr(res), condT); 5545 else 5546 putDRegI64(dreg, mkexpr(res), condT); 5547 DIP("vmul.i%u %c%u, %c%u, d%u[%u]\n", 8 << size, Q ? 'q' : 'd', dreg, 5548 Q ? 'q' : 'd', nreg, mreg, index); 5549 return True; 5550 } 5551 5552 /* VMULL (scalar) */ 5553 if (INSN(11,8) == BITS4(1,0,1,0)) { 5554 IRTemp res, arg_m, arg_n; 5555 IROp dup, get, op; 5556 if (dreg & 1) 5557 return False; 5558 dreg >>= 1; 5559 res = newTemp(Ity_V128); 5560 arg_m = newTemp(Ity_I64); 5561 arg_n = newTemp(Ity_I64); 5562 assign(arg_n, getDRegI64(nreg)); 5563 switch(size) { 5564 case 1: 5565 dup = Iop_Dup16x4; 5566 get = Iop_GetElem16x4; 5567 index = mreg >> 3; 5568 mreg &= 7; 5569 break; 5570 case 2: 5571 dup = Iop_Dup32x2; 5572 get = Iop_GetElem32x2; 5573 index = mreg >> 4; 5574 mreg &= 0xf; 5575 break; 5576 case 0: 5577 case 3: 5578 return False; 5579 default: 5580 vassert(0); 5581 } 5582 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5583 switch (size) { 5584 case 1: op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; break; 5585 case 2: op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; break; 5586 case 0: case 3: return False; 5587 default: vassert(0); 5588 } 5589 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5590 putQReg(dreg, mkexpr(res), condT); 5591 DIP("vmull.%c%u q%u, d%u, d%u[%u]\n", U ? 'u' : 's', 8 << size, dreg, 5592 nreg, mreg, index); 5593 return True; 5594 } 5595 5596 /* VQDMULL */ 5597 if (INSN(11,8) == BITS4(1,0,1,1) && !U) { 5598 IROp op ,op2, dup, get; 5599 ULong imm; 5600 IRTemp res, arg_m, arg_n; 5601 if (dreg & 1) 5602 return False; 5603 dreg >>= 1; 5604 res = newTemp(Ity_V128); 5605 arg_m = newTemp(Ity_I64); 5606 arg_n = newTemp(Ity_I64); 5607 assign(arg_n, getDRegI64(nreg)); 5608 switch(size) { 5609 case 1: 5610 dup = Iop_Dup16x4; 5611 get = Iop_GetElem16x4; 5612 index = mreg >> 3; 5613 mreg &= 7; 5614 break; 5615 case 2: 5616 dup = Iop_Dup32x2; 5617 get = Iop_GetElem32x2; 5618 index = mreg >> 4; 5619 mreg &= 0xf; 5620 break; 5621 case 0: 5622 case 3: 5623 return False; 5624 default: 5625 vassert(0); 5626 } 5627 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5628 switch (size) { 5629 case 0: 5630 case 3: 5631 return False; 5632 case 1: 5633 op = Iop_QDMulLong16Sx4; 5634 op2 = Iop_CmpEQ16x4; 5635 imm = 1LL << 15; 5636 imm = (imm << 16) | imm; 5637 imm = (imm << 32) | imm; 5638 break; 5639 case 2: 5640 op = Iop_QDMulLong32Sx2; 5641 op2 = Iop_CmpEQ32x2; 5642 imm = 1LL << 31; 5643 imm = (imm << 32) | imm; 5644 break; 5645 default: 5646 vassert(0); 5647 } 5648 putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)), 5649 condT); 5650 #ifndef DISABLE_QC_FLAG 5651 setFlag_QC(binop(Iop_And64, 5652 binop(op2, mkexpr(arg_n), mkU64(imm)), 5653 binop(op2, mkexpr(arg_m), mkU64(imm))), 5654 mkU64(0), 5655 False, condT); 5656 #endif 5657 DIP("vqdmull.s%u q%u, d%u, d%u[%u]\n", 8 << size, dreg, nreg, mreg, 5658 index); 5659 return True; 5660 } 5661 5662 /* VQDMULH */ 5663 if (INSN(11,8) == BITS4(1,1,0,0)) { 5664 IROp op ,op2, dup, get; 5665 ULong imm; 5666 IRTemp res, arg_m, arg_n; 5667 if (Q) { 5668 if ((dreg & 1) || (nreg & 1)) 5669 return False; 5670 dreg >>= 1; 5671 nreg >>= 1; 5672 res = newTemp(Ity_V128); 5673 arg_m = newTemp(Ity_V128); 5674 arg_n = newTemp(Ity_V128); 5675 assign(arg_n, getQReg(nreg)); 5676 switch(size) { 5677 case 1: 5678 dup = Iop_Dup16x8; 5679 get = Iop_GetElem16x4; 5680 index = mreg >> 3; 5681 mreg &= 7; 5682 break; 5683 case 2: 5684 dup = Iop_Dup32x4; 5685 get = Iop_GetElem32x2; 5686 index = mreg >> 4; 5687 mreg &= 0xf; 5688 break; 5689 case 0: 5690 case 3: 5691 return False; 5692 default: 5693 vassert(0); 5694 } 5695 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5696 } else { 5697 res = newTemp(Ity_I64); 5698 arg_m = newTemp(Ity_I64); 5699 arg_n = newTemp(Ity_I64); 5700 assign(arg_n, getDRegI64(nreg)); 5701 switch(size) { 5702 case 1: 5703 dup = Iop_Dup16x4; 5704 get = Iop_GetElem16x4; 5705 index = mreg >> 3; 5706 mreg &= 7; 5707 break; 5708 case 2: 5709 dup = Iop_Dup32x2; 5710 get = Iop_GetElem32x2; 5711 index = mreg >> 4; 5712 mreg &= 0xf; 5713 break; 5714 case 0: 5715 case 3: 5716 return False; 5717 default: 5718 vassert(0); 5719 } 5720 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5721 } 5722 switch (size) { 5723 case 0: 5724 case 3: 5725 return False; 5726 case 1: 5727 op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4; 5728 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4; 5729 imm = 1LL << 15; 5730 imm = (imm << 16) | imm; 5731 imm = (imm << 32) | imm; 5732 break; 5733 case 2: 5734 op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2; 5735 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2; 5736 imm = 1LL << 31; 5737 imm = (imm << 32) | imm; 5738 break; 5739 default: 5740 vassert(0); 5741 } 5742 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5743 #ifndef DISABLE_QC_FLAG 5744 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 5745 binop(op2, mkexpr(arg_n), 5746 Q ? mkU128(imm) : mkU64(imm)), 5747 binop(op2, mkexpr(arg_m), 5748 Q ? mkU128(imm) : mkU64(imm))), 5749 Q ? mkU128(0) : mkU64(0), 5750 Q, condT); 5751 #endif 5752 if (Q) 5753 putQReg(dreg, mkexpr(res), condT); 5754 else 5755 putDRegI64(dreg, mkexpr(res), condT); 5756 DIP("vqdmulh.s%u %c%u, %c%u, d%u[%u]\n", 5757 8 << size, Q ? 'q' : 'd', dreg, 5758 Q ? 'q' : 'd', nreg, mreg, index); 5759 return True; 5760 } 5761 5762 /* VQRDMULH (scalar) */ 5763 if (INSN(11,8) == BITS4(1,1,0,1)) { 5764 IROp op ,op2, dup, get; 5765 ULong imm; 5766 IRTemp res, arg_m, arg_n; 5767 if (Q) { 5768 if ((dreg & 1) || (nreg & 1)) 5769 return False; 5770 dreg >>= 1; 5771 nreg >>= 1; 5772 res = newTemp(Ity_V128); 5773 arg_m = newTemp(Ity_V128); 5774 arg_n = newTemp(Ity_V128); 5775 assign(arg_n, getQReg(nreg)); 5776 switch(size) { 5777 case 1: 5778 dup = Iop_Dup16x8; 5779 get = Iop_GetElem16x4; 5780 index = mreg >> 3; 5781 mreg &= 7; 5782 break; 5783 case 2: 5784 dup = Iop_Dup32x4; 5785 get = Iop_GetElem32x2; 5786 index = mreg >> 4; 5787 mreg &= 0xf; 5788 break; 5789 case 0: 5790 case 3: 5791 return False; 5792 default: 5793 vassert(0); 5794 } 5795 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5796 } else { 5797 res = newTemp(Ity_I64); 5798 arg_m = newTemp(Ity_I64); 5799 arg_n = newTemp(Ity_I64); 5800 assign(arg_n, getDRegI64(nreg)); 5801 switch(size) { 5802 case 1: 5803 dup = Iop_Dup16x4; 5804 get = Iop_GetElem16x4; 5805 index = mreg >> 3; 5806 mreg &= 7; 5807 break; 5808 case 2: 5809 dup = Iop_Dup32x2; 5810 get = Iop_GetElem32x2; 5811 index = mreg >> 4; 5812 mreg &= 0xf; 5813 break; 5814 case 0: 5815 case 3: 5816 return False; 5817 default: 5818 vassert(0); 5819 } 5820 assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index)))); 5821 } 5822 switch (size) { 5823 case 0: 5824 case 3: 5825 return False; 5826 case 1: 5827 op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4; 5828 op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4; 5829 imm = 1LL << 15; 5830 imm = (imm << 16) | imm; 5831 imm = (imm << 32) | imm; 5832 break; 5833 case 2: 5834 op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2; 5835 op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2; 5836 imm = 1LL << 31; 5837 imm = (imm << 32) | imm; 5838 break; 5839 default: 5840 vassert(0); 5841 } 5842 assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m))); 5843 #ifndef DISABLE_QC_FLAG 5844 setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64, 5845 binop(op2, mkexpr(arg_n), 5846 Q ? mkU128(imm) : mkU64(imm)), 5847 binop(op2, mkexpr(arg_m), 5848 Q ? mkU128(imm) : mkU64(imm))), 5849 Q ? mkU128(0) : mkU64(0), 5850 Q, condT); 5851 #endif 5852 if (Q) 5853 putQReg(dreg, mkexpr(res), condT); 5854 else 5855 putDRegI64(dreg, mkexpr(res), condT); 5856 DIP("vqrdmulh.s%u %c%u, %c%u, d%u[%u]\n", 5857 8 << size, Q ? 'q' : 'd', dreg, 5858 Q ? 'q' : 'd', nreg, mreg, index); 5859 return True; 5860 } 5861 5862 return False; 5863 # undef INSN 5864 } 5865 5866 /* A7.4.4 Two registers and a shift amount */ 5867 static 5868 Bool dis_neon_data_2reg_and_shift ( UInt theInstr, IRTemp condT ) 5869 { 5870 UInt A = (theInstr >> 8) & 0xf; 5871 UInt B = (theInstr >> 6) & 1; 5872 UInt L = (theInstr >> 7) & 1; 5873 UInt U = (theInstr >> 24) & 1; 5874 UInt Q = B; 5875 UInt imm6 = (theInstr >> 16) & 0x3f; 5876 UInt shift_imm; 5877 UInt size = 4; 5878 UInt tmp; 5879 UInt mreg = get_neon_m_regno(theInstr); 5880 UInt dreg = get_neon_d_regno(theInstr); 5881 ULong imm = 0; 5882 IROp op, cvt, add = Iop_INVALID, cvt2, op_rev; 5883 IRTemp reg_m, res, mask; 5884 5885 if (L == 0 && ((theInstr >> 19) & 7) == 0) 5886 /* It is one reg and immediate */ 5887 return False; 5888 5889 tmp = (L << 6) | imm6; 5890 if (tmp & 0x40) { 5891 size = 3; 5892 shift_imm = 64 - imm6; 5893 } else if (tmp & 0x20) { 5894 size = 2; 5895 shift_imm = 64 - imm6; 5896 } else if (tmp & 0x10) { 5897 size = 1; 5898 shift_imm = 32 - imm6; 5899 } else if (tmp & 0x8) { 5900 size = 0; 5901 shift_imm = 16 - imm6; 5902 } else { 5903 return False; 5904 } 5905 5906 switch (A) { 5907 case 3: 5908 case 2: 5909 /* VRSHR, VRSRA */ 5910 if (shift_imm > 0) { 5911 IRExpr *imm_val; 5912 imm = 1L; 5913 switch (size) { 5914 case 0: 5915 imm = (imm << 8) | imm; 5916 /* fall through */ 5917 case 1: 5918 imm = (imm << 16) | imm; 5919 /* fall through */ 5920 case 2: 5921 imm = (imm << 32) | imm; 5922 /* fall through */ 5923 case 3: 5924 break; 5925 default: 5926 vassert(0); 5927 } 5928 if (Q) { 5929 reg_m = newTemp(Ity_V128); 5930 res = newTemp(Ity_V128); 5931 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)); 5932 assign(reg_m, getQReg(mreg)); 5933 switch (size) { 5934 case 0: 5935 add = Iop_Add8x16; 5936 op = U ? Iop_ShrN8x16 : Iop_SarN8x16; 5937 break; 5938 case 1: 5939 add = Iop_Add16x8; 5940 op = U ? Iop_ShrN16x8 : Iop_SarN16x8; 5941 break; 5942 case 2: 5943 add = Iop_Add32x4; 5944 op = U ? Iop_ShrN32x4 : Iop_SarN32x4; 5945 break; 5946 case 3: 5947 add = Iop_Add64x2; 5948 op = U ? Iop_ShrN64x2 : Iop_SarN64x2; 5949 break; 5950 default: 5951 vassert(0); 5952 } 5953 } else { 5954 reg_m = newTemp(Ity_I64); 5955 res = newTemp(Ity_I64); 5956 imm_val = mkU64(imm); 5957 assign(reg_m, getDRegI64(mreg)); 5958 switch (size) { 5959 case 0: 5960 add = Iop_Add8x8; 5961 op = U ? Iop_ShrN8x8 : Iop_SarN8x8; 5962 break; 5963 case 1: 5964 add = Iop_Add16x4; 5965 op = U ? Iop_ShrN16x4 : Iop_SarN16x4; 5966 break; 5967 case 2: 5968 add = Iop_Add32x2; 5969 op = U ? Iop_ShrN32x2 : Iop_SarN32x2; 5970 break; 5971 case 3: 5972 add = Iop_Add64; 5973 op = U ? Iop_Shr64 : Iop_Sar64; 5974 break; 5975 default: 5976 vassert(0); 5977 } 5978 } 5979 assign(res, 5980 binop(add, 5981 binop(op, 5982 mkexpr(reg_m), 5983 mkU8(shift_imm)), 5984 binop(Q ? Iop_AndV128 : Iop_And64, 5985 binop(op, 5986 mkexpr(reg_m), 5987 mkU8(shift_imm - 1)), 5988 imm_val))); 5989 } else { 5990 if (Q) { 5991 res = newTemp(Ity_V128); 5992 assign(res, getQReg(mreg)); 5993 } else { 5994 res = newTemp(Ity_I64); 5995 assign(res, getDRegI64(mreg)); 5996 } 5997 } 5998 if (A == 3) { 5999 if (Q) { 6000 putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)), 6001 condT); 6002 } else { 6003 putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)), 6004 condT); 6005 } 6006 DIP("vrsra.%c%u %c%u, %c%u, #%u\n", 6007 U ? 'u' : 's', 8 << size, 6008 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6009 } else { 6010 if (Q) { 6011 putQReg(dreg, mkexpr(res), condT); 6012 } else { 6013 putDRegI64(dreg, mkexpr(res), condT); 6014 } 6015 DIP("vrshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size, 6016 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6017 } 6018 return True; 6019 case 1: 6020 case 0: 6021 /* VSHR, VSRA */ 6022 if (Q) { 6023 reg_m = newTemp(Ity_V128); 6024 assign(reg_m, getQReg(mreg)); 6025 res = newTemp(Ity_V128); 6026 } else { 6027 reg_m = newTemp(Ity_I64); 6028 assign(reg_m, getDRegI64(mreg)); 6029 res = newTemp(Ity_I64); 6030 } 6031 if (Q) { 6032 switch (size) { 6033 case 0: 6034 op = U ? Iop_ShrN8x16 : Iop_SarN8x16; 6035 add = Iop_Add8x16; 6036 break; 6037 case 1: 6038 op = U ? Iop_ShrN16x8 : Iop_SarN16x8; 6039 add = Iop_Add16x8; 6040 break; 6041 case 2: 6042 op = U ? Iop_ShrN32x4 : Iop_SarN32x4; 6043 add = Iop_Add32x4; 6044 break; 6045 case 3: 6046 op = U ? Iop_ShrN64x2 : Iop_SarN64x2; 6047 add = Iop_Add64x2; 6048 break; 6049 default: 6050 vassert(0); 6051 } 6052 } else { 6053 switch (size) { 6054 case 0: 6055 op = U ? Iop_ShrN8x8 : Iop_SarN8x8; 6056 add = Iop_Add8x8; 6057 break; 6058 case 1: 6059 op = U ? Iop_ShrN16x4 : Iop_SarN16x4; 6060 add = Iop_Add16x4; 6061 break; 6062 case 2: 6063 op = U ? Iop_ShrN32x2 : Iop_SarN32x2; 6064 add = Iop_Add32x2; 6065 break; 6066 case 3: 6067 op = U ? Iop_Shr64 : Iop_Sar64; 6068 add = Iop_Add64; 6069 break; 6070 default: 6071 vassert(0); 6072 } 6073 } 6074 assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm))); 6075 if (A == 1) { 6076 if (Q) { 6077 putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)), 6078 condT); 6079 } else { 6080 putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)), 6081 condT); 6082 } 6083 DIP("vsra.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size, 6084 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6085 } else { 6086 if (Q) { 6087 putQReg(dreg, mkexpr(res), condT); 6088 } else { 6089 putDRegI64(dreg, mkexpr(res), condT); 6090 } 6091 DIP("vshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size, 6092 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6093 } 6094 return True; 6095 case 4: 6096 /* VSRI */ 6097 if (!U) 6098 return False; 6099 if (Q) { 6100 res = newTemp(Ity_V128); 6101 mask = newTemp(Ity_V128); 6102 } else { 6103 res = newTemp(Ity_I64); 6104 mask = newTemp(Ity_I64); 6105 } 6106 switch (size) { 6107 case 0: op = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; break; 6108 case 1: op = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; break; 6109 case 2: op = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; break; 6110 case 3: op = Q ? Iop_ShrN64x2 : Iop_Shr64; break; 6111 default: vassert(0); 6112 } 6113 if (Q) { 6114 assign(mask, binop(op, binop(Iop_64HLtoV128, 6115 mkU64(0xFFFFFFFFFFFFFFFFLL), 6116 mkU64(0xFFFFFFFFFFFFFFFFLL)), 6117 mkU8(shift_imm))); 6118 assign(res, binop(Iop_OrV128, 6119 binop(Iop_AndV128, 6120 getQReg(dreg), 6121 unop(Iop_NotV128, 6122 mkexpr(mask))), 6123 binop(op, 6124 getQReg(mreg), 6125 mkU8(shift_imm)))); 6126 putQReg(dreg, mkexpr(res), condT); 6127 } else { 6128 assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL), 6129 mkU8(shift_imm))); 6130 assign(res, binop(Iop_Or64, 6131 binop(Iop_And64, 6132 getDRegI64(dreg), 6133 unop(Iop_Not64, 6134 mkexpr(mask))), 6135 binop(op, 6136 getDRegI64(mreg), 6137 mkU8(shift_imm)))); 6138 putDRegI64(dreg, mkexpr(res), condT); 6139 } 6140 DIP("vsri.%u %c%u, %c%u, #%u\n", 6141 8 << size, Q ? 'q' : 'd', dreg, 6142 Q ? 'q' : 'd', mreg, shift_imm); 6143 return True; 6144 case 5: 6145 if (U) { 6146 /* VSLI */ 6147 shift_imm = 8 * (1 << size) - shift_imm; 6148 if (Q) { 6149 res = newTemp(Ity_V128); 6150 mask = newTemp(Ity_V128); 6151 } else { 6152 res = newTemp(Ity_I64); 6153 mask = newTemp(Ity_I64); 6154 } 6155 switch (size) { 6156 case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break; 6157 case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break; 6158 case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break; 6159 case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break; 6160 default: vassert(0); 6161 } 6162 if (Q) { 6163 assign(mask, binop(op, binop(Iop_64HLtoV128, 6164 mkU64(0xFFFFFFFFFFFFFFFFLL), 6165 mkU64(0xFFFFFFFFFFFFFFFFLL)), 6166 mkU8(shift_imm))); 6167 assign(res, binop(Iop_OrV128, 6168 binop(Iop_AndV128, 6169 getQReg(dreg), 6170 unop(Iop_NotV128, 6171 mkexpr(mask))), 6172 binop(op, 6173 getQReg(mreg), 6174 mkU8(shift_imm)))); 6175 putQReg(dreg, mkexpr(res), condT); 6176 } else { 6177 assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL), 6178 mkU8(shift_imm))); 6179 assign(res, binop(Iop_Or64, 6180 binop(Iop_And64, 6181 getDRegI64(dreg), 6182 unop(Iop_Not64, 6183 mkexpr(mask))), 6184 binop(op, 6185 getDRegI64(mreg), 6186 mkU8(shift_imm)))); 6187 putDRegI64(dreg, mkexpr(res), condT); 6188 } 6189 DIP("vsli.%u %c%u, %c%u, #%u\n", 6190 8 << size, Q ? 'q' : 'd', dreg, 6191 Q ? 'q' : 'd', mreg, shift_imm); 6192 return True; 6193 } else { 6194 /* VSHL #imm */ 6195 shift_imm = 8 * (1 << size) - shift_imm; 6196 if (Q) { 6197 res = newTemp(Ity_V128); 6198 } else { 6199 res = newTemp(Ity_I64); 6200 } 6201 switch (size) { 6202 case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break; 6203 case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break; 6204 case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break; 6205 case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break; 6206 default: vassert(0); 6207 } 6208 assign(res, binop(op, Q ? getQReg(mreg) : getDRegI64(mreg), 6209 mkU8(shift_imm))); 6210 if (Q) { 6211 putQReg(dreg, mkexpr(res), condT); 6212 } else { 6213 putDRegI64(dreg, mkexpr(res), condT); 6214 } 6215 DIP("vshl.i%u %c%u, %c%u, #%u\n", 6216 8 << size, Q ? 'q' : 'd', dreg, 6217 Q ? 'q' : 'd', mreg, shift_imm); 6218 return True; 6219 } 6220 break; 6221 case 6: 6222 case 7: 6223 /* VQSHL, VQSHLU */ 6224 shift_imm = 8 * (1 << size) - shift_imm; 6225 if (U) { 6226 if (A & 1) { 6227 switch (size) { 6228 case 0: 6229 op = Q ? Iop_QShlN8x16 : Iop_QShlN8x8; 6230 op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 6231 break; 6232 case 1: 6233 op = Q ? Iop_QShlN16x8 : Iop_QShlN16x4; 6234 op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 6235 break; 6236 case 2: 6237 op = Q ? Iop_QShlN32x4 : Iop_QShlN32x2; 6238 op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 6239 break; 6240 case 3: 6241 op = Q ? Iop_QShlN64x2 : Iop_QShlN64x1; 6242 op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64; 6243 break; 6244 default: 6245 vassert(0); 6246 } 6247 DIP("vqshl.u%u %c%u, %c%u, #%u\n", 6248 8 << size, 6249 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6250 } else { 6251 switch (size) { 6252 case 0: 6253 op = Q ? Iop_QShlN8Sx16 : Iop_QShlN8Sx8; 6254 op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; 6255 break; 6256 case 1: 6257 op = Q ? Iop_QShlN16Sx8 : Iop_QShlN16Sx4; 6258 op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; 6259 break; 6260 case 2: 6261 op = Q ? Iop_QShlN32Sx4 : Iop_QShlN32Sx2; 6262 op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; 6263 break; 6264 case 3: 6265 op = Q ? Iop_QShlN64Sx2 : Iop_QShlN64Sx1; 6266 op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64; 6267 break; 6268 default: 6269 vassert(0); 6270 } 6271 DIP("vqshlu.s%u %c%u, %c%u, #%u\n", 6272 8 << size, 6273 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6274 } 6275 } else { 6276 if (!(A & 1)) 6277 return False; 6278 switch (size) { 6279 case 0: 6280 op = Q ? Iop_QSalN8x16 : Iop_QSalN8x8; 6281 op_rev = Q ? Iop_SarN8x16 : Iop_SarN8x8; 6282 break; 6283 case 1: 6284 op = Q ? Iop_QSalN16x8 : Iop_QSalN16x4; 6285 op_rev = Q ? Iop_SarN16x8 : Iop_SarN16x4; 6286 break; 6287 case 2: 6288 op = Q ? Iop_QSalN32x4 : Iop_QSalN32x2; 6289 op_rev = Q ? Iop_SarN32x4 : Iop_SarN32x2; 6290 break; 6291 case 3: 6292 op = Q ? Iop_QSalN64x2 : Iop_QSalN64x1; 6293 op_rev = Q ? Iop_SarN64x2 : Iop_Sar64; 6294 break; 6295 default: 6296 vassert(0); 6297 } 6298 DIP("vqshl.s%u %c%u, %c%u, #%u\n", 6299 8 << size, 6300 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm); 6301 } 6302 if (Q) { 6303 tmp = newTemp(Ity_V128); 6304 res = newTemp(Ity_V128); 6305 reg_m = newTemp(Ity_V128); 6306 assign(reg_m, getQReg(mreg)); 6307 } else { 6308 tmp = newTemp(Ity_I64); 6309 res = newTemp(Ity_I64); 6310 reg_m = newTemp(Ity_I64); 6311 assign(reg_m, getDRegI64(mreg)); 6312 } 6313 assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm))); 6314 #ifndef DISABLE_QC_FLAG 6315 assign(tmp, binop(op_rev, mkexpr(res), mkU8(shift_imm))); 6316 setFlag_QC(mkexpr(tmp), mkexpr(reg_m), Q, condT); 6317 #endif 6318 if (Q) 6319 putQReg(dreg, mkexpr(res), condT); 6320 else 6321 putDRegI64(dreg, mkexpr(res), condT); 6322 return True; 6323 case 8: 6324 if (!U) { 6325 if (L == 1) 6326 return False; 6327 size++; 6328 dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF); 6329 mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF); 6330 if (mreg & 1) 6331 return False; 6332 mreg >>= 1; 6333 if (!B) { 6334 /* VSHRN*/ 6335 IROp narOp; 6336 reg_m = newTemp(Ity_V128); 6337 assign(reg_m, getQReg(mreg)); 6338 res = newTemp(Ity_I64); 6339 switch (size) { 6340 case 1: 6341 op = Iop_ShrN16x8; 6342 narOp = Iop_Shorten16x8; 6343 break; 6344 case 2: 6345 op = Iop_ShrN32x4; 6346 narOp = Iop_Shorten32x4; 6347 break; 6348 case 3: 6349 op = Iop_ShrN64x2; 6350 narOp = Iop_Shorten64x2; 6351 break; 6352 default: 6353 vassert(0); 6354 } 6355 assign(res, unop(narOp, 6356 binop(op, 6357 mkexpr(reg_m), 6358 mkU8(shift_imm)))); 6359 putDRegI64(dreg, mkexpr(res), condT); 6360 DIP("vshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg, 6361 shift_imm); 6362 return True; 6363 } else { 6364 /* VRSHRN */ 6365 IROp addOp, shOp, narOp; 6366 IRExpr *imm_val; 6367 reg_m = newTemp(Ity_V128); 6368 assign(reg_m, getQReg(mreg)); 6369 res = newTemp(Ity_I64); 6370 imm = 1L; 6371 switch (size) { 6372 case 0: imm = (imm << 8) | imm; /* fall through */ 6373 case 1: imm = (imm << 16) | imm; /* fall through */ 6374 case 2: imm = (imm << 32) | imm; /* fall through */ 6375 case 3: break; 6376 default: vassert(0); 6377 } 6378 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)); 6379 switch (size) { 6380 case 1: 6381 addOp = Iop_Add16x8; 6382 shOp = Iop_ShrN16x8; 6383 narOp = Iop_Shorten16x8; 6384 break; 6385 case 2: 6386 addOp = Iop_Add32x4; 6387 shOp = Iop_ShrN32x4; 6388 narOp = Iop_Shorten32x4; 6389 break; 6390 case 3: 6391 addOp = Iop_Add64x2; 6392 shOp = Iop_ShrN64x2; 6393 narOp = Iop_Shorten64x2; 6394 break; 6395 default: 6396 vassert(0); 6397 } 6398 assign(res, unop(narOp, 6399 binop(addOp, 6400 binop(shOp, 6401 mkexpr(reg_m), 6402 mkU8(shift_imm)), 6403 binop(Iop_AndV128, 6404 binop(shOp, 6405 mkexpr(reg_m), 6406 mkU8(shift_imm - 1)), 6407 imm_val)))); 6408 putDRegI64(dreg, mkexpr(res), condT); 6409 if (shift_imm == 0) { 6410 DIP("vmov%u d%u, q%u, #%u\n", 8 << size, dreg, mreg, 6411 shift_imm); 6412 } else { 6413 DIP("vrshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg, 6414 shift_imm); 6415 } 6416 return True; 6417 } 6418 } else { 6419 /* fall through */ 6420 } 6421 case 9: 6422 dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF); 6423 mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF); 6424 if (mreg & 1) 6425 return False; 6426 mreg >>= 1; 6427 size++; 6428 if ((theInstr >> 8) & 1) { 6429 switch (size) { 6430 case 1: 6431 op = U ? Iop_ShrN16x8 : Iop_SarN16x8; 6432 cvt = U ? Iop_QShortenU16Ux8 : Iop_QShortenS16Sx8; 6433 cvt2 = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8; 6434 break; 6435 case 2: 6436 op = U ? Iop_ShrN32x4 : Iop_SarN32x4; 6437 cvt = U ? Iop_QShortenU32Ux4 : Iop_QShortenS32Sx4; 6438 cvt2 = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4; 6439 break; 6440 case 3: 6441 op = U ? Iop_ShrN64x2 : Iop_SarN64x2; 6442 cvt = U ? Iop_QShortenU64Ux2 : Iop_QShortenS64Sx2; 6443 cvt2 = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2; 6444 break; 6445 default: 6446 vassert(0); 6447 } 6448 DIP("vq%sshrn.%c%u d%u, q%u, #%u\n", B ? "r" : "", 6449 U ? 'u' : 's', 8 << size, dreg, mreg, shift_imm); 6450 } else { 6451 vassert(U); 6452 switch (size) { 6453 case 1: 6454 op = Iop_SarN16x8; 6455 cvt = Iop_QShortenU16Sx8; 6456 cvt2 = Iop_Longen8Ux8; 6457 break; 6458 case 2: 6459 op = Iop_SarN32x4; 6460 cvt = Iop_QShortenU32Sx4; 6461 cvt2 = Iop_Longen16Ux4; 6462 break; 6463 case 3: 6464 op = Iop_SarN64x2; 6465 cvt = Iop_QShortenU64Sx2; 6466 cvt2 = Iop_Longen32Ux2; 6467 break; 6468 default: 6469 vassert(0); 6470 } 6471 DIP("vq%sshrun.s%u d%u, q%u, #%u\n", B ? "r" : "", 6472 8 << size, dreg, mreg, shift_imm); 6473 } 6474 if (B) { 6475 if (shift_imm > 0) { 6476 imm = 1; 6477 switch (size) { 6478 case 1: imm = (imm << 16) | imm; /* fall through */ 6479 case 2: imm = (imm << 32) | imm; /* fall through */ 6480 case 3: break; 6481 case 0: default: vassert(0); 6482 } 6483 switch (size) { 6484 case 1: add = Iop_Add16x8; break; 6485 case 2: add = Iop_Add32x4; break; 6486 case 3: add = Iop_Add64x2; break; 6487 case 0: default: vassert(0); 6488 } 6489 } 6490 } 6491 reg_m = newTemp(Ity_V128); 6492 res = newTemp(Ity_V128); 6493 assign(reg_m, getQReg(mreg)); 6494 if (B) { 6495 /* VQRSHRN, VQRSHRUN */ 6496 assign(res, binop(add, 6497 binop(op, mkexpr(reg_m), mkU8(shift_imm)), 6498 binop(Iop_AndV128, 6499 binop(op, 6500 mkexpr(reg_m), 6501 mkU8(shift_imm - 1)), 6502 mkU128(imm)))); 6503 } else { 6504 /* VQSHRN, VQSHRUN */ 6505 assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm))); 6506 } 6507 #ifndef DISABLE_QC_FLAG 6508 setFlag_QC(unop(cvt2, unop(cvt, mkexpr(res))), mkexpr(res), 6509 True, condT); 6510 #endif 6511 putDRegI64(dreg, unop(cvt, mkexpr(res)), condT); 6512 return True; 6513 case 10: 6514 /* VSHLL 6515 VMOVL ::= VSHLL #0 */ 6516 if (B) 6517 return False; 6518 if (dreg & 1) 6519 return False; 6520 dreg >>= 1; 6521 shift_imm = (8 << size) - shift_imm; 6522 res = newTemp(Ity_V128); 6523 switch (size) { 6524 case 0: 6525 op = Iop_ShlN16x8; 6526 cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8; 6527 break; 6528 case 1: 6529 op = Iop_ShlN32x4; 6530 cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4; 6531 break; 6532 case 2: 6533 op = Iop_ShlN64x2; 6534 cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2; 6535 break; 6536 case 3: 6537 return False; 6538 default: 6539 vassert(0); 6540 } 6541 assign(res, binop(op, unop(cvt, getDRegI64(mreg)), mkU8(shift_imm))); 6542 putQReg(dreg, mkexpr(res), condT); 6543 if (shift_imm == 0) { 6544 DIP("vmovl.%c%u q%u, d%u\n", U ? 'u' : 's', 8 << size, 6545 dreg, mreg); 6546 } else { 6547 DIP("vshll.%c%u q%u, d%u, #%u\n", U ? 'u' : 's', 8 << size, 6548 dreg, mreg, shift_imm); 6549 } 6550 return True; 6551 case 14: 6552 case 15: 6553 /* VCVT floating-point <-> fixed-point */ 6554 if ((theInstr >> 8) & 1) { 6555 if (U) { 6556 op = Q ? Iop_F32ToFixed32Ux4_RZ : Iop_F32ToFixed32Ux2_RZ; 6557 } else { 6558 op = Q ? Iop_F32ToFixed32Sx4_RZ : Iop_F32ToFixed32Sx2_RZ; 6559 } 6560 DIP("vcvt.%c32.f32 %c%u, %c%u, #%u\n", U ? 'u' : 's', 6561 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, 6562 64 - ((theInstr >> 16) & 0x3f)); 6563 } else { 6564 if (U) { 6565 op = Q ? Iop_Fixed32UToF32x4_RN : Iop_Fixed32UToF32x2_RN; 6566 } else { 6567 op = Q ? Iop_Fixed32SToF32x4_RN : Iop_Fixed32SToF32x2_RN; 6568 } 6569 DIP("vcvt.f32.%c32 %c%u, %c%u, #%u\n", U ? 'u' : 's', 6570 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, 6571 64 - ((theInstr >> 16) & 0x3f)); 6572 } 6573 if (((theInstr >> 21) & 1) == 0) 6574 return False; 6575 if (Q) { 6576 putQReg(dreg, binop(op, getQReg(mreg), 6577 mkU8(64 - ((theInstr >> 16) & 0x3f))), condT); 6578 } else { 6579 putDRegI64(dreg, binop(op, getDRegI64(mreg), 6580 mkU8(64 - ((theInstr >> 16) & 0x3f))), condT); 6581 } 6582 return True; 6583 default: 6584 return False; 6585 6586 } 6587 return False; 6588 } 6589 6590 /* A7.4.5 Two registers, miscellaneous */ 6591 static 6592 Bool dis_neon_data_2reg_misc ( UInt theInstr, IRTemp condT ) 6593 { 6594 UInt A = (theInstr >> 16) & 3; 6595 UInt B = (theInstr >> 6) & 0x1f; 6596 UInt Q = (theInstr >> 6) & 1; 6597 UInt U = (theInstr >> 24) & 1; 6598 UInt size = (theInstr >> 18) & 3; 6599 UInt dreg = get_neon_d_regno(theInstr); 6600 UInt mreg = get_neon_m_regno(theInstr); 6601 UInt F = (theInstr >> 10) & 1; 6602 IRTemp arg_d; 6603 IRTemp arg_m; 6604 IRTemp res; 6605 switch (A) { 6606 case 0: 6607 if (Q) { 6608 arg_m = newTemp(Ity_V128); 6609 res = newTemp(Ity_V128); 6610 assign(arg_m, getQReg(mreg)); 6611 } else { 6612 arg_m = newTemp(Ity_I64); 6613 res = newTemp(Ity_I64); 6614 assign(arg_m, getDRegI64(mreg)); 6615 } 6616 switch (B >> 1) { 6617 case 0: { 6618 /* VREV64 */ 6619 IROp op; 6620 switch (size) { 6621 case 0: 6622 op = Q ? Iop_Reverse64_8x16 : Iop_Reverse64_8x8; 6623 break; 6624 case 1: 6625 op = Q ? Iop_Reverse64_16x8 : Iop_Reverse64_16x4; 6626 break; 6627 case 2: 6628 op = Q ? Iop_Reverse64_32x4 : Iop_Reverse64_32x2; 6629 break; 6630 case 3: 6631 return False; 6632 default: 6633 vassert(0); 6634 } 6635 assign(res, unop(op, mkexpr(arg_m))); 6636 DIP("vrev64.%u %c%u, %c%u\n", 8 << size, 6637 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6638 break; 6639 } 6640 case 1: { 6641 /* VREV32 */ 6642 IROp op; 6643 switch (size) { 6644 case 0: 6645 op = Q ? Iop_Reverse32_8x16 : Iop_Reverse32_8x8; 6646 break; 6647 case 1: 6648 op = Q ? Iop_Reverse32_16x8 : Iop_Reverse32_16x4; 6649 break; 6650 case 2: 6651 case 3: 6652 return False; 6653 default: 6654 vassert(0); 6655 } 6656 assign(res, unop(op, mkexpr(arg_m))); 6657 DIP("vrev32.%u %c%u, %c%u\n", 8 << size, 6658 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6659 break; 6660 } 6661 case 2: { 6662 /* VREV16 */ 6663 IROp op; 6664 switch (size) { 6665 case 0: 6666 op = Q ? Iop_Reverse16_8x16 : Iop_Reverse16_8x8; 6667 break; 6668 case 1: 6669 case 2: 6670 case 3: 6671 return False; 6672 default: 6673 vassert(0); 6674 } 6675 assign(res, unop(op, mkexpr(arg_m))); 6676 DIP("vrev16.%u %c%u, %c%u\n", 8 << size, 6677 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6678 break; 6679 } 6680 case 3: 6681 return False; 6682 case 4: 6683 case 5: { 6684 /* VPADDL */ 6685 IROp op; 6686 U = (theInstr >> 7) & 1; 6687 if (Q) { 6688 switch (size) { 6689 case 0: op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16; break; 6690 case 1: op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8; break; 6691 case 2: op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4; break; 6692 case 3: return False; 6693 default: vassert(0); 6694 } 6695 } else { 6696 switch (size) { 6697 case 0: op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8; break; 6698 case 1: op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4; break; 6699 case 2: op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2; break; 6700 case 3: return False; 6701 default: vassert(0); 6702 } 6703 } 6704 assign(res, unop(op, mkexpr(arg_m))); 6705 DIP("vpaddl.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size, 6706 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6707 break; 6708 } 6709 case 6: 6710 case 7: 6711 return False; 6712 case 8: { 6713 /* VCLS */ 6714 IROp op; 6715 switch (size) { 6716 case 0: op = Q ? Iop_Cls8Sx16 : Iop_Cls8Sx8; break; 6717 case 1: op = Q ? Iop_Cls16Sx8 : Iop_Cls16Sx4; break; 6718 case 2: op = Q ? Iop_Cls32Sx4 : Iop_Cls32Sx2; break; 6719 case 3: return False; 6720 default: vassert(0); 6721 } 6722 assign(res, unop(op, mkexpr(arg_m))); 6723 DIP("vcls.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg, 6724 Q ? 'q' : 'd', mreg); 6725 break; 6726 } 6727 case 9: { 6728 /* VCLZ */ 6729 IROp op; 6730 switch (size) { 6731 case 0: op = Q ? Iop_Clz8Sx16 : Iop_Clz8Sx8; break; 6732 case 1: op = Q ? Iop_Clz16Sx8 : Iop_Clz16Sx4; break; 6733 case 2: op = Q ? Iop_Clz32Sx4 : Iop_Clz32Sx2; break; 6734 case 3: return False; 6735 default: vassert(0); 6736 } 6737 assign(res, unop(op, mkexpr(arg_m))); 6738 DIP("vclz.i%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg, 6739 Q ? 'q' : 'd', mreg); 6740 break; 6741 } 6742 case 10: 6743 /* VCNT */ 6744 assign(res, unop(Q ? Iop_Cnt8x16 : Iop_Cnt8x8, mkexpr(arg_m))); 6745 DIP("vcnt.8 %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', 6746 mreg); 6747 break; 6748 case 11: 6749 /* VMVN */ 6750 if (Q) 6751 assign(res, unop(Iop_NotV128, mkexpr(arg_m))); 6752 else 6753 assign(res, unop(Iop_Not64, mkexpr(arg_m))); 6754 DIP("vmvn %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', 6755 mreg); 6756 break; 6757 case 12: 6758 case 13: { 6759 /* VPADAL */ 6760 IROp op, add_op; 6761 U = (theInstr >> 7) & 1; 6762 if (Q) { 6763 switch (size) { 6764 case 0: 6765 op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16; 6766 add_op = Iop_Add16x8; 6767 break; 6768 case 1: 6769 op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8; 6770 add_op = Iop_Add32x4; 6771 break; 6772 case 2: 6773 op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4; 6774 add_op = Iop_Add64x2; 6775 break; 6776 case 3: 6777 return False; 6778 default: 6779 vassert(0); 6780 } 6781 } else { 6782 switch (size) { 6783 case 0: 6784 op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8; 6785 add_op = Iop_Add16x4; 6786 break; 6787 case 1: 6788 op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4; 6789 add_op = Iop_Add32x2; 6790 break; 6791 case 2: 6792 op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2; 6793 add_op = Iop_Add64; 6794 break; 6795 case 3: 6796 return False; 6797 default: 6798 vassert(0); 6799 } 6800 } 6801 if (Q) { 6802 arg_d = newTemp(Ity_V128); 6803 assign(arg_d, getQReg(dreg)); 6804 } else { 6805 arg_d = newTemp(Ity_I64); 6806 assign(arg_d, getDRegI64(dreg)); 6807 } 6808 assign(res, binop(add_op, unop(op, mkexpr(arg_m)), 6809 mkexpr(arg_d))); 6810 DIP("vpadal.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size, 6811 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6812 break; 6813 } 6814 case 14: { 6815 /* VQABS */ 6816 IROp op_sub, op_qsub, op_cmp; 6817 IRTemp mask, tmp; 6818 IRExpr *zero1, *zero2; 6819 IRExpr *neg, *neg2; 6820 if (Q) { 6821 zero1 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 6822 zero2 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 6823 mask = newTemp(Ity_V128); 6824 tmp = newTemp(Ity_V128); 6825 } else { 6826 zero1 = mkU64(0); 6827 zero2 = mkU64(0); 6828 mask = newTemp(Ity_I64); 6829 tmp = newTemp(Ity_I64); 6830 } 6831 switch (size) { 6832 case 0: 6833 op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8; 6834 op_qsub = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8; 6835 op_cmp = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; 6836 break; 6837 case 1: 6838 op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4; 6839 op_qsub = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4; 6840 op_cmp = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; 6841 break; 6842 case 2: 6843 op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2; 6844 op_qsub = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2; 6845 op_cmp = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; 6846 break; 6847 case 3: 6848 return False; 6849 default: 6850 vassert(0); 6851 } 6852 assign(mask, binop(op_cmp, mkexpr(arg_m), zero1)); 6853 neg = binop(op_qsub, zero2, mkexpr(arg_m)); 6854 neg2 = binop(op_sub, zero2, mkexpr(arg_m)); 6855 assign(res, binop(Q ? Iop_OrV128 : Iop_Or64, 6856 binop(Q ? Iop_AndV128 : Iop_And64, 6857 mkexpr(mask), 6858 mkexpr(arg_m)), 6859 binop(Q ? Iop_AndV128 : Iop_And64, 6860 unop(Q ? Iop_NotV128 : Iop_Not64, 6861 mkexpr(mask)), 6862 neg))); 6863 #ifndef DISABLE_QC_FLAG 6864 assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64, 6865 binop(Q ? Iop_AndV128 : Iop_And64, 6866 mkexpr(mask), 6867 mkexpr(arg_m)), 6868 binop(Q ? Iop_AndV128 : Iop_And64, 6869 unop(Q ? Iop_NotV128 : Iop_Not64, 6870 mkexpr(mask)), 6871 neg2))); 6872 setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT); 6873 #endif 6874 DIP("vqabs.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg, 6875 Q ? 'q' : 'd', mreg); 6876 break; 6877 } 6878 case 15: { 6879 /* VQNEG */ 6880 IROp op, op2; 6881 IRExpr *zero; 6882 if (Q) { 6883 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 6884 } else { 6885 zero = mkU64(0); 6886 } 6887 switch (size) { 6888 case 0: 6889 op = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8; 6890 op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8; 6891 break; 6892 case 1: 6893 op = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4; 6894 op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4; 6895 break; 6896 case 2: 6897 op = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2; 6898 op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2; 6899 break; 6900 case 3: 6901 return False; 6902 default: 6903 vassert(0); 6904 } 6905 assign(res, binop(op, zero, mkexpr(arg_m))); 6906 #ifndef DISABLE_QC_FLAG 6907 setFlag_QC(mkexpr(res), binop(op2, zero, mkexpr(arg_m)), 6908 Q, condT); 6909 #endif 6910 DIP("vqneg.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg, 6911 Q ? 'q' : 'd', mreg); 6912 break; 6913 } 6914 default: 6915 vassert(0); 6916 } 6917 if (Q) { 6918 putQReg(dreg, mkexpr(res), condT); 6919 } else { 6920 putDRegI64(dreg, mkexpr(res), condT); 6921 } 6922 return True; 6923 case 1: 6924 if (Q) { 6925 arg_m = newTemp(Ity_V128); 6926 res = newTemp(Ity_V128); 6927 assign(arg_m, getQReg(mreg)); 6928 } else { 6929 arg_m = newTemp(Ity_I64); 6930 res = newTemp(Ity_I64); 6931 assign(arg_m, getDRegI64(mreg)); 6932 } 6933 switch ((B >> 1) & 0x7) { 6934 case 0: { 6935 /* VCGT #0 */ 6936 IRExpr *zero; 6937 IROp op; 6938 if (Q) { 6939 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 6940 } else { 6941 zero = mkU64(0); 6942 } 6943 if (F) { 6944 switch (size) { 6945 case 0: case 1: case 3: return False; 6946 case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break; 6947 default: vassert(0); 6948 } 6949 } else { 6950 switch (size) { 6951 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break; 6952 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break; 6953 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break; 6954 case 3: return False; 6955 default: vassert(0); 6956 } 6957 } 6958 assign(res, binop(op, mkexpr(arg_m), zero)); 6959 DIP("vcgt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size, 6960 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6961 break; 6962 } 6963 case 1: { 6964 /* VCGE #0 */ 6965 IROp op; 6966 IRExpr *zero; 6967 if (Q) { 6968 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 6969 } else { 6970 zero = mkU64(0); 6971 } 6972 if (F) { 6973 switch (size) { 6974 case 0: case 1: case 3: return False; 6975 case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break; 6976 default: vassert(0); 6977 } 6978 assign(res, binop(op, mkexpr(arg_m), zero)); 6979 } else { 6980 switch (size) { 6981 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break; 6982 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break; 6983 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break; 6984 case 3: return False; 6985 default: vassert(0); 6986 } 6987 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64, 6988 binop(op, zero, mkexpr(arg_m)))); 6989 } 6990 DIP("vcge.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size, 6991 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 6992 break; 6993 } 6994 case 2: { 6995 /* VCEQ #0 */ 6996 IROp op; 6997 IRExpr *zero; 6998 if (F) { 6999 if (Q) { 7000 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 7001 } else { 7002 zero = mkU64(0); 7003 } 7004 switch (size) { 7005 case 0: case 1: case 3: return False; 7006 case 2: op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2; break; 7007 default: vassert(0); 7008 } 7009 assign(res, binop(op, zero, mkexpr(arg_m))); 7010 } else { 7011 switch (size) { 7012 case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break; 7013 case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break; 7014 case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break; 7015 case 3: return False; 7016 default: vassert(0); 7017 } 7018 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64, 7019 unop(op, mkexpr(arg_m)))); 7020 } 7021 DIP("vceq.%c%u %c%u, %c%u, #0\n", F ? 'f' : 'i', 8 << size, 7022 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7023 break; 7024 } 7025 case 3: { 7026 /* VCLE #0 */ 7027 IRExpr *zero; 7028 IROp op; 7029 if (Q) { 7030 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 7031 } else { 7032 zero = mkU64(0); 7033 } 7034 if (F) { 7035 switch (size) { 7036 case 0: case 1: case 3: return False; 7037 case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break; 7038 default: vassert(0); 7039 } 7040 assign(res, binop(op, zero, mkexpr(arg_m))); 7041 } else { 7042 switch (size) { 7043 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break; 7044 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break; 7045 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break; 7046 case 3: return False; 7047 default: vassert(0); 7048 } 7049 assign(res, unop(Q ? Iop_NotV128 : Iop_Not64, 7050 binop(op, mkexpr(arg_m), zero))); 7051 } 7052 DIP("vcle.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size, 7053 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7054 break; 7055 } 7056 case 4: { 7057 /* VCLT #0 */ 7058 IROp op; 7059 IRExpr *zero; 7060 if (Q) { 7061 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 7062 } else { 7063 zero = mkU64(0); 7064 } 7065 if (F) { 7066 switch (size) { 7067 case 0: case 1: case 3: return False; 7068 case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break; 7069 default: vassert(0); 7070 } 7071 assign(res, binop(op, zero, mkexpr(arg_m))); 7072 } else { 7073 switch (size) { 7074 case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break; 7075 case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break; 7076 case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break; 7077 case 3: return False; 7078 default: vassert(0); 7079 } 7080 assign(res, binop(op, zero, mkexpr(arg_m))); 7081 } 7082 DIP("vclt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size, 7083 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7084 break; 7085 } 7086 case 5: 7087 return False; 7088 case 6: { 7089 /* VABS */ 7090 if (!F) { 7091 IROp op; 7092 switch(size) { 7093 case 0: op = Q ? Iop_Abs8x16 : Iop_Abs8x8; break; 7094 case 1: op = Q ? Iop_Abs16x8 : Iop_Abs16x4; break; 7095 case 2: op = Q ? Iop_Abs32x4 : Iop_Abs32x2; break; 7096 case 3: return False; 7097 default: vassert(0); 7098 } 7099 assign(res, unop(op, mkexpr(arg_m))); 7100 } else { 7101 assign(res, unop(Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2, 7102 mkexpr(arg_m))); 7103 } 7104 DIP("vabs.%c%u %c%u, %c%u\n", 7105 F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg, 7106 Q ? 'q' : 'd', mreg); 7107 break; 7108 } 7109 case 7: { 7110 /* VNEG */ 7111 IROp op; 7112 IRExpr *zero; 7113 if (F) { 7114 switch (size) { 7115 case 0: case 1: case 3: return False; 7116 case 2: op = Q ? Iop_Neg32Fx4 : Iop_Neg32Fx2; break; 7117 default: vassert(0); 7118 } 7119 assign(res, unop(op, mkexpr(arg_m))); 7120 } else { 7121 if (Q) { 7122 zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0)); 7123 } else { 7124 zero = mkU64(0); 7125 } 7126 switch (size) { 7127 case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break; 7128 case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break; 7129 case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break; 7130 case 3: return False; 7131 default: vassert(0); 7132 } 7133 assign(res, binop(op, zero, mkexpr(arg_m))); 7134 } 7135 DIP("vneg.%c%u %c%u, %c%u\n", 7136 F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg, 7137 Q ? 'q' : 'd', mreg); 7138 break; 7139 } 7140 default: 7141 vassert(0); 7142 } 7143 if (Q) { 7144 putQReg(dreg, mkexpr(res), condT); 7145 } else { 7146 putDRegI64(dreg, mkexpr(res), condT); 7147 } 7148 return True; 7149 case 2: 7150 if ((B >> 1) == 0) { 7151 /* VSWP */ 7152 if (Q) { 7153 arg_m = newTemp(Ity_V128); 7154 assign(arg_m, getQReg(mreg)); 7155 putQReg(mreg, getQReg(dreg), condT); 7156 putQReg(dreg, mkexpr(arg_m), condT); 7157 } else { 7158 arg_m = newTemp(Ity_I64); 7159 assign(arg_m, getDRegI64(mreg)); 7160 putDRegI64(mreg, getDRegI64(dreg), condT); 7161 putDRegI64(dreg, mkexpr(arg_m), condT); 7162 } 7163 DIP("vswp %c%u, %c%u\n", 7164 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7165 return True; 7166 } else if ((B >> 1) == 1) { 7167 /* VTRN */ 7168 IROp op_lo, op_hi; 7169 IRTemp res1, res2; 7170 if (Q) { 7171 arg_m = newTemp(Ity_V128); 7172 arg_d = newTemp(Ity_V128); 7173 res1 = newTemp(Ity_V128); 7174 res2 = newTemp(Ity_V128); 7175 assign(arg_m, getQReg(mreg)); 7176 assign(arg_d, getQReg(dreg)); 7177 } else { 7178 res1 = newTemp(Ity_I64); 7179 res2 = newTemp(Ity_I64); 7180 arg_m = newTemp(Ity_I64); 7181 arg_d = newTemp(Ity_I64); 7182 assign(arg_m, getDRegI64(mreg)); 7183 assign(arg_d, getDRegI64(dreg)); 7184 } 7185 if (Q) { 7186 switch (size) { 7187 case 0: 7188 op_lo = Iop_InterleaveOddLanes8x16; 7189 op_hi = Iop_InterleaveEvenLanes8x16; 7190 break; 7191 case 1: 7192 op_lo = Iop_InterleaveOddLanes16x8; 7193 op_hi = Iop_InterleaveEvenLanes16x8; 7194 break; 7195 case 2: 7196 op_lo = Iop_InterleaveOddLanes32x4; 7197 op_hi = Iop_InterleaveEvenLanes32x4; 7198 break; 7199 case 3: 7200 return False; 7201 default: 7202 vassert(0); 7203 } 7204 } else { 7205 switch (size) { 7206 case 0: 7207 op_lo = Iop_InterleaveOddLanes8x8; 7208 op_hi = Iop_InterleaveEvenLanes8x8; 7209 break; 7210 case 1: 7211 op_lo = Iop_InterleaveOddLanes16x4; 7212 op_hi = Iop_InterleaveEvenLanes16x4; 7213 break; 7214 case 2: 7215 op_lo = Iop_InterleaveLO32x2; 7216 op_hi = Iop_InterleaveHI32x2; 7217 break; 7218 case 3: 7219 return False; 7220 default: 7221 vassert(0); 7222 } 7223 } 7224 assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d))); 7225 assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d))); 7226 if (Q) { 7227 putQReg(dreg, mkexpr(res1), condT); 7228 putQReg(mreg, mkexpr(res2), condT); 7229 } else { 7230 putDRegI64(dreg, mkexpr(res1), condT); 7231 putDRegI64(mreg, mkexpr(res2), condT); 7232 } 7233 DIP("vtrn.%u %c%u, %c%u\n", 7234 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7235 return True; 7236 } else if ((B >> 1) == 2) { 7237 /* VUZP */ 7238 IROp op_lo, op_hi; 7239 IRTemp res1, res2; 7240 if (!Q && size == 2) 7241 return False; 7242 if (Q) { 7243 arg_m = newTemp(Ity_V128); 7244 arg_d = newTemp(Ity_V128); 7245 res1 = newTemp(Ity_V128); 7246 res2 = newTemp(Ity_V128); 7247 assign(arg_m, getQReg(mreg)); 7248 assign(arg_d, getQReg(dreg)); 7249 } else { 7250 res1 = newTemp(Ity_I64); 7251 res2 = newTemp(Ity_I64); 7252 arg_m = newTemp(Ity_I64); 7253 arg_d = newTemp(Ity_I64); 7254 assign(arg_m, getDRegI64(mreg)); 7255 assign(arg_d, getDRegI64(dreg)); 7256 } 7257 switch (size) { 7258 case 0: 7259 op_lo = Q ? Iop_CatOddLanes8x16 : Iop_CatOddLanes8x8; 7260 op_hi = Q ? Iop_CatEvenLanes8x16 : Iop_CatEvenLanes8x8; 7261 break; 7262 case 1: 7263 op_lo = Q ? Iop_CatOddLanes16x8 : Iop_CatOddLanes16x4; 7264 op_hi = Q ? Iop_CatEvenLanes16x8 : Iop_CatEvenLanes16x4; 7265 break; 7266 case 2: 7267 op_lo = Iop_CatOddLanes32x4; 7268 op_hi = Iop_CatEvenLanes32x4; 7269 break; 7270 case 3: 7271 return False; 7272 default: 7273 vassert(0); 7274 } 7275 assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d))); 7276 assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d))); 7277 if (Q) { 7278 putQReg(dreg, mkexpr(res1), condT); 7279 putQReg(mreg, mkexpr(res2), condT); 7280 } else { 7281 putDRegI64(dreg, mkexpr(res1), condT); 7282 putDRegI64(mreg, mkexpr(res2), condT); 7283 } 7284 DIP("vuzp.%u %c%u, %c%u\n", 7285 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7286 return True; 7287 } else if ((B >> 1) == 3) { 7288 /* VZIP */ 7289 IROp op_lo, op_hi; 7290 IRTemp res1, res2; 7291 if (!Q && size == 2) 7292 return False; 7293 if (Q) { 7294 arg_m = newTemp(Ity_V128); 7295 arg_d = newTemp(Ity_V128); 7296 res1 = newTemp(Ity_V128); 7297 res2 = newTemp(Ity_V128); 7298 assign(arg_m, getQReg(mreg)); 7299 assign(arg_d, getQReg(dreg)); 7300 } else { 7301 res1 = newTemp(Ity_I64); 7302 res2 = newTemp(Ity_I64); 7303 arg_m = newTemp(Ity_I64); 7304 arg_d = newTemp(Ity_I64); 7305 assign(arg_m, getDRegI64(mreg)); 7306 assign(arg_d, getDRegI64(dreg)); 7307 } 7308 switch (size) { 7309 case 0: 7310 op_lo = Q ? Iop_InterleaveHI8x16 : Iop_InterleaveHI8x8; 7311 op_hi = Q ? Iop_InterleaveLO8x16 : Iop_InterleaveLO8x8; 7312 break; 7313 case 1: 7314 op_lo = Q ? Iop_InterleaveHI16x8 : Iop_InterleaveHI16x4; 7315 op_hi = Q ? Iop_InterleaveLO16x8 : Iop_InterleaveLO16x4; 7316 break; 7317 case 2: 7318 op_lo = Iop_InterleaveHI32x4; 7319 op_hi = Iop_InterleaveLO32x4; 7320 break; 7321 case 3: 7322 return False; 7323 default: 7324 vassert(0); 7325 } 7326 assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d))); 7327 assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d))); 7328 if (Q) { 7329 putQReg(dreg, mkexpr(res1), condT); 7330 putQReg(mreg, mkexpr(res2), condT); 7331 } else { 7332 putDRegI64(dreg, mkexpr(res1), condT); 7333 putDRegI64(mreg, mkexpr(res2), condT); 7334 } 7335 DIP("vzip.%u %c%u, %c%u\n", 7336 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7337 return True; 7338 } else if (B == 8) { 7339 /* VMOVN */ 7340 IROp op; 7341 mreg >>= 1; 7342 switch (size) { 7343 case 0: op = Iop_Shorten16x8; break; 7344 case 1: op = Iop_Shorten32x4; break; 7345 case 2: op = Iop_Shorten64x2; break; 7346 case 3: return False; 7347 default: vassert(0); 7348 } 7349 putDRegI64(dreg, unop(op, getQReg(mreg)), condT); 7350 DIP("vmovn.i%u d%u, q%u\n", 16 << size, dreg, mreg); 7351 return True; 7352 } else if (B == 9 || (B >> 1) == 5) { 7353 /* VQMOVN, VQMOVUN */ 7354 IROp op, op2; 7355 IRTemp tmp; 7356 dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF); 7357 mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF); 7358 if (mreg & 1) 7359 return False; 7360 mreg >>= 1; 7361 switch (size) { 7362 case 0: op2 = Iop_Shorten16x8; break; 7363 case 1: op2 = Iop_Shorten32x4; break; 7364 case 2: op2 = Iop_Shorten64x2; break; 7365 case 3: return False; 7366 default: vassert(0); 7367 } 7368 switch (B & 3) { 7369 case 0: 7370 vassert(0); 7371 case 1: 7372 switch (size) { 7373 case 0: op = Iop_QShortenU16Sx8; break; 7374 case 1: op = Iop_QShortenU32Sx4; break; 7375 case 2: op = Iop_QShortenU64Sx2; break; 7376 case 3: return False; 7377 default: vassert(0); 7378 } 7379 DIP("vqmovun.s%u d%u, q%u\n", 16 << size, dreg, mreg); 7380 break; 7381 case 2: 7382 switch (size) { 7383 case 0: op = Iop_QShortenS16Sx8; break; 7384 case 1: op = Iop_QShortenS32Sx4; break; 7385 case 2: op = Iop_QShortenS64Sx2; break; 7386 case 3: return False; 7387 default: vassert(0); 7388 } 7389 DIP("vqmovn.s%u d%u, q%u\n", 16 << size, dreg, mreg); 7390 break; 7391 case 3: 7392 switch (size) { 7393 case 0: op = Iop_QShortenU16Ux8; break; 7394 case 1: op = Iop_QShortenU32Ux4; break; 7395 case 2: op = Iop_QShortenU64Ux2; break; 7396 case 3: return False; 7397 default: vassert(0); 7398 } 7399 DIP("vqmovn.u%u d%u, q%u\n", 16 << size, dreg, mreg); 7400 break; 7401 default: 7402 vassert(0); 7403 } 7404 res = newTemp(Ity_I64); 7405 tmp = newTemp(Ity_I64); 7406 assign(res, unop(op, getQReg(mreg))); 7407 #ifndef DISABLE_QC_FLAG 7408 assign(tmp, unop(op2, getQReg(mreg))); 7409 setFlag_QC(mkexpr(res), mkexpr(tmp), False, condT); 7410 #endif 7411 putDRegI64(dreg, mkexpr(res), condT); 7412 return True; 7413 } else if (B == 12) { 7414 /* VSHLL (maximum shift) */ 7415 IROp op, cvt; 7416 UInt shift_imm; 7417 if (Q) 7418 return False; 7419 if (dreg & 1) 7420 return False; 7421 dreg >>= 1; 7422 shift_imm = 8 << size; 7423 res = newTemp(Ity_V128); 7424 switch (size) { 7425 case 0: op = Iop_ShlN16x8; cvt = Iop_Longen8Ux8; break; 7426 case 1: op = Iop_ShlN32x4; cvt = Iop_Longen16Ux4; break; 7427 case 2: op = Iop_ShlN64x2; cvt = Iop_Longen32Ux2; break; 7428 case 3: return False; 7429 default: vassert(0); 7430 } 7431 assign(res, binop(op, unop(cvt, getDRegI64(mreg)), 7432 mkU8(shift_imm))); 7433 putQReg(dreg, mkexpr(res), condT); 7434 DIP("vshll.i%u q%u, d%u, #%u\n", 8 << size, dreg, mreg, 8 << size); 7435 return True; 7436 } else if ((B >> 3) == 3 && (B & 3) == 0) { 7437 /* VCVT (half<->single) */ 7438 /* Half-precision extensions are needed to run this */ 7439 vassert(0); // ATC 7440 if (((theInstr >> 18) & 3) != 1) 7441 return False; 7442 if ((theInstr >> 8) & 1) { 7443 if (dreg & 1) 7444 return False; 7445 dreg >>= 1; 7446 putQReg(dreg, unop(Iop_F16toF32x4, getDRegI64(mreg)), 7447 condT); 7448 DIP("vcvt.f32.f16 q%u, d%u\n", dreg, mreg); 7449 } else { 7450 if (mreg & 1) 7451 return False; 7452 mreg >>= 1; 7453 putDRegI64(dreg, unop(Iop_F32toF16x4, getQReg(mreg)), 7454 condT); 7455 DIP("vcvt.f16.f32 d%u, q%u\n", dreg, mreg); 7456 } 7457 return True; 7458 } else { 7459 return False; 7460 } 7461 vassert(0); 7462 return True; 7463 case 3: 7464 if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,0)) { 7465 /* VRECPE */ 7466 IROp op; 7467 F = (theInstr >> 8) & 1; 7468 if (size != 2) 7469 return False; 7470 if (Q) { 7471 op = F ? Iop_Recip32Fx4 : Iop_Recip32x4; 7472 putQReg(dreg, unop(op, getQReg(mreg)), condT); 7473 DIP("vrecpe.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg); 7474 } else { 7475 op = F ? Iop_Recip32Fx2 : Iop_Recip32x2; 7476 putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT); 7477 DIP("vrecpe.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg); 7478 } 7479 return True; 7480 } else if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,1)) { 7481 /* VRSQRTE */ 7482 IROp op; 7483 F = (B >> 2) & 1; 7484 if (size != 2) 7485 return False; 7486 if (F) { 7487 /* fp */ 7488 op = Q ? Iop_Rsqrte32Fx4 : Iop_Rsqrte32Fx2; 7489 } else { 7490 /* unsigned int */ 7491 op = Q ? Iop_Rsqrte32x4 : Iop_Rsqrte32x2; 7492 } 7493 if (Q) { 7494 putQReg(dreg, unop(op, getQReg(mreg)), condT); 7495 DIP("vrsqrte.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg); 7496 } else { 7497 putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT); 7498 DIP("vrsqrte.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg); 7499 } 7500 return True; 7501 } else if ((B >> 3) == 3) { 7502 /* VCVT (fp<->integer) */ 7503 IROp op; 7504 if (size != 2) 7505 return False; 7506 switch ((B >> 1) & 3) { 7507 case 0: 7508 op = Q ? Iop_I32StoFx4 : Iop_I32StoFx2; 7509 DIP("vcvt.f32.s32 %c%u, %c%u\n", 7510 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7511 break; 7512 case 1: 7513 op = Q ? Iop_I32UtoFx4 : Iop_I32UtoFx2; 7514 DIP("vcvt.f32.u32 %c%u, %c%u\n", 7515 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7516 break; 7517 case 2: 7518 op = Q ? Iop_FtoI32Sx4_RZ : Iop_FtoI32Sx2_RZ; 7519 DIP("vcvt.s32.f32 %c%u, %c%u\n", 7520 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7521 break; 7522 case 3: 7523 op = Q ? Iop_FtoI32Ux4_RZ : Iop_FtoI32Ux2_RZ; 7524 DIP("vcvt.u32.f32 %c%u, %c%u\n", 7525 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg); 7526 break; 7527 default: 7528 vassert(0); 7529 } 7530 if (Q) { 7531 putQReg(dreg, unop(op, getQReg(mreg)), condT); 7532 } else { 7533 putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT); 7534 } 7535 return True; 7536 } else { 7537 return False; 7538 } 7539 vassert(0); 7540 return True; 7541 default: 7542 vassert(0); 7543 } 7544 return False; 7545 } 7546 7547 /* A7.4.6 One register and a modified immediate value */ 7548 static 7549 void ppNeonImm(UInt imm, UInt cmode, UInt op) 7550 { 7551 int i; 7552 switch (cmode) { 7553 case 0: case 1: case 8: case 9: 7554 vex_printf("0x%x", imm); 7555 break; 7556 case 2: case 3: case 10: case 11: 7557 vex_printf("0x%x00", imm); 7558 break; 7559 case 4: case 5: 7560 vex_printf("0x%x0000", imm); 7561 break; 7562 case 6: case 7: 7563 vex_printf("0x%x000000", imm); 7564 break; 7565 case 12: 7566 vex_printf("0x%xff", imm); 7567 break; 7568 case 13: 7569 vex_printf("0x%xffff", imm); 7570 break; 7571 case 14: 7572 if (op) { 7573 vex_printf("0x"); 7574 for (i = 7; i >= 0; i--) 7575 vex_printf("%s", (imm & (1 << i)) ? "ff" : "00"); 7576 } else { 7577 vex_printf("0x%x", imm); 7578 } 7579 break; 7580 case 15: 7581 vex_printf("0x%x", imm); 7582 break; 7583 } 7584 } 7585 7586 static 7587 const char *ppNeonImmType(UInt cmode, UInt op) 7588 { 7589 switch (cmode) { 7590 case 0 ... 7: 7591 case 12: case 13: 7592 return "i32"; 7593 case 8 ... 11: 7594 return "i16"; 7595 case 14: 7596 if (op) 7597 return "i64"; 7598 else 7599 return "i8"; 7600 case 15: 7601 if (op) 7602 vassert(0); 7603 else 7604 return "f32"; 7605 default: 7606 vassert(0); 7607 } 7608 } 7609 7610 static 7611 void DIPimm(UInt imm, UInt cmode, UInt op, 7612 const char *instr, UInt Q, UInt dreg) 7613 { 7614 if (vex_traceflags & VEX_TRACE_FE) { 7615 vex_printf("%s.%s %c%u, #", instr, 7616 ppNeonImmType(cmode, op), Q ? 'q' : 'd', dreg); 7617 ppNeonImm(imm, cmode, op); 7618 vex_printf("\n"); 7619 } 7620 } 7621 7622 static 7623 Bool dis_neon_data_1reg_and_imm ( UInt theInstr, IRTemp condT ) 7624 { 7625 UInt dreg = get_neon_d_regno(theInstr); 7626 ULong imm_raw = ((theInstr >> 17) & 0x80) | ((theInstr >> 12) & 0x70) | 7627 (theInstr & 0xf); 7628 ULong imm_raw_pp = imm_raw; 7629 UInt cmode = (theInstr >> 8) & 0xf; 7630 UInt op_bit = (theInstr >> 5) & 1; 7631 ULong imm = 0; 7632 UInt Q = (theInstr >> 6) & 1; 7633 int i, j; 7634 UInt tmp; 7635 IRExpr *imm_val; 7636 IRExpr *expr; 7637 IRTemp tmp_var; 7638 switch(cmode) { 7639 case 7: case 6: 7640 imm_raw = imm_raw << 8; 7641 /* fallthrough */ 7642 case 5: case 4: 7643 imm_raw = imm_raw << 8; 7644 /* fallthrough */ 7645 case 3: case 2: 7646 imm_raw = imm_raw << 8; 7647 /* fallthrough */ 7648 case 0: case 1: 7649 imm = (imm_raw << 32) | imm_raw; 7650 break; 7651 case 11: case 10: 7652 imm_raw = imm_raw << 8; 7653 /* fallthrough */ 7654 case 9: case 8: 7655 imm_raw = (imm_raw << 16) | imm_raw; 7656 imm = (imm_raw << 32) | imm_raw; 7657 break; 7658 case 13: 7659 imm_raw = (imm_raw << 8) | 0xff; 7660 /* fallthrough */ 7661 case 12: 7662 imm_raw = (imm_raw << 8) | 0xff; 7663 imm = (imm_raw << 32) | imm_raw; 7664 break; 7665 case 14: 7666 if (! op_bit) { 7667 for(i = 0; i < 8; i++) { 7668 imm = (imm << 8) | imm_raw; 7669 } 7670 } else { 7671 for(i = 7; i >= 0; i--) { 7672 tmp = 0; 7673 for(j = 0; j < 8; j++) { 7674 tmp = (tmp << 1) | ((imm_raw >> i) & 1); 7675 } 7676 imm = (imm << 8) | tmp; 7677 } 7678 } 7679 break; 7680 case 15: 7681 imm = (imm_raw & 0x80) << 5; 7682 imm |= ~((imm_raw & 0x40) << 5); 7683 for(i = 1; i <= 4; i++) 7684 imm |= (imm_raw & 0x40) << i; 7685 imm |= (imm_raw & 0x7f); 7686 imm = imm << 19; 7687 imm = (imm << 32) | imm; 7688 break; 7689 default: 7690 return False; 7691 } 7692 if (Q) { 7693 imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)); 7694 } else { 7695 imm_val = mkU64(imm); 7696 } 7697 if (((op_bit == 0) && 7698 (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 12) == 12))) || 7699 ((op_bit == 1) && (cmode == 14))) { 7700 /* VMOV (immediate) */ 7701 if (Q) { 7702 putQReg(dreg, imm_val, condT); 7703 } else { 7704 putDRegI64(dreg, imm_val, condT); 7705 } 7706 DIPimm(imm_raw_pp, cmode, op_bit, "vmov", Q, dreg); 7707 return True; 7708 } 7709 if ((op_bit == 1) && 7710 (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 14) == 12))) { 7711 /* VMVN (immediate) */ 7712 if (Q) { 7713 putQReg(dreg, unop(Iop_NotV128, imm_val), condT); 7714 } else { 7715 putDRegI64(dreg, unop(Iop_Not64, imm_val), condT); 7716 } 7717 DIPimm(imm_raw_pp, cmode, op_bit, "vmvn", Q, dreg); 7718 return True; 7719 } 7720 if (Q) { 7721 tmp_var = newTemp(Ity_V128); 7722 assign(tmp_var, getQReg(dreg)); 7723 } else { 7724 tmp_var = newTemp(Ity_I64); 7725 assign(tmp_var, getDRegI64(dreg)); 7726 } 7727 if ((op_bit == 0) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) { 7728 /* VORR (immediate) */ 7729 if (Q) 7730 expr = binop(Iop_OrV128, mkexpr(tmp_var), imm_val); 7731 else 7732 expr = binop(Iop_Or64, mkexpr(tmp_var), imm_val); 7733 DIPimm(imm_raw_pp, cmode, op_bit, "vorr", Q, dreg); 7734 } else if ((op_bit == 1) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) { 7735 /* VBIC (immediate) */ 7736 if (Q) 7737 expr = binop(Iop_AndV128, mkexpr(tmp_var), 7738 unop(Iop_NotV128, imm_val)); 7739 else 7740 expr = binop(Iop_And64, mkexpr(tmp_var), unop(Iop_Not64, imm_val)); 7741 DIPimm(imm_raw_pp, cmode, op_bit, "vbic", Q, dreg); 7742 } else { 7743 return False; 7744 } 7745 if (Q) 7746 putQReg(dreg, expr, condT); 7747 else 7748 putDRegI64(dreg, expr, condT); 7749 return True; 7750 } 7751 7752 /* A7.4 Advanced SIMD data-processing instructions */ 7753 static 7754 Bool dis_neon_data_processing ( UInt theInstr, IRTemp condT ) 7755 { 7756 UInt A = (theInstr >> 19) & 0x1F; 7757 UInt B = (theInstr >> 8) & 0xF; 7758 UInt C = (theInstr >> 4) & 0xF; 7759 UInt U = (theInstr >> 24) & 0x1; 7760 7761 if (! (A & 0x10)) { 7762 return dis_neon_data_3same(theInstr, condT); 7763 } 7764 if (((A & 0x17) == 0x10) && ((C & 0x9) == 0x1)) { 7765 return dis_neon_data_1reg_and_imm(theInstr, condT); 7766 } 7767 if ((C & 1) == 1) { 7768 return dis_neon_data_2reg_and_shift(theInstr, condT); 7769 } 7770 if (((C & 5) == 0) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) { 7771 return dis_neon_data_3diff(theInstr, condT); 7772 } 7773 if (((C & 5) == 4) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) { 7774 return dis_neon_data_2reg_and_scalar(theInstr, condT); 7775 } 7776 if ((A & 0x16) == 0x16) { 7777 if ((U == 0) && ((C & 1) == 0)) { 7778 return dis_neon_vext(theInstr, condT); 7779 } 7780 if ((U != 1) || ((C & 1) == 1)) 7781 return False; 7782 if ((B & 8) == 0) { 7783 return dis_neon_data_2reg_misc(theInstr, condT); 7784 } 7785 if ((B & 12) == 8) { 7786 return dis_neon_vtb(theInstr, condT); 7787 } 7788 if ((B == 12) && ((C & 9) == 0)) { 7789 return dis_neon_vdup(theInstr, condT); 7790 } 7791 } 7792 return False; 7793 } 7794 7795 7796 /*------------------------------------------------------------*/ 7797 /*--- NEON loads and stores ---*/ 7798 /*------------------------------------------------------------*/ 7799 7800 /* For NEON memory operations, we use the standard scheme to handle 7801 conditionalisation: generate a jump around the instruction if the 7802 condition is false. That's only necessary in Thumb mode, however, 7803 since in ARM mode NEON instructions are unconditional. */ 7804 7805 /* A helper function for what follows. It assumes we already went 7806 uncond as per comments at the top of this section. */ 7807 static 7808 void mk_neon_elem_load_to_one_lane( UInt rD, UInt inc, UInt index, 7809 UInt N, UInt size, IRTemp addr ) 7810 { 7811 UInt i; 7812 switch (size) { 7813 case 0: 7814 putDRegI64(rD, triop(Iop_SetElem8x8, getDRegI64(rD), mkU8(index), 7815 loadLE(Ity_I8, mkexpr(addr))), IRTemp_INVALID); 7816 break; 7817 case 1: 7818 putDRegI64(rD, triop(Iop_SetElem16x4, getDRegI64(rD), mkU8(index), 7819 loadLE(Ity_I16, mkexpr(addr))), IRTemp_INVALID); 7820 break; 7821 case 2: 7822 putDRegI64(rD, triop(Iop_SetElem32x2, getDRegI64(rD), mkU8(index), 7823 loadLE(Ity_I32, mkexpr(addr))), IRTemp_INVALID); 7824 break; 7825 default: 7826 vassert(0); 7827 } 7828 for (i = 1; i <= N; i++) { 7829 switch (size) { 7830 case 0: 7831 putDRegI64(rD + i * inc, 7832 triop(Iop_SetElem8x8, 7833 getDRegI64(rD + i * inc), 7834 mkU8(index), 7835 loadLE(Ity_I8, binop(Iop_Add32, 7836 mkexpr(addr), 7837 mkU32(i * 1)))), 7838 IRTemp_INVALID); 7839 break; 7840 case 1: 7841 putDRegI64(rD + i * inc, 7842 triop(Iop_SetElem16x4, 7843 getDRegI64(rD + i * inc), 7844 mkU8(index), 7845 loadLE(Ity_I16, binop(Iop_Add32, 7846 mkexpr(addr), 7847 mkU32(i * 2)))), 7848 IRTemp_INVALID); 7849 break; 7850 case 2: 7851 putDRegI64(rD + i * inc, 7852 triop(Iop_SetElem32x2, 7853 getDRegI64(rD + i * inc), 7854 mkU8(index), 7855 loadLE(Ity_I32, binop(Iop_Add32, 7856 mkexpr(addr), 7857 mkU32(i * 4)))), 7858 IRTemp_INVALID); 7859 break; 7860 default: 7861 vassert(0); 7862 } 7863 } 7864 } 7865 7866 /* A(nother) helper function for what follows. It assumes we already 7867 went uncond as per comments at the top of this section. */ 7868 static 7869 void mk_neon_elem_store_from_one_lane( UInt rD, UInt inc, UInt index, 7870 UInt N, UInt size, IRTemp addr ) 7871 { 7872 UInt i; 7873 switch (size) { 7874 case 0: 7875 storeLE(mkexpr(addr), 7876 binop(Iop_GetElem8x8, getDRegI64(rD), mkU8(index))); 7877 break; 7878 case 1: 7879 storeLE(mkexpr(addr), 7880 binop(Iop_GetElem16x4, getDRegI64(rD), mkU8(index))); 7881 break; 7882 case 2: 7883 storeLE(mkexpr(addr), 7884 binop(Iop_GetElem32x2, getDRegI64(rD), mkU8(index))); 7885 break; 7886 default: 7887 vassert(0); 7888 } 7889 for (i = 1; i <= N; i++) { 7890 switch (size) { 7891 case 0: 7892 storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 1)), 7893 binop(Iop_GetElem8x8, getDRegI64(rD + i * inc), 7894 mkU8(index))); 7895 break; 7896 case 1: 7897 storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 2)), 7898 binop(Iop_GetElem16x4, getDRegI64(rD + i * inc), 7899 mkU8(index))); 7900 break; 7901 case 2: 7902 storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 4)), 7903 binop(Iop_GetElem32x2, getDRegI64(rD + i * inc), 7904 mkU8(index))); 7905 break; 7906 default: 7907 vassert(0); 7908 } 7909 } 7910 } 7911 7912 /* A7.7 Advanced SIMD element or structure load/store instructions */ 7913 static 7914 Bool dis_neon_elem_or_struct_load ( UInt theInstr, 7915 Bool isT, IRTemp condT ) 7916 { 7917 # define INSN(_bMax,_bMin) SLICE_UInt(theInstr, (_bMax), (_bMin)) 7918 UInt A = INSN(23,23); 7919 UInt B = INSN(11,8); 7920 UInt L = INSN(21,21); 7921 UInt rD = (INSN(22,22) << 4) | INSN(15,12); 7922 UInt rN = INSN(19,16); 7923 UInt rM = INSN(3,0); 7924 UInt N, size, i, j; 7925 UInt inc; 7926 UInt regs = 1; 7927 7928 if (isT) { 7929 vassert(condT != IRTemp_INVALID); 7930 } else { 7931 vassert(condT == IRTemp_INVALID); 7932 } 7933 /* So now, if condT is not IRTemp_INVALID, we know we're 7934 dealing with Thumb code. */ 7935 7936 if (INSN(20,20) != 0) 7937 return False; 7938 7939 IRTemp initialRn = newTemp(Ity_I32); 7940 assign(initialRn, isT ? getIRegT(rN) : getIRegA(rN)); 7941 7942 IRTemp initialRm = newTemp(Ity_I32); 7943 assign(initialRm, isT ? getIRegT(rM) : getIRegA(rM)); 7944 7945 if (A) { 7946 N = B & 3; 7947 if ((B >> 2) < 3) { 7948 /* VSTn / VLDn (n-element structure from/to one lane) */ 7949 7950 size = B >> 2; 7951 7952 switch (size) { 7953 case 0: i = INSN(7,5); inc = 1; break; 7954 case 1: i = INSN(7,6); inc = INSN(5,5) ? 2 : 1; break; 7955 case 2: i = INSN(7,7); inc = INSN(6,6) ? 2 : 1; break; 7956 case 3: return False; 7957 default: vassert(0); 7958 } 7959 7960 IRTemp addr = newTemp(Ity_I32); 7961 assign(addr, mkexpr(initialRn)); 7962 7963 // go uncond 7964 if (condT != IRTemp_INVALID) 7965 mk_skip_over_T32_if_cond_is_false(condT); 7966 // now uncond 7967 7968 if (L) 7969 mk_neon_elem_load_to_one_lane(rD, inc, i, N, size, addr); 7970 else 7971 mk_neon_elem_store_from_one_lane(rD, inc, i, N, size, addr); 7972 DIP("v%s%u.%u {", L ? "ld" : "st", N + 1, 8 << size); 7973 for (j = 0; j <= N; j++) { 7974 if (j) 7975 DIP(", "); 7976 DIP("d%u[%u]", rD + j * inc, i); 7977 } 7978 DIP("}, [r%u]", rN); 7979 if (rM != 13 && rM != 15) { 7980 DIP(", r%u\n", rM); 7981 } else { 7982 DIP("%s\n", (rM != 15) ? "!" : ""); 7983 } 7984 } else { 7985 /* VLDn (single element to all lanes) */ 7986 UInt r; 7987 if (L == 0) 7988 return False; 7989 7990 inc = INSN(5,5) + 1; 7991 size = INSN(7,6); 7992 7993 /* size == 3 and size == 2 cases differ in alignment constraints */ 7994 if (size == 3 && N == 3 && INSN(4,4) == 1) 7995 size = 2; 7996 7997 if (size == 0 && N == 0 && INSN(4,4) == 1) 7998 return False; 7999 if (N == 2 && INSN(4,4) == 1) 8000 return False; 8001 if (size == 3) 8002 return False; 8003 8004 // go uncond 8005 if (condT != IRTemp_INVALID) 8006 mk_skip_over_T32_if_cond_is_false(condT); 8007 // now uncond 8008 8009 IRTemp addr = newTemp(Ity_I32); 8010 assign(addr, mkexpr(initialRn)); 8011 8012 if (N == 0 && INSN(5,5)) 8013 regs = 2; 8014 8015 for (r = 0; r < regs; r++) { 8016 switch (size) { 8017 case 0: 8018 putDRegI64(rD + r, unop(Iop_Dup8x8, 8019 loadLE(Ity_I8, mkexpr(addr))), 8020 IRTemp_INVALID); 8021 break; 8022 case 1: 8023 putDRegI64(rD + r, unop(Iop_Dup16x4, 8024 loadLE(Ity_I16, mkexpr(addr))), 8025 IRTemp_INVALID); 8026 break; 8027 case 2: 8028 putDRegI64(rD + r, unop(Iop_Dup32x2, 8029 loadLE(Ity_I32, mkexpr(addr))), 8030 IRTemp_INVALID); 8031 break; 8032 default: 8033 vassert(0); 8034 } 8035 for (i = 1; i <= N; i++) { 8036 switch (size) { 8037 case 0: 8038 putDRegI64(rD + r + i * inc, 8039 unop(Iop_Dup8x8, 8040 loadLE(Ity_I8, binop(Iop_Add32, 8041 mkexpr(addr), 8042 mkU32(i * 1)))), 8043 IRTemp_INVALID); 8044 break; 8045 case 1: 8046 putDRegI64(rD + r + i * inc, 8047 unop(Iop_Dup16x4, 8048 loadLE(Ity_I16, binop(Iop_Add32, 8049 mkexpr(addr), 8050 mkU32(i * 2)))), 8051 IRTemp_INVALID); 8052 break; 8053 case 2: 8054 putDRegI64(rD + r + i * inc, 8055 unop(Iop_Dup32x2, 8056 loadLE(Ity_I32, binop(Iop_Add32, 8057 mkexpr(addr), 8058 mkU32(i * 4)))), 8059 IRTemp_INVALID); 8060 break; 8061 default: 8062 vassert(0); 8063 } 8064 } 8065 } 8066 DIP("vld%u.%u {", N + 1, 8 << size); 8067 for (r = 0; r < regs; r++) { 8068 for (i = 0; i <= N; i++) { 8069 if (i || r) 8070 DIP(", "); 8071 DIP("d%u[]", rD + r + i * inc); 8072 } 8073 } 8074 DIP("}, [r%u]", rN); 8075 if (rM != 13 && rM != 15) { 8076 DIP(", r%u\n", rM); 8077 } else { 8078 DIP("%s\n", (rM != 15) ? "!" : ""); 8079 } 8080 } 8081 /* Writeback. We're uncond here, so no condT-ing. */ 8082 if (rM != 15) { 8083 if (rM == 13) { 8084 IRExpr* e = binop(Iop_Add32, 8085 mkexpr(initialRn), 8086 mkU32((1 << size) * (N + 1))); 8087 if (isT) 8088 putIRegT(rN, e, IRTemp_INVALID); 8089 else 8090 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring); 8091 } else { 8092 IRExpr* e = binop(Iop_Add32, 8093 mkexpr(initialRn), 8094 mkexpr(initialRm)); 8095 if (isT) 8096 putIRegT(rN, e, IRTemp_INVALID); 8097 else 8098 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring); 8099 } 8100 } 8101 return True; 8102 } else { 8103 IRTemp tmp; 8104 UInt r, elems; 8105 /* VSTn / VLDn (multiple n-element structures) */ 8106 if (B == BITS4(0,0,1,0) || B == BITS4(0,1,1,0) 8107 || B == BITS4(0,1,1,1) || B == BITS4(1,0,1,0)) { 8108 N = 0; 8109 } else if (B == BITS4(0,0,1,1) || B == BITS4(1,0,0,0) 8110 || B == BITS4(1,0,0,1)) { 8111 N = 1; 8112 } else if (B == BITS4(0,1,0,0) || B == BITS4(0,1,0,1)) { 8113 N = 2; 8114 } else if (B == BITS4(0,0,0,0) || B == BITS4(0,0,0,1)) { 8115 N = 3; 8116 } else { 8117 return False; 8118 } 8119 inc = (B & 1) + 1; 8120 if (N == 1 && B == BITS4(0,0,1,1)) { 8121 regs = 2; 8122 } else if (N == 0) { 8123 if (B == BITS4(1,0,1,0)) { 8124 regs = 2; 8125 } else if (B == BITS4(0,1,1,0)) { 8126 regs = 3; 8127 } else if (B == BITS4(0,0,1,0)) { 8128 regs = 4; 8129 } 8130 } 8131 8132 size = INSN(7,6); 8133 if (N == 0 && size == 3) 8134 size = 2; 8135 if (size == 3) 8136 return False; 8137 8138 elems = 8 / (1 << size); 8139 8140 // go uncond 8141 if (condT != IRTemp_INVALID) 8142 mk_skip_over_T32_if_cond_is_false(condT); 8143 // now uncond 8144 8145 IRTemp addr = newTemp(Ity_I32); 8146 assign(addr, mkexpr(initialRn)); 8147 8148 for (r = 0; r < regs; r++) { 8149 for (i = 0; i < elems; i++) { 8150 if (L) 8151 mk_neon_elem_load_to_one_lane(rD + r, inc, i, N, size, addr); 8152 else 8153 mk_neon_elem_store_from_one_lane(rD + r, inc, i, N, size, addr); 8154 tmp = newTemp(Ity_I32); 8155 assign(tmp, binop(Iop_Add32, mkexpr(addr), 8156 mkU32((1 << size) * (N + 1)))); 8157 addr = tmp; 8158 } 8159 } 8160 /* Writeback */ 8161 if (rM != 15) { 8162 if (rM == 13) { 8163 IRExpr* e = binop(Iop_Add32, 8164 mkexpr(initialRn), 8165 mkU32(8 * (N + 1) * regs)); 8166 if (isT) 8167 putIRegT(rN, e, IRTemp_INVALID); 8168 else 8169 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring); 8170 } else { 8171 IRExpr* e = binop(Iop_Add32, 8172 mkexpr(initialRn), 8173 mkexpr(initialRm)); 8174 if (isT) 8175 putIRegT(rN, e, IRTemp_INVALID); 8176 else 8177 putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring); 8178 } 8179 } 8180 DIP("v%s%u.%u {", L ? "ld" : "st", N + 1, 8 << INSN(7,6)); 8181 if ((inc == 1 && regs * (N + 1) > 1) 8182 || (inc == 2 && regs > 1 && N > 0)) { 8183 DIP("d%u-d%u", rD, rD + regs * (N + 1) - 1); 8184 } else { 8185 for (r = 0; r < regs; r++) { 8186 for (i = 0; i <= N; i++) { 8187 if (i || r) 8188 DIP(", "); 8189 DIP("d%u", rD + r + i * inc); 8190 } 8191 } 8192 } 8193 DIP("}, [r%u]", rN); 8194 if (rM != 13 && rM != 15) { 8195 DIP(", r%u\n", rM); 8196 } else { 8197 DIP("%s\n", (rM != 15) ? "!" : ""); 8198 } 8199 return True; 8200 } 8201 # undef INSN 8202 } 8203 8204 8205 /*------------------------------------------------------------*/ 8206 /*--- NEON, top level control ---*/ 8207 /*------------------------------------------------------------*/ 8208 8209 /* Both ARM and Thumb */ 8210 8211 /* Translate a NEON instruction. If successful, returns 8212 True and *dres may or may not be updated. If failure, returns 8213 False and doesn't change *dres nor create any IR. 8214 8215 The Thumb and ARM encodings are similar for the 24 bottom bits, but 8216 the top 8 bits are slightly different. In both cases, the caller 8217 must pass the entire 32 bits. Callers may pass any instruction; 8218 this ignores non-NEON ones. 8219 8220 Caller must supply an IRTemp 'condT' holding the gating condition, 8221 or IRTemp_INVALID indicating the insn is always executed. In ARM 8222 code, this must always be IRTemp_INVALID because NEON insns are 8223 unconditional for ARM. 8224 8225 Finally, the caller must indicate whether this occurs in ARM or in 8226 Thumb code. 8227 */ 8228 static Bool decode_NEON_instruction ( 8229 /*MOD*/DisResult* dres, 8230 UInt insn32, 8231 IRTemp condT, 8232 Bool isT 8233 ) 8234 { 8235 # define INSN(_bMax,_bMin) SLICE_UInt(insn32, (_bMax), (_bMin)) 8236 8237 /* There are two kinds of instruction to deal with: load/store and 8238 data processing. In each case, in ARM mode we merely identify 8239 the kind, and pass it on to the relevant sub-handler. In Thumb 8240 mode we identify the kind, swizzle the bits around to make it 8241 have the same encoding as in ARM, and hand it on to the 8242 sub-handler. 8243 */ 8244 8245 /* In ARM mode, NEON instructions can't be conditional. */ 8246 if (!isT) 8247 vassert(condT == IRTemp_INVALID); 8248 8249 /* Data processing: 8250 Thumb: 111U 1111 AAAA Axxx xxxx BBBB CCCC xxxx 8251 ARM: 1111 001U AAAA Axxx xxxx BBBB CCCC xxxx 8252 */ 8253 if (!isT && INSN(31,25) == BITS7(1,1,1,1,0,0,1)) { 8254 // ARM, DP 8255 return dis_neon_data_processing(INSN(31,0), condT); 8256 } 8257 if (isT && INSN(31,29) == BITS3(1,1,1) 8258 && INSN(27,24) == BITS4(1,1,1,1)) { 8259 // Thumb, DP 8260 UInt reformatted = INSN(23,0); 8261 reformatted |= (INSN(28,28) << 24); // U bit 8262 reformatted |= (BITS7(1,1,1,1,0,0,1) << 25); 8263 return dis_neon_data_processing(reformatted, condT); 8264 } 8265 8266 /* Load/store: 8267 Thumb: 1111 1001 AxL0 xxxx xxxx BBBB xxxx xxxx 8268 ARM: 1111 0100 AxL0 xxxx xxxx BBBB xxxx xxxx 8269 */ 8270 if (!isT && INSN(31,24) == BITS8(1,1,1,1,0,1,0,0)) { 8271 // ARM, memory 8272 return dis_neon_elem_or_struct_load(INSN(31,0), isT, condT); 8273 } 8274 if (isT && INSN(31,24) == BITS8(1,1,1,1,1,0,0,1)) { 8275 UInt reformatted = INSN(23,0); 8276 reformatted |= (BITS8(1,1,1,1,0,1,0,0) << 24); 8277 return dis_neon_elem_or_struct_load(reformatted, isT, condT); 8278 } 8279 8280 /* Doesn't match. */ 8281 return False; 8282 8283 # undef INSN 8284 } 8285 8286 8287 /*------------------------------------------------------------*/ 8288 /*--- V6 MEDIA instructions ---*/ 8289 /*------------------------------------------------------------*/ 8290 8291 /* Both ARM and Thumb */ 8292 8293 /* Translate a V6 media instruction. If successful, returns 8294 True and *dres may or may not be updated. If failure, returns 8295 False and doesn't change *dres nor create any IR. 8296 8297 The Thumb and ARM encodings are completely different. In Thumb 8298 mode, the caller must pass the entire 32 bits. In ARM mode it must 8299 pass the lower 28 bits. Apart from that, callers may pass any 8300 instruction; this function ignores anything it doesn't recognise. 8301 8302 Caller must supply an IRTemp 'condT' holding the gating condition, 8303 or IRTemp_INVALID indicating the insn is always executed. 8304 8305 Caller must also supply an ARMCondcode 'cond'. This is only used 8306 for debug printing, no other purpose. For ARM, this is simply the 8307 top 4 bits of the original instruction. For Thumb, the condition 8308 is not (really) known until run time, and so ARMCondAL should be 8309 passed, only so that printing of these instructions does not show 8310 any condition. 8311 8312 Finally, the caller must indicate whether this occurs in ARM or in 8313 Thumb code. 8314 */ 8315 static Bool decode_V6MEDIA_instruction ( 8316 /*MOD*/DisResult* dres, 8317 UInt insnv6m, 8318 IRTemp condT, 8319 ARMCondcode conq, 8320 Bool isT 8321 ) 8322 { 8323 # define INSNA(_bMax,_bMin) SLICE_UInt(insnv6m, (_bMax), (_bMin)) 8324 # define INSNT0(_bMax,_bMin) SLICE_UInt( ((insnv6m >> 16) & 0xFFFF), \ 8325 (_bMax), (_bMin) ) 8326 # define INSNT1(_bMax,_bMin) SLICE_UInt( ((insnv6m >> 0) & 0xFFFF), \ 8327 (_bMax), (_bMin) ) 8328 HChar dis_buf[128]; 8329 dis_buf[0] = 0; 8330 8331 if (isT) { 8332 vassert(conq == ARMCondAL); 8333 } else { 8334 vassert(INSNA(31,28) == BITS4(0,0,0,0)); // caller's obligation 8335 vassert(conq >= ARMCondEQ && conq <= ARMCondAL); 8336 } 8337 8338 /* ----------- smulbb, smulbt, smultb, smultt ----------- */ 8339 { 8340 UInt regD = 99, regM = 99, regN = 99, bitM = 0, bitN = 0; 8341 Bool gate = False; 8342 8343 if (isT) { 8344 if (INSNT0(15,4) == 0xFB1 && INSNT1(15,12) == BITS4(1,1,1,1) 8345 && INSNT1(7,6) == BITS2(0,0)) { 8346 regD = INSNT1(11,8); 8347 regM = INSNT1(3,0); 8348 regN = INSNT0(3,0); 8349 bitM = INSNT1(4,4); 8350 bitN = INSNT1(5,5); 8351 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8352 gate = True; 8353 } 8354 } else { 8355 if (BITS8(0,0,0,1,0,1,1,0) == INSNA(27,20) && 8356 BITS4(0,0,0,0) == INSNA(15,12) && 8357 BITS4(1,0,0,0) == (INSNA(7,4) & BITS4(1,0,0,1)) ) { 8358 regD = INSNA(19,16); 8359 regM = INSNA(11,8); 8360 regN = INSNA(3,0); 8361 bitM = INSNA(6,6); 8362 bitN = INSNA(5,5); 8363 if (regD != 15 && regN != 15 && regM != 15) 8364 gate = True; 8365 } 8366 } 8367 8368 if (gate) { 8369 IRTemp srcN = newTemp(Ity_I32); 8370 IRTemp srcM = newTemp(Ity_I32); 8371 IRTemp res = newTemp(Ity_I32); 8372 8373 assign( srcN, binop(Iop_Sar32, 8374 binop(Iop_Shl32, 8375 isT ? getIRegT(regN) : getIRegA(regN), 8376 mkU8(bitN ? 0 : 16)), mkU8(16)) ); 8377 assign( srcM, binop(Iop_Sar32, 8378 binop(Iop_Shl32, 8379 isT ? getIRegT(regM) : getIRegA(regM), 8380 mkU8(bitM ? 0 : 16)), mkU8(16)) ); 8381 assign( res, binop(Iop_Mul32, mkexpr(srcN), mkexpr(srcM)) ); 8382 8383 if (isT) 8384 putIRegT( regD, mkexpr(res), condT ); 8385 else 8386 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8387 8388 DIP( "smul%c%c%s r%u, r%u, r%u\n", bitN ? 't' : 'b', bitM ? 't' : 'b', 8389 nCC(conq), regD, regN, regM ); 8390 return True; 8391 } 8392 /* fall through */ 8393 } 8394 8395 /* ------------ smulwb<y><c> <Rd>,<Rn>,<Rm> ------------- */ 8396 /* ------------ smulwt<y><c> <Rd>,<Rn>,<Rm> ------------- */ 8397 { 8398 UInt regD = 99, regN = 99, regM = 99, bitM = 0; 8399 Bool gate = False; 8400 8401 if (isT) { 8402 if (INSNT0(15,4) == 0xFB3 && INSNT1(15,12) == BITS4(1,1,1,1) 8403 && INSNT1(7,5) == BITS3(0,0,0)) { 8404 regN = INSNT0(3,0); 8405 regD = INSNT1(11,8); 8406 regM = INSNT1(3,0); 8407 bitM = INSNT1(4,4); 8408 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8409 gate = True; 8410 } 8411 } else { 8412 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) && 8413 INSNA(15,12) == BITS4(0,0,0,0) && 8414 (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,1,0)) { 8415 regD = INSNA(19,16); 8416 regN = INSNA(3,0); 8417 regM = INSNA(11,8); 8418 bitM = INSNA(6,6); 8419 if (regD != 15 && regN != 15 && regM != 15) 8420 gate = True; 8421 } 8422 } 8423 8424 if (gate) { 8425 IRTemp irt_prod = newTemp(Ity_I64); 8426 8427 assign( irt_prod, 8428 binop(Iop_MullS32, 8429 isT ? getIRegT(regN) : getIRegA(regN), 8430 binop(Iop_Sar32, 8431 binop(Iop_Shl32, 8432 isT ? getIRegT(regM) : getIRegA(regM), 8433 mkU8(bitM ? 0 : 16)), 8434 mkU8(16))) ); 8435 8436 IRExpr* ire_result = binop(Iop_Or32, 8437 binop( Iop_Shl32, 8438 unop(Iop_64HIto32, mkexpr(irt_prod)), 8439 mkU8(16) ), 8440 binop( Iop_Shr32, 8441 unop(Iop_64to32, mkexpr(irt_prod)), 8442 mkU8(16) ) ); 8443 8444 if (isT) 8445 putIRegT( regD, ire_result, condT ); 8446 else 8447 putIRegA( regD, ire_result, condT, Ijk_Boring ); 8448 8449 DIP("smulw%c%s r%u, r%u, r%u\n", 8450 bitM ? 't' : 'b', nCC(conq),regD,regN,regM); 8451 return True; 8452 } 8453 /* fall through */ 8454 } 8455 8456 /* ------------ pkhbt<c> Rd, Rn, Rm {,LSL #imm} ------------- */ 8457 /* ------------ pkhtb<c> Rd, Rn, Rm {,ASR #imm} ------------- */ 8458 { 8459 UInt regD = 99, regN = 99, regM = 99, imm5 = 99, shift_type = 99; 8460 Bool tbform = False; 8461 Bool gate = False; 8462 8463 if (isT) { 8464 if (INSNT0(15,4) == 0xEAC 8465 && INSNT1(15,15) == 0 && INSNT1(4,4) == 0) { 8466 regN = INSNT0(3,0); 8467 regD = INSNT1(11,8); 8468 regM = INSNT1(3,0); 8469 imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6); 8470 shift_type = (INSNT1(5,5) << 1) | 0; 8471 tbform = (INSNT1(5,5) == 0) ? False : True; 8472 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8473 gate = True; 8474 } 8475 } else { 8476 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) && 8477 INSNA(5,4) == BITS2(0,1) && 8478 (INSNA(6,6) == 0 || INSNA(6,6) == 1) ) { 8479 regD = INSNA(15,12); 8480 regN = INSNA(19,16); 8481 regM = INSNA(3,0); 8482 imm5 = INSNA(11,7); 8483 shift_type = (INSNA(6,6) << 1) | 0; 8484 tbform = (INSNA(6,6) == 0) ? False : True; 8485 if (regD != 15 && regN != 15 && regM != 15) 8486 gate = True; 8487 } 8488 } 8489 8490 if (gate) { 8491 IRTemp irt_regM = newTemp(Ity_I32); 8492 IRTemp irt_regM_shift = newTemp(Ity_I32); 8493 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) ); 8494 compute_result_and_C_after_shift_by_imm5( 8495 dis_buf, &irt_regM_shift, NULL, irt_regM, shift_type, imm5, regM ); 8496 8497 UInt mask = (tbform == True) ? 0x0000FFFF : 0xFFFF0000; 8498 IRExpr* ire_result 8499 = binop( Iop_Or32, 8500 binop(Iop_And32, mkexpr(irt_regM_shift), mkU32(mask)), 8501 binop(Iop_And32, isT ? getIRegT(regN) : getIRegA(regN), 8502 unop(Iop_Not32, mkU32(mask))) ); 8503 8504 if (isT) 8505 putIRegT( regD, ire_result, condT ); 8506 else 8507 putIRegA( regD, ire_result, condT, Ijk_Boring ); 8508 8509 DIP( "pkh%s%s r%u, r%u, r%u %s\n", tbform ? "tb" : "bt", 8510 nCC(conq), regD, regN, regM, dis_buf ); 8511 8512 return True; 8513 } 8514 /* fall through */ 8515 } 8516 8517 /* ---------- usat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */ 8518 { 8519 UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99; 8520 Bool gate = False; 8521 8522 if (isT) { 8523 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,1,0) 8524 && INSNT0(4,4) == 0 8525 && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) { 8526 regD = INSNT1(11,8); 8527 regN = INSNT0(3,0); 8528 shift_type = (INSNT0(5,5) << 1) | 0; 8529 imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6); 8530 sat_imm = INSNT1(4,0); 8531 if (!isBadRegT(regD) && !isBadRegT(regN)) 8532 gate = True; 8533 if (shift_type == BITS2(1,0) && imm5 == 0) 8534 gate = False; 8535 } 8536 } else { 8537 if (INSNA(27,21) == BITS7(0,1,1,0,1,1,1) && 8538 INSNA(5,4) == BITS2(0,1)) { 8539 regD = INSNA(15,12); 8540 regN = INSNA(3,0); 8541 shift_type = (INSNA(6,6) << 1) | 0; 8542 imm5 = INSNA(11,7); 8543 sat_imm = INSNA(20,16); 8544 if (regD != 15 && regN != 15) 8545 gate = True; 8546 } 8547 } 8548 8549 if (gate) { 8550 IRTemp irt_regN = newTemp(Ity_I32); 8551 IRTemp irt_regN_shift = newTemp(Ity_I32); 8552 IRTemp irt_sat_Q = newTemp(Ity_I32); 8553 IRTemp irt_result = newTemp(Ity_I32); 8554 8555 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 8556 compute_result_and_C_after_shift_by_imm5( 8557 dis_buf, &irt_regN_shift, NULL, 8558 irt_regN, shift_type, imm5, regN ); 8559 8560 armUnsignedSatQ( &irt_result, &irt_sat_Q, irt_regN_shift, sat_imm ); 8561 or_into_QFLAG32( mkexpr(irt_sat_Q), condT ); 8562 8563 if (isT) 8564 putIRegT( regD, mkexpr(irt_result), condT ); 8565 else 8566 putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring ); 8567 8568 DIP("usat%s r%u, #0x%04x, %s\n", 8569 nCC(conq), regD, imm5, dis_buf); 8570 return True; 8571 } 8572 /* fall through */ 8573 } 8574 8575 /* ----------- ssat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */ 8576 { 8577 UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99; 8578 Bool gate = False; 8579 8580 if (isT) { 8581 if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0) 8582 && INSNT0(4,4) == 0 8583 && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) { 8584 regD = INSNT1(11,8); 8585 regN = INSNT0(3,0); 8586 shift_type = (INSNT0(5,5) << 1) | 0; 8587 imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6); 8588 sat_imm = INSNT1(4,0) + 1; 8589 if (!isBadRegT(regD) && !isBadRegT(regN)) 8590 gate = True; 8591 if (shift_type == BITS2(1,0) && imm5 == 0) 8592 gate = False; 8593 } 8594 } else { 8595 if (INSNA(27,21) == BITS7(0,1,1,0,1,0,1) && 8596 INSNA(5,4) == BITS2(0,1)) { 8597 regD = INSNA(15,12); 8598 regN = INSNA(3,0); 8599 shift_type = (INSNA(6,6) << 1) | 0; 8600 imm5 = INSNA(11,7); 8601 sat_imm = INSNA(20,16) + 1; 8602 if (regD != 15 && regN != 15) 8603 gate = True; 8604 } 8605 } 8606 8607 if (gate) { 8608 IRTemp irt_regN = newTemp(Ity_I32); 8609 IRTemp irt_regN_shift = newTemp(Ity_I32); 8610 IRTemp irt_sat_Q = newTemp(Ity_I32); 8611 IRTemp irt_result = newTemp(Ity_I32); 8612 8613 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 8614 compute_result_and_C_after_shift_by_imm5( 8615 dis_buf, &irt_regN_shift, NULL, 8616 irt_regN, shift_type, imm5, regN ); 8617 8618 armSignedSatQ( irt_regN_shift, sat_imm, &irt_result, &irt_sat_Q ); 8619 or_into_QFLAG32( mkexpr(irt_sat_Q), condT ); 8620 8621 if (isT) 8622 putIRegT( regD, mkexpr(irt_result), condT ); 8623 else 8624 putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring ); 8625 8626 DIP( "ssat%s r%u, #0x%04x, %s\n", 8627 nCC(conq), regD, imm5, dis_buf); 8628 return True; 8629 } 8630 /* fall through */ 8631 } 8632 8633 /* -------------- usat16<c> <Rd>,#<imm4>,<Rn> --------------- */ 8634 { 8635 UInt regD = 99, regN = 99, sat_imm = 99; 8636 Bool gate = False; 8637 8638 if (isT) { 8639 if (INSNT0(15,4) == 0xF3A && (INSNT1(15,0) & 0xF0F0) == 0x0000) { 8640 regN = INSNT0(3,0); 8641 regD = INSNT1(11,8); 8642 sat_imm = INSNT1(3,0); 8643 if (!isBadRegT(regD) && !isBadRegT(regN)) 8644 gate = True; 8645 } 8646 } else { 8647 if (INSNA(27,20) == BITS8(0,1,1,0,1,1,1,0) && 8648 INSNA(11,8) == BITS4(1,1,1,1) && 8649 INSNA(7,4) == BITS4(0,0,1,1)) { 8650 regD = INSNA(15,12); 8651 regN = INSNA(3,0); 8652 sat_imm = INSNA(19,16); 8653 if (regD != 15 && regN != 15) 8654 gate = True; 8655 } 8656 } 8657 8658 if (gate) { 8659 IRTemp irt_regN = newTemp(Ity_I32); 8660 IRTemp irt_regN_lo = newTemp(Ity_I32); 8661 IRTemp irt_regN_hi = newTemp(Ity_I32); 8662 IRTemp irt_Q_lo = newTemp(Ity_I32); 8663 IRTemp irt_Q_hi = newTemp(Ity_I32); 8664 IRTemp irt_res_lo = newTemp(Ity_I32); 8665 IRTemp irt_res_hi = newTemp(Ity_I32); 8666 8667 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 8668 assign( irt_regN_lo, binop( Iop_Sar32, 8669 binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 8670 mkU8(16)) ); 8671 assign( irt_regN_hi, binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)) ); 8672 8673 armUnsignedSatQ( &irt_res_lo, &irt_Q_lo, irt_regN_lo, sat_imm ); 8674 or_into_QFLAG32( mkexpr(irt_Q_lo), condT ); 8675 8676 armUnsignedSatQ( &irt_res_hi, &irt_Q_hi, irt_regN_hi, sat_imm ); 8677 or_into_QFLAG32( mkexpr(irt_Q_hi), condT ); 8678 8679 IRExpr* ire_result = binop( Iop_Or32, 8680 binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)), 8681 mkexpr(irt_res_lo) ); 8682 8683 if (isT) 8684 putIRegT( regD, ire_result, condT ); 8685 else 8686 putIRegA( regD, ire_result, condT, Ijk_Boring ); 8687 8688 DIP( "usat16%s r%u, #0x%04x, r%u\n", nCC(conq), regD, sat_imm, regN ); 8689 return True; 8690 } 8691 /* fall through */ 8692 } 8693 8694 /* -------------- uadd16<c> <Rd>,<Rn>,<Rm> -------------- */ 8695 { 8696 UInt regD = 99, regN = 99, regM = 99; 8697 Bool gate = False; 8698 8699 if (isT) { 8700 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF040) { 8701 regN = INSNT0(3,0); 8702 regD = INSNT1(11,8); 8703 regM = INSNT1(3,0); 8704 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8705 gate = True; 8706 } 8707 } else { 8708 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) && 8709 INSNA(11,8) == BITS4(1,1,1,1) && 8710 INSNA(7,4) == BITS4(0,0,0,1)) { 8711 regD = INSNA(15,12); 8712 regN = INSNA(19,16); 8713 regM = INSNA(3,0); 8714 if (regD != 15 && regN != 15 && regM != 15) 8715 gate = True; 8716 } 8717 } 8718 8719 if (gate) { 8720 IRTemp rNt = newTemp(Ity_I32); 8721 IRTemp rMt = newTemp(Ity_I32); 8722 IRTemp res = newTemp(Ity_I32); 8723 IRTemp reso = newTemp(Ity_I32); 8724 8725 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 8726 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 8727 8728 assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt))); 8729 if (isT) 8730 putIRegT( regD, mkexpr(res), condT ); 8731 else 8732 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8733 8734 assign(reso, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt))); 8735 set_GE_32_10_from_bits_31_15(reso, condT); 8736 8737 DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 8738 return True; 8739 } 8740 /* fall through */ 8741 } 8742 8743 /* -------------- sadd16<c> <Rd>,<Rn>,<Rm> -------------- */ 8744 { 8745 UInt regD = 99, regN = 99, regM = 99; 8746 Bool gate = False; 8747 8748 if (isT) { 8749 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF000) { 8750 regN = INSNT0(3,0); 8751 regD = INSNT1(11,8); 8752 regM = INSNT1(3,0); 8753 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8754 gate = True; 8755 } 8756 } else { 8757 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 8758 INSNA(11,8) == BITS4(1,1,1,1) && 8759 INSNA(7,4) == BITS4(0,0,0,1)) { 8760 regD = INSNA(15,12); 8761 regN = INSNA(19,16); 8762 regM = INSNA(3,0); 8763 if (regD != 15 && regN != 15 && regM != 15) 8764 gate = True; 8765 } 8766 } 8767 8768 if (gate) { 8769 IRTemp rNt = newTemp(Ity_I32); 8770 IRTemp rMt = newTemp(Ity_I32); 8771 IRTemp res = newTemp(Ity_I32); 8772 IRTemp reso = newTemp(Ity_I32); 8773 8774 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 8775 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 8776 8777 assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt))); 8778 if (isT) 8779 putIRegT( regD, mkexpr(res), condT ); 8780 else 8781 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8782 8783 assign(reso, unop(Iop_Not32, 8784 binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt)))); 8785 set_GE_32_10_from_bits_31_15(reso, condT); 8786 8787 DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 8788 return True; 8789 } 8790 /* fall through */ 8791 } 8792 8793 /* ---------------- usub16<c> <Rd>,<Rn>,<Rm> ---------------- */ 8794 { 8795 UInt regD = 99, regN = 99, regM = 99; 8796 Bool gate = False; 8797 8798 if (isT) { 8799 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF040) { 8800 regN = INSNT0(3,0); 8801 regD = INSNT1(11,8); 8802 regM = INSNT1(3,0); 8803 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8804 gate = True; 8805 } 8806 } else { 8807 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) && 8808 INSNA(11,8) == BITS4(1,1,1,1) && 8809 INSNA(7,4) == BITS4(0,1,1,1)) { 8810 regD = INSNA(15,12); 8811 regN = INSNA(19,16); 8812 regM = INSNA(3,0); 8813 if (regD != 15 && regN != 15 && regM != 15) 8814 gate = True; 8815 } 8816 } 8817 8818 if (gate) { 8819 IRTemp rNt = newTemp(Ity_I32); 8820 IRTemp rMt = newTemp(Ity_I32); 8821 IRTemp res = newTemp(Ity_I32); 8822 IRTemp reso = newTemp(Ity_I32); 8823 8824 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 8825 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 8826 8827 assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt))); 8828 if (isT) 8829 putIRegT( regD, mkexpr(res), condT ); 8830 else 8831 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8832 8833 assign(reso, unop(Iop_Not32, 8834 binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt)))); 8835 set_GE_32_10_from_bits_31_15(reso, condT); 8836 8837 DIP("usub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 8838 return True; 8839 } 8840 /* fall through */ 8841 } 8842 8843 /* -------------- ssub16<c> <Rd>,<Rn>,<Rm> -------------- */ 8844 { 8845 UInt regD = 99, regN = 99, regM = 99; 8846 Bool gate = False; 8847 8848 if (isT) { 8849 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF000) { 8850 regN = INSNT0(3,0); 8851 regD = INSNT1(11,8); 8852 regM = INSNT1(3,0); 8853 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8854 gate = True; 8855 } 8856 } else { 8857 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 8858 INSNA(11,8) == BITS4(1,1,1,1) && 8859 INSNA(7,4) == BITS4(0,1,1,1)) { 8860 regD = INSNA(15,12); 8861 regN = INSNA(19,16); 8862 regM = INSNA(3,0); 8863 if (regD != 15 && regN != 15 && regM != 15) 8864 gate = True; 8865 } 8866 } 8867 8868 if (gate) { 8869 IRTemp rNt = newTemp(Ity_I32); 8870 IRTemp rMt = newTemp(Ity_I32); 8871 IRTemp res = newTemp(Ity_I32); 8872 IRTemp reso = newTemp(Ity_I32); 8873 8874 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 8875 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 8876 8877 assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt))); 8878 if (isT) 8879 putIRegT( regD, mkexpr(res), condT ); 8880 else 8881 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8882 8883 assign(reso, unop(Iop_Not32, 8884 binop(Iop_HSub16Sx2, mkexpr(rNt), mkexpr(rMt)))); 8885 set_GE_32_10_from_bits_31_15(reso, condT); 8886 8887 DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 8888 return True; 8889 } 8890 /* fall through */ 8891 } 8892 8893 /* ----------------- uadd8<c> <Rd>,<Rn>,<Rm> ---------------- */ 8894 { 8895 UInt regD = 99, regN = 99, regM = 99; 8896 Bool gate = False; 8897 8898 if (isT) { 8899 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF040) { 8900 regN = INSNT0(3,0); 8901 regD = INSNT1(11,8); 8902 regM = INSNT1(3,0); 8903 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8904 gate = True; 8905 } 8906 } else { 8907 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) && 8908 INSNA(11,8) == BITS4(1,1,1,1) && 8909 (INSNA(7,4) == BITS4(1,0,0,1))) { 8910 regD = INSNA(15,12); 8911 regN = INSNA(19,16); 8912 regM = INSNA(3,0); 8913 if (regD != 15 && regN != 15 && regM != 15) 8914 gate = True; 8915 } 8916 } 8917 8918 if (gate) { 8919 IRTemp rNt = newTemp(Ity_I32); 8920 IRTemp rMt = newTemp(Ity_I32); 8921 IRTemp res = newTemp(Ity_I32); 8922 IRTemp reso = newTemp(Ity_I32); 8923 8924 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 8925 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 8926 8927 assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt))); 8928 if (isT) 8929 putIRegT( regD, mkexpr(res), condT ); 8930 else 8931 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8932 8933 assign(reso, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt))); 8934 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT); 8935 8936 DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 8937 return True; 8938 } 8939 /* fall through */ 8940 } 8941 8942 /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */ 8943 { 8944 UInt regD = 99, regN = 99, regM = 99; 8945 Bool gate = False; 8946 8947 if (isT) { 8948 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) { 8949 regN = INSNT0(3,0); 8950 regD = INSNT1(11,8); 8951 regM = INSNT1(3,0); 8952 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 8953 gate = True; 8954 } 8955 } else { 8956 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 8957 INSNA(11,8) == BITS4(1,1,1,1) && 8958 (INSNA(7,4) == BITS4(1,0,0,1))) { 8959 regD = INSNA(15,12); 8960 regN = INSNA(19,16); 8961 regM = INSNA(3,0); 8962 if (regD != 15 && regN != 15 && regM != 15) 8963 gate = True; 8964 } 8965 } 8966 8967 if (gate) { 8968 IRTemp rNt = newTemp(Ity_I32); 8969 IRTemp rMt = newTemp(Ity_I32); 8970 IRTemp res = newTemp(Ity_I32); 8971 IRTemp reso = newTemp(Ity_I32); 8972 8973 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 8974 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 8975 8976 assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt))); 8977 if (isT) 8978 putIRegT( regD, mkexpr(res), condT ); 8979 else 8980 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 8981 8982 assign(reso, unop(Iop_Not32, 8983 binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt)))); 8984 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT); 8985 8986 DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 8987 return True; 8988 } 8989 /* fall through */ 8990 } 8991 8992 /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */ 8993 { 8994 UInt regD = 99, regN = 99, regM = 99; 8995 Bool gate = False; 8996 8997 if (isT) { 8998 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) { 8999 regN = INSNT0(3,0); 9000 regD = INSNT1(11,8); 9001 regM = INSNT1(3,0); 9002 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9003 gate = True; 9004 } 9005 } else { 9006 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) && 9007 INSNA(11,8) == BITS4(1,1,1,1) && 9008 (INSNA(7,4) == BITS4(1,1,1,1))) { 9009 regD = INSNA(15,12); 9010 regN = INSNA(19,16); 9011 regM = INSNA(3,0); 9012 if (regD != 15 && regN != 15 && regM != 15) 9013 gate = True; 9014 } 9015 } 9016 9017 if (gate) { 9018 IRTemp rNt = newTemp(Ity_I32); 9019 IRTemp rMt = newTemp(Ity_I32); 9020 IRTemp res = newTemp(Ity_I32); 9021 IRTemp reso = newTemp(Ity_I32); 9022 9023 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9024 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9025 9026 assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt))); 9027 if (isT) 9028 putIRegT( regD, mkexpr(res), condT ); 9029 else 9030 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 9031 9032 assign(reso, unop(Iop_Not32, 9033 binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt)))); 9034 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT); 9035 9036 DIP("usub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9037 return True; 9038 } 9039 /* fall through */ 9040 } 9041 9042 /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */ 9043 { 9044 UInt regD = 99, regN = 99, regM = 99; 9045 Bool gate = False; 9046 9047 if (isT) { 9048 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) { 9049 regN = INSNT0(3,0); 9050 regD = INSNT1(11,8); 9051 regM = INSNT1(3,0); 9052 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9053 gate = True; 9054 } 9055 } else { 9056 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 9057 INSNA(11,8) == BITS4(1,1,1,1) && 9058 INSNA(7,4) == BITS4(1,1,1,1)) { 9059 regD = INSNA(15,12); 9060 regN = INSNA(19,16); 9061 regM = INSNA(3,0); 9062 if (regD != 15 && regN != 15 && regM != 15) 9063 gate = True; 9064 } 9065 } 9066 9067 if (gate) { 9068 IRTemp rNt = newTemp(Ity_I32); 9069 IRTemp rMt = newTemp(Ity_I32); 9070 IRTemp res = newTemp(Ity_I32); 9071 IRTemp reso = newTemp(Ity_I32); 9072 9073 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9074 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9075 9076 assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt))); 9077 if (isT) 9078 putIRegT( regD, mkexpr(res), condT ); 9079 else 9080 putIRegA( regD, mkexpr(res), condT, Ijk_Boring ); 9081 9082 assign(reso, unop(Iop_Not32, 9083 binop(Iop_HSub8Sx4, mkexpr(rNt), mkexpr(rMt)))); 9084 set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT); 9085 9086 DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9087 return True; 9088 } 9089 /* fall through */ 9090 } 9091 9092 /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */ 9093 { 9094 UInt regD = 99, regN = 99, regM = 99; 9095 Bool gate = False; 9096 9097 if (isT) { 9098 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9099 regN = INSNT0(3,0); 9100 regD = INSNT1(11,8); 9101 regM = INSNT1(3,0); 9102 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9103 gate = True; 9104 } 9105 } else { 9106 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9107 INSNA(11,8) == BITS4(1,1,1,1) && 9108 INSNA(7,4) == BITS4(1,0,0,1)) { 9109 regD = INSNA(15,12); 9110 regN = INSNA(19,16); 9111 regM = INSNA(3,0); 9112 if (regD != 15 && regN != 15 && regM != 15) 9113 gate = True; 9114 } 9115 } 9116 9117 if (gate) { 9118 IRTemp rNt = newTemp(Ity_I32); 9119 IRTemp rMt = newTemp(Ity_I32); 9120 IRTemp res_q = newTemp(Ity_I32); 9121 9122 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9123 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9124 9125 assign(res_q, binop(Iop_QAdd8Sx4, mkexpr(rNt), mkexpr(rMt))); 9126 if (isT) 9127 putIRegT( regD, mkexpr(res_q), condT ); 9128 else 9129 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9130 9131 DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9132 return True; 9133 } 9134 /* fall through */ 9135 } 9136 9137 /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */ 9138 { 9139 UInt regD = 99, regN = 99, regM = 99; 9140 Bool gate = False; 9141 9142 if (isT) { 9143 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9144 regN = INSNT0(3,0); 9145 regD = INSNT1(11,8); 9146 regM = INSNT1(3,0); 9147 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9148 gate = True; 9149 } 9150 } else { 9151 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9152 INSNA(11,8) == BITS4(1,1,1,1) && 9153 INSNA(7,4) == BITS4(1,1,1,1)) { 9154 regD = INSNA(15,12); 9155 regN = INSNA(19,16); 9156 regM = INSNA(3,0); 9157 if (regD != 15 && regN != 15 && regM != 15) 9158 gate = True; 9159 } 9160 } 9161 9162 if (gate) { 9163 IRTemp rNt = newTemp(Ity_I32); 9164 IRTemp rMt = newTemp(Ity_I32); 9165 IRTemp res_q = newTemp(Ity_I32); 9166 9167 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9168 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9169 9170 assign(res_q, binop(Iop_QSub8Sx4, mkexpr(rNt), mkexpr(rMt))); 9171 if (isT) 9172 putIRegT( regD, mkexpr(res_q), condT ); 9173 else 9174 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9175 9176 DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9177 return True; 9178 } 9179 /* fall through */ 9180 } 9181 9182 /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */ 9183 { 9184 UInt regD = 99, regN = 99, regM = 99; 9185 Bool gate = False; 9186 9187 if (isT) { 9188 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) { 9189 regN = INSNT0(3,0); 9190 regD = INSNT1(11,8); 9191 regM = INSNT1(3,0); 9192 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9193 gate = True; 9194 } 9195 } else { 9196 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) && 9197 INSNA(11,8) == BITS4(1,1,1,1) && 9198 (INSNA(7,4) == BITS4(1,0,0,1))) { 9199 regD = INSNA(15,12); 9200 regN = INSNA(19,16); 9201 regM = INSNA(3,0); 9202 if (regD != 15 && regN != 15 && regM != 15) 9203 gate = True; 9204 } 9205 } 9206 9207 if (gate) { 9208 IRTemp rNt = newTemp(Ity_I32); 9209 IRTemp rMt = newTemp(Ity_I32); 9210 IRTemp res_q = newTemp(Ity_I32); 9211 9212 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9213 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9214 9215 assign(res_q, binop(Iop_QAdd8Ux4, mkexpr(rNt), mkexpr(rMt))); 9216 if (isT) 9217 putIRegT( regD, mkexpr(res_q), condT ); 9218 else 9219 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9220 9221 DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9222 return True; 9223 } 9224 /* fall through */ 9225 } 9226 9227 /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */ 9228 { 9229 UInt regD = 99, regN = 99, regM = 99; 9230 Bool gate = False; 9231 9232 if (isT) { 9233 if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) { 9234 regN = INSNT0(3,0); 9235 regD = INSNT1(11,8); 9236 regM = INSNT1(3,0); 9237 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9238 gate = True; 9239 } 9240 } else { 9241 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) && 9242 INSNA(11,8) == BITS4(1,1,1,1) && 9243 (INSNA(7,4) == BITS4(1,1,1,1))) { 9244 regD = INSNA(15,12); 9245 regN = INSNA(19,16); 9246 regM = INSNA(3,0); 9247 if (regD != 15 && regN != 15 && regM != 15) 9248 gate = True; 9249 } 9250 } 9251 9252 if (gate) { 9253 IRTemp rNt = newTemp(Ity_I32); 9254 IRTemp rMt = newTemp(Ity_I32); 9255 IRTemp res_q = newTemp(Ity_I32); 9256 9257 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9258 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9259 9260 assign(res_q, binop(Iop_QSub8Ux4, mkexpr(rNt), mkexpr(rMt))); 9261 if (isT) 9262 putIRegT( regD, mkexpr(res_q), condT ); 9263 else 9264 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9265 9266 DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9267 return True; 9268 } 9269 /* fall through */ 9270 } 9271 9272 /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */ 9273 { 9274 UInt regD = 99, regN = 99, regM = 99; 9275 Bool gate = False; 9276 9277 if (isT) { 9278 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) { 9279 regN = INSNT0(3,0); 9280 regD = INSNT1(11,8); 9281 regM = INSNT1(3,0); 9282 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9283 gate = True; 9284 } 9285 } else { 9286 if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) && 9287 INSNA(11,8) == BITS4(1,1,1,1) && 9288 INSNA(7,4) == BITS4(1,0,0,1)) { 9289 regD = INSNA(15,12); 9290 regN = INSNA(19,16); 9291 regM = INSNA(3,0); 9292 if (regD != 15 && regN != 15 && regM != 15) 9293 gate = True; 9294 } 9295 } 9296 9297 if (gate) { 9298 IRTemp rNt = newTemp(Ity_I32); 9299 IRTemp rMt = newTemp(Ity_I32); 9300 IRTemp res_q = newTemp(Ity_I32); 9301 9302 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9303 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9304 9305 assign(res_q, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt))); 9306 if (isT) 9307 putIRegT( regD, mkexpr(res_q), condT ); 9308 else 9309 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9310 9311 DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9312 return True; 9313 } 9314 /* fall through */ 9315 } 9316 9317 /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */ 9318 { 9319 UInt regD = 99, regN = 99, regM = 99; 9320 Bool gate = False; 9321 9322 if (isT) { 9323 if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) { 9324 regN = INSNT0(3,0); 9325 regD = INSNT1(11,8); 9326 regM = INSNT1(3,0); 9327 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9328 gate = True; 9329 } 9330 } else { 9331 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) && 9332 INSNA(11,8) == BITS4(1,1,1,1) && 9333 INSNA(7,4) == BITS4(1,0,0,1)) { 9334 regD = INSNA(15,12); 9335 regN = INSNA(19,16); 9336 regM = INSNA(3,0); 9337 if (regD != 15 && regN != 15 && regM != 15) 9338 gate = True; 9339 } 9340 } 9341 9342 if (gate) { 9343 IRTemp rNt = newTemp(Ity_I32); 9344 IRTemp rMt = newTemp(Ity_I32); 9345 IRTemp res_q = newTemp(Ity_I32); 9346 9347 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9348 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9349 9350 assign(res_q, binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt))); 9351 if (isT) 9352 putIRegT( regD, mkexpr(res_q), condT ); 9353 else 9354 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9355 9356 DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9357 return True; 9358 } 9359 /* fall through */ 9360 } 9361 9362 /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */ 9363 { 9364 UInt regD = 99, regN = 99, regM = 99; 9365 Bool gate = False; 9366 9367 if (isT) { 9368 if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9369 regN = INSNT0(3,0); 9370 regD = INSNT1(11,8); 9371 regM = INSNT1(3,0); 9372 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9373 gate = True; 9374 } 9375 } else { 9376 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9377 INSNA(11,8) == BITS4(1,1,1,1) && 9378 INSNA(7,4) == BITS4(0,0,0,1)) { 9379 regD = INSNA(15,12); 9380 regN = INSNA(19,16); 9381 regM = INSNA(3,0); 9382 if (regD != 15 && regN != 15 && regM != 15) 9383 gate = True; 9384 } 9385 } 9386 9387 if (gate) { 9388 IRTemp rNt = newTemp(Ity_I32); 9389 IRTemp rMt = newTemp(Ity_I32); 9390 IRTemp res_q = newTemp(Ity_I32); 9391 9392 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9393 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9394 9395 assign(res_q, binop(Iop_QAdd16Sx2, mkexpr(rNt), mkexpr(rMt))); 9396 if (isT) 9397 putIRegT( regD, mkexpr(res_q), condT ); 9398 else 9399 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9400 9401 DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9402 return True; 9403 } 9404 /* fall through */ 9405 } 9406 9407 /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */ 9408 { 9409 UInt regD = 99, regN = 99, regM = 99; 9410 Bool gate = False; 9411 9412 if (isT) { 9413 if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9414 regN = INSNT0(3,0); 9415 regD = INSNT1(11,8); 9416 regM = INSNT1(3,0); 9417 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9418 gate = True; 9419 } 9420 } else { 9421 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9422 INSNA(11,8) == BITS4(1,1,1,1) && 9423 INSNA(7,4) == BITS4(0,1,1,1)) { 9424 regD = INSNA(15,12); 9425 regN = INSNA(19,16); 9426 regM = INSNA(3,0); 9427 if (regD != 15 && regN != 15 && regM != 15) 9428 gate = True; 9429 } 9430 } 9431 9432 if (gate) { 9433 IRTemp rNt = newTemp(Ity_I32); 9434 IRTemp rMt = newTemp(Ity_I32); 9435 IRTemp res_q = newTemp(Ity_I32); 9436 9437 assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) ); 9438 assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) ); 9439 9440 assign(res_q, binop(Iop_QSub16Sx2, mkexpr(rNt), mkexpr(rMt))); 9441 if (isT) 9442 putIRegT( regD, mkexpr(res_q), condT ); 9443 else 9444 putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring ); 9445 9446 DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM); 9447 return True; 9448 } 9449 /* fall through */ 9450 } 9451 9452 ///////////////////////////////////////////////////////////////// 9453 ///////////////////////////////////////////////////////////////// 9454 ///////////////////////////////////////////////////////////////// 9455 ///////////////////////////////////////////////////////////////// 9456 ///////////////////////////////////////////////////////////////// 9457 9458 /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */ 9459 /* note: the hardware seems to construct the result differently 9460 from wot the manual says. */ 9461 { 9462 UInt regD = 99, regN = 99, regM = 99; 9463 Bool gate = False; 9464 9465 if (isT) { 9466 if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9467 regN = INSNT0(3,0); 9468 regD = INSNT1(11,8); 9469 regM = INSNT1(3,0); 9470 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9471 gate = True; 9472 } 9473 } else { 9474 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9475 INSNA(11,8) == BITS4(1,1,1,1) && 9476 INSNA(7,4) == BITS4(0,1,0,1)) { 9477 regD = INSNA(15,12); 9478 regN = INSNA(19,16); 9479 regM = INSNA(3,0); 9480 if (regD != 15 && regN != 15 && regM != 15) 9481 gate = True; 9482 } 9483 } 9484 9485 if (gate) { 9486 IRTemp irt_regN = newTemp(Ity_I32); 9487 IRTemp irt_regM = newTemp(Ity_I32); 9488 IRTemp irt_sum = newTemp(Ity_I32); 9489 IRTemp irt_diff = newTemp(Ity_I32); 9490 IRTemp irt_sum_res = newTemp(Ity_I32); 9491 IRTemp irt_diff_res = newTemp(Ity_I32); 9492 9493 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 9494 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) ); 9495 9496 assign( irt_diff, 9497 binop( Iop_Sub32, 9498 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 9499 binop( Iop_Sar32, 9500 binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 9501 mkU8(16) ) ) ); 9502 armSignedSatQ( irt_diff, 0x10, &irt_diff_res, NULL); 9503 9504 assign( irt_sum, 9505 binop( Iop_Add32, 9506 binop( Iop_Sar32, 9507 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 9508 mkU8(16) ), 9509 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) )) ); 9510 armSignedSatQ( irt_sum, 0x10, &irt_sum_res, NULL ); 9511 9512 IRExpr* ire_result = binop( Iop_Or32, 9513 binop( Iop_Shl32, mkexpr(irt_diff_res), 9514 mkU8(16) ), 9515 binop( Iop_And32, mkexpr(irt_sum_res), 9516 mkU32(0xFFFF)) ); 9517 9518 if (isT) 9519 putIRegT( regD, ire_result, condT ); 9520 else 9521 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9522 9523 DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM ); 9524 return True; 9525 } 9526 /* fall through */ 9527 } 9528 9529 /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */ 9530 { 9531 UInt regD = 99, regN = 99, regM = 99; 9532 Bool gate = False; 9533 9534 if (isT) { 9535 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) { 9536 regN = INSNT0(3,0); 9537 regD = INSNT1(11,8); 9538 regM = INSNT1(3,0); 9539 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9540 gate = True; 9541 } 9542 } else { 9543 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) && 9544 INSNA(11,8) == BITS4(1,1,1,1) && 9545 INSNA(7,4) == BITS4(0,0,1,1)) { 9546 regD = INSNA(15,12); 9547 regN = INSNA(19,16); 9548 regM = INSNA(3,0); 9549 if (regD != 15 && regN != 15 && regM != 15) 9550 gate = True; 9551 } 9552 } 9553 9554 if (gate) { 9555 IRTemp irt_regN = newTemp(Ity_I32); 9556 IRTemp irt_regM = newTemp(Ity_I32); 9557 IRTemp irt_sum = newTemp(Ity_I32); 9558 IRTemp irt_diff = newTemp(Ity_I32); 9559 IRTemp irt_res_sum = newTemp(Ity_I32); 9560 IRTemp irt_res_diff = newTemp(Ity_I32); 9561 9562 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 9563 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) ); 9564 9565 assign( irt_diff, 9566 binop( Iop_Sub32, 9567 binop( Iop_Sar32, 9568 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 9569 mkU8(16) ), 9570 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) ); 9571 armSignedSatQ( irt_diff, 0x10, &irt_res_diff, NULL ); 9572 9573 assign( irt_sum, 9574 binop( Iop_Add32, 9575 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 9576 binop( Iop_Sar32, 9577 binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 9578 mkU8(16) ) ) ); 9579 armSignedSatQ( irt_sum, 0x10, &irt_res_sum, NULL ); 9580 9581 IRExpr* ire_result 9582 = binop( Iop_Or32, 9583 binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ), 9584 binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) ); 9585 9586 if (isT) 9587 putIRegT( regD, ire_result, condT ); 9588 else 9589 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9590 9591 DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM ); 9592 return True; 9593 } 9594 /* fall through */ 9595 } 9596 9597 /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */ 9598 { 9599 UInt regD = 99, regN = 99, regM = 99; 9600 Bool gate = False; 9601 9602 if (isT) { 9603 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) { 9604 regN = INSNT0(3,0); 9605 regD = INSNT1(11,8); 9606 regM = INSNT1(3,0); 9607 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9608 gate = True; 9609 } 9610 } else { 9611 if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 9612 INSNA(11,8) == BITS4(1,1,1,1) && 9613 INSNA(7,4) == BITS4(0,0,1,1)) { 9614 regD = INSNA(15,12); 9615 regN = INSNA(19,16); 9616 regM = INSNA(3,0); 9617 if (regD != 15 && regN != 15 && regM != 15) 9618 gate = True; 9619 } 9620 } 9621 9622 if (gate) { 9623 IRTemp irt_regN = newTemp(Ity_I32); 9624 IRTemp irt_regM = newTemp(Ity_I32); 9625 IRTemp irt_sum = newTemp(Ity_I32); 9626 IRTemp irt_diff = newTemp(Ity_I32); 9627 9628 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 9629 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) ); 9630 9631 assign( irt_diff, 9632 binop( Iop_Sub32, 9633 binop( Iop_Sar32, 9634 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 9635 mkU8(16) ), 9636 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) ); 9637 9638 assign( irt_sum, 9639 binop( Iop_Add32, 9640 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 9641 binop( Iop_Sar32, 9642 binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 9643 mkU8(16) ) ) ); 9644 9645 IRExpr* ire_result 9646 = binop( Iop_Or32, 9647 binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ), 9648 binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) ); 9649 9650 IRTemp ge10 = newTemp(Ity_I32); 9651 assign(ge10, unop(Iop_Not32, mkexpr(irt_diff))); 9652 put_GEFLAG32( 0, 31, mkexpr(ge10), condT ); 9653 put_GEFLAG32( 1, 31, mkexpr(ge10), condT ); 9654 9655 IRTemp ge32 = newTemp(Ity_I32); 9656 assign(ge32, unop(Iop_Not32, mkexpr(irt_sum))); 9657 put_GEFLAG32( 2, 31, mkexpr(ge32), condT ); 9658 put_GEFLAG32( 3, 31, mkexpr(ge32), condT ); 9659 9660 if (isT) 9661 putIRegT( regD, ire_result, condT ); 9662 else 9663 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9664 9665 DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM ); 9666 return True; 9667 } 9668 /* fall through */ 9669 } 9670 9671 /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */ 9672 /* --------------- smsad, smsadx<c><Rd>,<Rn>,<Rm> --------------- */ 9673 { 9674 UInt regD = 99, regN = 99, regM = 99, bitM = 99; 9675 Bool gate = False, isAD = False; 9676 9677 if (isT) { 9678 if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4) 9679 && (INSNT1(15,0) & 0xF0E0) == 0xF000) { 9680 regN = INSNT0(3,0); 9681 regD = INSNT1(11,8); 9682 regM = INSNT1(3,0); 9683 bitM = INSNT1(4,4); 9684 isAD = INSNT0(15,4) == 0xFB2; 9685 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9686 gate = True; 9687 } 9688 } else { 9689 if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) && 9690 INSNA(15,12) == BITS4(1,1,1,1) && 9691 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1) ) { 9692 regD = INSNA(19,16); 9693 regN = INSNA(3,0); 9694 regM = INSNA(11,8); 9695 bitM = INSNA(5,5); 9696 isAD = INSNA(6,6) == 0; 9697 if (regD != 15 && regN != 15 && regM != 15) 9698 gate = True; 9699 } 9700 } 9701 9702 if (gate) { 9703 IRTemp irt_regN = newTemp(Ity_I32); 9704 IRTemp irt_regM = newTemp(Ity_I32); 9705 IRTemp irt_prod_lo = newTemp(Ity_I32); 9706 IRTemp irt_prod_hi = newTemp(Ity_I32); 9707 IRTemp tmpM = newTemp(Ity_I32); 9708 9709 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 9710 9711 assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) ); 9712 assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) ); 9713 9714 assign( irt_prod_lo, 9715 binop( Iop_Mul32, 9716 binop( Iop_Sar32, 9717 binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 9718 mkU8(16) ), 9719 binop( Iop_Sar32, 9720 binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 9721 mkU8(16) ) ) ); 9722 assign( irt_prod_hi, binop(Iop_Mul32, 9723 binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)), 9724 binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) ); 9725 IRExpr* ire_result 9726 = binop( isAD ? Iop_Add32 : Iop_Sub32, 9727 mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ); 9728 9729 if (isT) 9730 putIRegT( regD, ire_result, condT ); 9731 else 9732 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9733 9734 if (isAD) { 9735 or_into_QFLAG32( 9736 signed_overflow_after_Add32( ire_result, 9737 irt_prod_lo, irt_prod_hi ), 9738 condT 9739 ); 9740 } 9741 9742 DIP("smu%cd%s%s r%u, r%u, r%u\n", 9743 isAD ? 'a' : 's', 9744 bitM ? "x" : "", nCC(conq), regD, regN, regM); 9745 return True; 9746 } 9747 /* fall through */ 9748 } 9749 9750 /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */ 9751 /* --------------- smlsd{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */ 9752 { 9753 UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99; 9754 Bool gate = False, isAD = False; 9755 9756 if (isT) { 9757 if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4) 9758 && INSNT1(7,5) == BITS3(0,0,0)) { 9759 regN = INSNT0(3,0); 9760 regD = INSNT1(11,8); 9761 regM = INSNT1(3,0); 9762 regA = INSNT1(15,12); 9763 bitM = INSNT1(4,4); 9764 isAD = INSNT0(15,4) == 0xFB2; 9765 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM) 9766 && !isBadRegT(regA)) 9767 gate = True; 9768 } 9769 } else { 9770 if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) && 9771 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) { 9772 regD = INSNA(19,16); 9773 regA = INSNA(15,12); 9774 regN = INSNA(3,0); 9775 regM = INSNA(11,8); 9776 bitM = INSNA(5,5); 9777 isAD = INSNA(6,6) == 0; 9778 if (regD != 15 && regN != 15 && regM != 15 && regA != 15) 9779 gate = True; 9780 } 9781 } 9782 9783 if (gate) { 9784 IRTemp irt_regN = newTemp(Ity_I32); 9785 IRTemp irt_regM = newTemp(Ity_I32); 9786 IRTemp irt_regA = newTemp(Ity_I32); 9787 IRTemp irt_prod_lo = newTemp(Ity_I32); 9788 IRTemp irt_prod_hi = newTemp(Ity_I32); 9789 IRTemp irt_sum = newTemp(Ity_I32); 9790 IRTemp tmpM = newTemp(Ity_I32); 9791 9792 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 9793 assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) ); 9794 9795 assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) ); 9796 assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) ); 9797 9798 assign( irt_prod_lo, 9799 binop(Iop_Mul32, 9800 binop(Iop_Sar32, 9801 binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 9802 mkU8(16)), 9803 binop(Iop_Sar32, 9804 binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 9805 mkU8(16))) ); 9806 assign( irt_prod_hi, 9807 binop( Iop_Mul32, 9808 binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 9809 binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) ); 9810 assign( irt_sum, binop( isAD ? Iop_Add32 : Iop_Sub32, 9811 mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ) ); 9812 9813 IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_sum), mkexpr(irt_regA)); 9814 9815 if (isT) 9816 putIRegT( regD, ire_result, condT ); 9817 else 9818 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9819 9820 if (isAD) { 9821 or_into_QFLAG32( 9822 signed_overflow_after_Add32( mkexpr(irt_sum), 9823 irt_prod_lo, irt_prod_hi ), 9824 condT 9825 ); 9826 } 9827 9828 or_into_QFLAG32( 9829 signed_overflow_after_Add32( ire_result, irt_sum, irt_regA ), 9830 condT 9831 ); 9832 9833 DIP("sml%cd%s%s r%u, r%u, r%u, r%u\n", 9834 isAD ? 'a' : 's', 9835 bitM ? "x" : "", nCC(conq), regD, regN, regM, regA); 9836 return True; 9837 } 9838 /* fall through */ 9839 } 9840 9841 /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */ 9842 { 9843 UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99, bitN = 99; 9844 Bool gate = False; 9845 9846 if (isT) { 9847 if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) { 9848 regN = INSNT0(3,0); 9849 regD = INSNT1(11,8); 9850 regM = INSNT1(3,0); 9851 regA = INSNT1(15,12); 9852 bitM = INSNT1(4,4); 9853 bitN = INSNT1(5,5); 9854 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM) 9855 && !isBadRegT(regA)) 9856 gate = True; 9857 } 9858 } else { 9859 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) && 9860 (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) { 9861 regD = INSNA(19,16); 9862 regN = INSNA(3,0); 9863 regM = INSNA(11,8); 9864 regA = INSNA(15,12); 9865 bitM = INSNA(6,6); 9866 bitN = INSNA(5,5); 9867 if (regD != 15 && regN != 15 && regM != 15 && regA != 15) 9868 gate = True; 9869 } 9870 } 9871 9872 if (gate) { 9873 IRTemp irt_regA = newTemp(Ity_I32); 9874 IRTemp irt_prod = newTemp(Ity_I32); 9875 9876 assign( irt_prod, 9877 binop(Iop_Mul32, 9878 binop(Iop_Sar32, 9879 binop(Iop_Shl32, 9880 isT ? getIRegT(regN) : getIRegA(regN), 9881 mkU8(bitN ? 0 : 16)), 9882 mkU8(16)), 9883 binop(Iop_Sar32, 9884 binop(Iop_Shl32, 9885 isT ? getIRegT(regM) : getIRegA(regM), 9886 mkU8(bitM ? 0 : 16)), 9887 mkU8(16))) ); 9888 9889 assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) ); 9890 9891 IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_prod), mkexpr(irt_regA)); 9892 9893 if (isT) 9894 putIRegT( regD, ire_result, condT ); 9895 else 9896 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9897 9898 or_into_QFLAG32( 9899 signed_overflow_after_Add32( ire_result, irt_prod, irt_regA ), 9900 condT 9901 ); 9902 9903 DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n", 9904 bitN ? 't' : 'b', bitM ? 't' : 'b', 9905 nCC(conq), regD, regN, regM, regA ); 9906 return True; 9907 } 9908 /* fall through */ 9909 } 9910 9911 /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */ 9912 { 9913 UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99; 9914 Bool gate = False; 9915 9916 if (isT) { 9917 if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) { 9918 regN = INSNT0(3,0); 9919 regD = INSNT1(11,8); 9920 regM = INSNT1(3,0); 9921 regA = INSNT1(15,12); 9922 bitM = INSNT1(4,4); 9923 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM) 9924 && !isBadRegT(regA)) 9925 gate = True; 9926 } 9927 } else { 9928 if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) && 9929 (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) { 9930 regD = INSNA(19,16); 9931 regN = INSNA(3,0); 9932 regM = INSNA(11,8); 9933 regA = INSNA(15,12); 9934 bitM = INSNA(6,6); 9935 if (regD != 15 && regN != 15 && regM != 15 && regA != 15) 9936 gate = True; 9937 } 9938 } 9939 9940 if (gate) { 9941 IRTemp irt_regA = newTemp(Ity_I32); 9942 IRTemp irt_prod = newTemp(Ity_I64); 9943 9944 assign( irt_prod, 9945 binop(Iop_MullS32, 9946 isT ? getIRegT(regN) : getIRegA(regN), 9947 binop(Iop_Sar32, 9948 binop(Iop_Shl32, 9949 isT ? getIRegT(regM) : getIRegA(regM), 9950 mkU8(bitM ? 0 : 16)), 9951 mkU8(16))) ); 9952 9953 assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) ); 9954 9955 IRTemp prod32 = newTemp(Ity_I32); 9956 assign(prod32, 9957 binop(Iop_Or32, 9958 binop(Iop_Shl32, unop(Iop_64HIto32, mkexpr(irt_prod)), mkU8(16)), 9959 binop(Iop_Shr32, unop(Iop_64to32, mkexpr(irt_prod)), mkU8(16)) 9960 )); 9961 9962 IRExpr* ire_result = binop(Iop_Add32, mkexpr(prod32), mkexpr(irt_regA)); 9963 9964 if (isT) 9965 putIRegT( regD, ire_result, condT ); 9966 else 9967 putIRegA( regD, ire_result, condT, Ijk_Boring ); 9968 9969 or_into_QFLAG32( 9970 signed_overflow_after_Add32( ire_result, prod32, irt_regA ), 9971 condT 9972 ); 9973 9974 DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n", 9975 bitM ? 't' : 'b', 9976 nCC(conq), regD, regN, regM, regA ); 9977 return True; 9978 } 9979 /* fall through */ 9980 } 9981 9982 /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */ 9983 /* fixme: fix up the test in v6media.c so that we can pass the ge 9984 flags as part of the test. */ 9985 { 9986 UInt regD = 99, regN = 99, regM = 99; 9987 Bool gate = False; 9988 9989 if (isT) { 9990 if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) { 9991 regN = INSNT0(3,0); 9992 regD = INSNT1(11,8); 9993 regM = INSNT1(3,0); 9994 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 9995 gate = True; 9996 } 9997 } else { 9998 if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) && 9999 INSNA(11,8) == BITS4(1,1,1,1) && 10000 INSNA(7,4) == BITS4(1,0,1,1)) { 10001 regD = INSNA(15,12); 10002 regN = INSNA(19,16); 10003 regM = INSNA(3,0); 10004 if (regD != 15 && regN != 15 && regM != 15) 10005 gate = True; 10006 } 10007 } 10008 10009 if (gate) { 10010 IRTemp irt_ge_flag0 = newTemp(Ity_I32); 10011 IRTemp irt_ge_flag1 = newTemp(Ity_I32); 10012 IRTemp irt_ge_flag2 = newTemp(Ity_I32); 10013 IRTemp irt_ge_flag3 = newTemp(Ity_I32); 10014 10015 assign( irt_ge_flag0, get_GEFLAG32(0) ); 10016 assign( irt_ge_flag1, get_GEFLAG32(1) ); 10017 assign( irt_ge_flag2, get_GEFLAG32(2) ); 10018 assign( irt_ge_flag3, get_GEFLAG32(3) ); 10019 10020 IRExpr* ire_ge_flag0_or 10021 = binop(Iop_Or32, mkexpr(irt_ge_flag0), 10022 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag0))); 10023 IRExpr* ire_ge_flag1_or 10024 = binop(Iop_Or32, mkexpr(irt_ge_flag1), 10025 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag1))); 10026 IRExpr* ire_ge_flag2_or 10027 = binop(Iop_Or32, mkexpr(irt_ge_flag2), 10028 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag2))); 10029 IRExpr* ire_ge_flag3_or 10030 = binop(Iop_Or32, mkexpr(irt_ge_flag3), 10031 binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag3))); 10032 10033 IRExpr* ire_ge_flags 10034 = binop( Iop_Or32, 10035 binop(Iop_Or32, 10036 binop(Iop_And32, 10037 binop(Iop_Sar32, ire_ge_flag0_or, mkU8(31)), 10038 mkU32(0x000000ff)), 10039 binop(Iop_And32, 10040 binop(Iop_Sar32, ire_ge_flag1_or, mkU8(31)), 10041 mkU32(0x0000ff00))), 10042 binop(Iop_Or32, 10043 binop(Iop_And32, 10044 binop(Iop_Sar32, ire_ge_flag2_or, mkU8(31)), 10045 mkU32(0x00ff0000)), 10046 binop(Iop_And32, 10047 binop(Iop_Sar32, ire_ge_flag3_or, mkU8(31)), 10048 mkU32(0xff000000))) ); 10049 10050 IRExpr* ire_result 10051 = binop(Iop_Or32, 10052 binop(Iop_And32, 10053 isT ? getIRegT(regN) : getIRegA(regN), 10054 ire_ge_flags ), 10055 binop(Iop_And32, 10056 isT ? getIRegT(regM) : getIRegA(regM), 10057 unop(Iop_Not32, ire_ge_flags))); 10058 10059 if (isT) 10060 putIRegT( regD, ire_result, condT ); 10061 else 10062 putIRegA( regD, ire_result, condT, Ijk_Boring ); 10063 10064 DIP("sel%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM ); 10065 return True; 10066 } 10067 /* fall through */ 10068 } 10069 10070 /* ----------------- uxtab16<c> Rd,Rn,Rm{,rot} ------------------ */ 10071 { 10072 UInt regD = 99, regN = 99, regM = 99, rotate = 99; 10073 Bool gate = False; 10074 10075 if (isT) { 10076 if (INSNT0(15,4) == 0xFA3 && (INSNT1(15,0) & 0xF0C0) == 0xF080) { 10077 regN = INSNT0(3,0); 10078 regD = INSNT1(11,8); 10079 regM = INSNT1(3,0); 10080 rotate = INSNT1(5,4); 10081 if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)) 10082 gate = True; 10083 } 10084 } else { 10085 if (INSNA(27,20) == BITS8(0,1,1,0,1,1,0,0) && 10086 INSNA(9,4) == BITS6(0,0,0,1,1,1) ) { 10087 regD = INSNA(15,12); 10088 regN = INSNA(19,16); 10089 regM = INSNA(3,0); 10090 rotate = INSNA(11,10); 10091 if (regD != 15 && regN != 15 && regM != 15) 10092 gate = True; 10093 } 10094 } 10095 10096 if (gate) { 10097 IRTemp irt_regN = newTemp(Ity_I32); 10098 assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) ); 10099 10100 IRTemp irt_regM = newTemp(Ity_I32); 10101 assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) ); 10102 10103 IRTemp irt_rot = newTemp(Ity_I32); 10104 assign( irt_rot, binop(Iop_And32, 10105 genROR32(irt_regM, 8 * rotate), 10106 mkU32(0x00FF00FF)) ); 10107 10108 IRExpr* resLo 10109 = binop(Iop_And32, 10110 binop(Iop_Add32, mkexpr(irt_regN), mkexpr(irt_rot)), 10111 mkU32(0x0000FFFF)); 10112 10113 IRExpr* resHi 10114 = binop(Iop_Add32, 10115 binop(Iop_And32, mkexpr(irt_regN), mkU32(0xFFFF0000)), 10116 binop(Iop_And32, mkexpr(irt_rot), mkU32(0xFFFF0000))); 10117 10118 IRExpr* ire_result 10119 = binop( Iop_Or32, resHi, resLo ); 10120 10121 if (isT) 10122 putIRegT( regD, ire_result, condT ); 10123 else 10124 putIRegA( regD, ire_result, condT, Ijk_Boring ); 10125 10126 DIP( "uxtab16%s r%u, r%u, r%u, ROR #%u\n", 10127 nCC(conq), regD, regN, regM, 8 * rotate ); 10128 return True; 10129 } 10130 /* fall through */ 10131 } 10132 10133 /* --------------- usad8 Rd,Rn,Rm ---------------- */ 10134 /* --------------- usada8 Rd,Rn,Rm,Ra ---------------- */ 10135 { 10136 UInt rD = 99, rN = 99, rM = 99, rA = 99; 10137 Bool gate = False; 10138 10139 if (isT) { 10140 if (INSNT0(15,4) == 0xFB7 && INSNT1(7,4) == BITS4(0,0,0,0)) { 10141 rN = INSNT0(3,0); 10142 rA = INSNT1(15,12); 10143 rD = INSNT1(11,8); 10144 rM = INSNT1(3,0); 10145 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && rA != 13) 10146 gate = True; 10147 } 10148 } else { 10149 if (INSNA(27,20) == BITS8(0,1,1,1,1,0,0,0) && 10150 INSNA(7,4) == BITS4(0,0,0,1) ) { 10151 rD = INSNA(19,16); 10152 rA = INSNA(15,12); 10153 rM = INSNA(11,8); 10154 rN = INSNA(3,0); 10155 if (rD != 15 && rN != 15 && rM != 15 /* but rA can be 15 */) 10156 gate = True; 10157 } 10158 } 10159 /* We allow rA == 15, to denote the usad8 (no accumulator) case. */ 10160 10161 if (gate) { 10162 IRExpr* rNe = isT ? getIRegT(rN) : getIRegA(rN); 10163 IRExpr* rMe = isT ? getIRegT(rM) : getIRegA(rM); 10164 IRExpr* rAe = rA == 15 ? mkU32(0) 10165 : (isT ? getIRegT(rA) : getIRegA(rA)); 10166 IRExpr* res = binop(Iop_Add32, 10167 binop(Iop_Sad8Ux4, rNe, rMe), 10168 rAe); 10169 if (isT) 10170 putIRegT( rD, res, condT ); 10171 else 10172 putIRegA( rD, res, condT, Ijk_Boring ); 10173 10174 if (rA == 15) { 10175 DIP( "usad8%s r%u, r%u, r%u\n", 10176 nCC(conq), rD, rN, rM ); 10177 } else { 10178 DIP( "usada8%s r%u, r%u, r%u, r%u\n", 10179 nCC(conq), rD, rN, rM, rA ); 10180 } 10181 return True; 10182 } 10183 /* fall through */ 10184 } 10185 10186 /* ---------- Doesn't match anything. ---------- */ 10187 return False; 10188 10189 # undef INSNA 10190 # undef INSNT0 10191 # undef INSNT1 10192 } 10193 10194 10195 /*------------------------------------------------------------*/ 10196 /*--- LDMxx/STMxx helper (both ARM and Thumb32) ---*/ 10197 /*------------------------------------------------------------*/ 10198 10199 /* Generate IR for LDMxx and STMxx. This is complex. Assumes it's 10200 unconditional, so the caller must produce a jump-around before 10201 calling this, if the insn is to be conditional. Caller is 10202 responsible for all validation of parameters. For LDMxx, if PC is 10203 amongst the values loaded, caller is also responsible for 10204 generating the jump. */ 10205 static void mk_ldm_stm ( Bool arm, /* True: ARM, False: Thumb */ 10206 UInt rN, /* base reg */ 10207 UInt bINC, /* 1: inc, 0: dec */ 10208 UInt bBEFORE, /* 1: inc/dec before, 0: after */ 10209 UInt bW, /* 1: writeback to Rn */ 10210 UInt bL, /* 1: load, 0: store */ 10211 UInt regList ) 10212 { 10213 Int i, r, m, nRegs; 10214 10215 /* Get hold of the old Rn value. We might need to write its value 10216 to memory during a store, and if it's also the writeback 10217 register then we need to get its value now. We can't treat it 10218 exactly like the other registers we're going to transfer, 10219 because for xxMDA and xxMDB writeback forms, the generated IR 10220 updates Rn in the guest state before any transfers take place. 10221 We have to do this as per comments below, in order that if Rn is 10222 the stack pointer then it always has a value is below or equal 10223 to any of the transfer addresses. Ick. */ 10224 IRTemp oldRnT = newTemp(Ity_I32); 10225 assign(oldRnT, arm ? getIRegA(rN) : getIRegT(rN)); 10226 10227 IRTemp anchorT = newTemp(Ity_I32); 10228 /* The old (Addison-Wesley) ARM ARM seems to say that LDMxx/STMxx 10229 ignore the bottom two bits of the address. However, Cortex-A8 10230 doesn't seem to care. Hence: */ 10231 /* No .. don't force alignment .. */ 10232 /* assign(anchorT, binop(Iop_And32, mkexpr(oldRnT), mkU32(~3U))); */ 10233 /* Instead, use the potentially misaligned address directly. */ 10234 assign(anchorT, mkexpr(oldRnT)); 10235 10236 IROp opADDorSUB = bINC ? Iop_Add32 : Iop_Sub32; 10237 // bINC == 1: xxMIA, xxMIB 10238 // bINC == 0: xxMDA, xxMDB 10239 10240 // For xxMDA and xxMDB, update Rn first if necessary. We have 10241 // to do this first so that, for the common idiom of the transfers 10242 // faulting because we're pushing stuff onto a stack and the stack 10243 // is growing down onto allocate-on-fault pages (as Valgrind simulates), 10244 // we need to have the SP up-to-date "covering" (pointing below) the 10245 // transfer area. For the same reason, if we are doing xxMIA or xxMIB, 10246 // do the transfer first, and then update rN afterwards. 10247 nRegs = 0; 10248 for (i = 0; i < 16; i++) { 10249 if ((regList & (1 << i)) != 0) 10250 nRegs++; 10251 } 10252 if (bW == 1 && !bINC) { 10253 IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs)); 10254 if (arm) 10255 putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring ); 10256 else 10257 putIRegT( rN, e, IRTemp_INVALID ); 10258 } 10259 10260 // Make up a list of the registers to transfer, and their offsets 10261 // in memory relative to the anchor. If the base reg (Rn) is part 10262 // of the transfer, then do it last for a load and first for a store. 10263 UInt xReg[16], xOff[16]; 10264 Int nX = 0; 10265 m = 0; 10266 for (i = 0; i < 16; i++) { 10267 r = bINC ? i : (15-i); 10268 if (0 == (regList & (1<<r))) 10269 continue; 10270 if (bBEFORE) 10271 m++; 10272 /* paranoia: check we aren't transferring the writeback 10273 register during a load. Should be assured by decode-point 10274 check above. */ 10275 if (bW == 1 && bL == 1) 10276 vassert(r != rN); 10277 10278 xOff[nX] = 4 * m; 10279 xReg[nX] = r; 10280 nX++; 10281 10282 if (!bBEFORE) 10283 m++; 10284 } 10285 vassert(m == nRegs); 10286 vassert(nX == nRegs); 10287 vassert(nX <= 16); 10288 10289 if (bW == 0 && (regList & (1<<rN)) != 0) { 10290 /* Non-writeback, and basereg is to be transferred. Do its 10291 transfer last for a load and first for a store. Requires 10292 reordering xOff/xReg. */ 10293 if (0) { 10294 vex_printf("\nREG_LIST_PRE: (rN=%d)\n", rN); 10295 for (i = 0; i < nX; i++) 10296 vex_printf("reg %d off %d\n", xReg[i], xOff[i]); 10297 vex_printf("\n"); 10298 } 10299 10300 vassert(nX > 0); 10301 for (i = 0; i < nX; i++) { 10302 if (xReg[i] == rN) 10303 break; 10304 } 10305 vassert(i < nX); /* else we didn't find it! */ 10306 UInt tReg = xReg[i]; 10307 UInt tOff = xOff[i]; 10308 if (bL == 1) { 10309 /* load; make this transfer happen last */ 10310 if (i < nX-1) { 10311 for (m = i+1; m < nX; m++) { 10312 xReg[m-1] = xReg[m]; 10313 xOff[m-1] = xOff[m]; 10314 } 10315 vassert(m == nX); 10316 xReg[m-1] = tReg; 10317 xOff[m-1] = tOff; 10318 } 10319 } else { 10320 /* store; make this transfer happen first */ 10321 if (i > 0) { 10322 for (m = i-1; m >= 0; m--) { 10323 xReg[m+1] = xReg[m]; 10324 xOff[m+1] = xOff[m]; 10325 } 10326 vassert(m == -1); 10327 xReg[0] = tReg; 10328 xOff[0] = tOff; 10329 } 10330 } 10331 10332 if (0) { 10333 vex_printf("REG_LIST_POST:\n"); 10334 for (i = 0; i < nX; i++) 10335 vex_printf("reg %d off %d\n", xReg[i], xOff[i]); 10336 vex_printf("\n"); 10337 } 10338 } 10339 10340 /* Actually generate the transfers */ 10341 for (i = 0; i < nX; i++) { 10342 r = xReg[i]; 10343 if (bL == 1) { 10344 IRExpr* e = loadLE(Ity_I32, 10345 binop(opADDorSUB, mkexpr(anchorT), 10346 mkU32(xOff[i]))); 10347 if (arm) { 10348 putIRegA( r, e, IRTemp_INVALID, Ijk_Ret ); 10349 } else { 10350 // no: putIRegT( r, e, IRTemp_INVALID ); 10351 // putIRegT refuses to write to R15. But that might happen. 10352 // Since this is uncond, and we need to be able to 10353 // write the PC, just use the low level put: 10354 llPutIReg( r, e ); 10355 } 10356 } else { 10357 /* if we're storing Rn, make sure we use the correct 10358 value, as per extensive comments above */ 10359 storeLE( binop(opADDorSUB, mkexpr(anchorT), mkU32(xOff[i])), 10360 r == rN ? mkexpr(oldRnT) 10361 : (arm ? getIRegA(r) : getIRegT(r) ) ); 10362 } 10363 } 10364 10365 // If we are doing xxMIA or xxMIB, 10366 // do the transfer first, and then update rN afterwards. 10367 if (bW == 1 && bINC) { 10368 IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs)); 10369 if (arm) 10370 putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring ); 10371 else 10372 putIRegT( rN, e, IRTemp_INVALID ); 10373 } 10374 } 10375 10376 10377 /*------------------------------------------------------------*/ 10378 /*--- VFP (CP 10 and 11) instructions ---*/ 10379 /*------------------------------------------------------------*/ 10380 10381 /* Both ARM and Thumb */ 10382 10383 /* Translate a CP10 or CP11 instruction. If successful, returns 10384 True and *dres may or may not be updated. If failure, returns 10385 False and doesn't change *dres nor create any IR. 10386 10387 The ARM and Thumb encodings are identical for the low 28 bits of 10388 the insn (yay!) and that's what the caller must supply, iow, imm28 10389 has the top 4 bits masked out. Caller is responsible for 10390 determining whether the masked-out bits are valid for a CP10/11 10391 insn. The rules for the top 4 bits are: 10392 10393 ARM: 0000 to 1110 allowed, and this is the gating condition. 10394 1111 (NV) is not allowed. 10395 10396 Thumb: must be 1110. The gating condition is taken from 10397 ITSTATE in the normal way. 10398 10399 Conditionalisation: 10400 10401 Caller must supply an IRTemp 'condT' holding the gating condition, 10402 or IRTemp_INVALID indicating the insn is always executed. 10403 10404 Caller must also supply an ARMCondcode 'cond'. This is only used 10405 for debug printing, no other purpose. For ARM, this is simply the 10406 top 4 bits of the original instruction. For Thumb, the condition 10407 is not (really) known until run time, and so ARMCondAL should be 10408 passed, only so that printing of these instructions does not show 10409 any condition. 10410 10411 Finally, the caller must indicate whether this occurs in ARM or 10412 Thumb code. 10413 */ 10414 static Bool decode_CP10_CP11_instruction ( 10415 /*MOD*/DisResult* dres, 10416 UInt insn28, 10417 IRTemp condT, 10418 ARMCondcode conq, 10419 Bool isT 10420 ) 10421 { 10422 # define INSN(_bMax,_bMin) SLICE_UInt(insn28, (_bMax), (_bMin)) 10423 10424 vassert(INSN(31,28) == BITS4(0,0,0,0)); // caller's obligation 10425 10426 if (isT) { 10427 vassert(conq == ARMCondAL); 10428 } else { 10429 vassert(conq >= ARMCondEQ && conq <= ARMCondAL); 10430 } 10431 10432 /* ----------------------------------------------------------- */ 10433 /* -- VFP instructions -- double precision (mostly) -- */ 10434 /* ----------------------------------------------------------- */ 10435 10436 /* --------------------- fldmx, fstmx --------------------- */ 10437 /* 10438 31 27 23 19 15 11 7 0 10439 P U WL 10440 C4-100, C5-26 1 FSTMX cond 1100 1000 Rn Dd 1011 offset 10441 C4-100, C5-28 2 FSTMIAX cond 1100 1010 Rn Dd 1011 offset 10442 C4-100, C5-30 3 FSTMDBX cond 1101 0010 Rn Dd 1011 offset 10443 10444 C4-42, C5-26 1 FLDMX cond 1100 1001 Rn Dd 1011 offset 10445 C4-42, C5-28 2 FLDMIAX cond 1100 1011 Rn Dd 1011 offset 10446 C4-42, C5-30 3 FLDMDBX cond 1101 0011 Rn Dd 1011 offset 10447 10448 Regs transferred: Dd .. D(d + (offset-3)/2) 10449 offset must be odd, must not imply a reg > 15 10450 IA/DB: Rn is changed by (4 + 8 x # regs transferred) 10451 10452 case coding: 10453 1 at-Rn (access at Rn) 10454 2 ia-Rn (access at Rn, then Rn += 4+8n) 10455 3 db-Rn (Rn -= 4+8n, then access at Rn) 10456 */ 10457 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0)) 10458 && INSN(11,8) == BITS4(1,0,1,1)) { 10459 UInt bP = (insn28 >> 24) & 1; 10460 UInt bU = (insn28 >> 23) & 1; 10461 UInt bW = (insn28 >> 21) & 1; 10462 UInt bL = (insn28 >> 20) & 1; 10463 UInt offset = (insn28 >> 0) & 0xFF; 10464 UInt rN = INSN(19,16); 10465 UInt dD = (INSN(22,22) << 4) | INSN(15,12); 10466 UInt nRegs = (offset - 1) / 2; 10467 UInt summary = 0; 10468 Int i; 10469 10470 /**/ if (bP == 0 && bU == 1 && bW == 0) { 10471 summary = 1; 10472 } 10473 else if (bP == 0 && bU == 1 && bW == 1) { 10474 summary = 2; 10475 } 10476 else if (bP == 1 && bU == 0 && bW == 1) { 10477 summary = 3; 10478 } 10479 else goto after_vfp_fldmx_fstmx; 10480 10481 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */ 10482 if (rN == 15 && (summary == 2 || summary == 3 || isT)) 10483 goto after_vfp_fldmx_fstmx; 10484 10485 /* offset must be odd, and specify at least one register */ 10486 if (0 == (offset & 1) || offset < 3) 10487 goto after_vfp_fldmx_fstmx; 10488 10489 /* can't transfer regs after D15 */ 10490 if (dD + nRegs - 1 >= 32) 10491 goto after_vfp_fldmx_fstmx; 10492 10493 /* Now, we can't do a conditional load or store, since that very 10494 likely will generate an exception. So we have to take a side 10495 exit at this point if the condition is false. */ 10496 if (condT != IRTemp_INVALID) { 10497 if (isT) 10498 mk_skip_over_T32_if_cond_is_false( condT ); 10499 else 10500 mk_skip_over_A32_if_cond_is_false( condT ); 10501 condT = IRTemp_INVALID; 10502 } 10503 /* Ok, now we're unconditional. Do the load or store. */ 10504 10505 /* get the old Rn value */ 10506 IRTemp rnT = newTemp(Ity_I32); 10507 assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN), 10508 rN == 15)); 10509 10510 /* make a new value for Rn, post-insn */ 10511 IRTemp rnTnew = IRTemp_INVALID; 10512 if (summary == 2 || summary == 3) { 10513 rnTnew = newTemp(Ity_I32); 10514 assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32, 10515 mkexpr(rnT), 10516 mkU32(4 + 8 * nRegs))); 10517 } 10518 10519 /* decide on the base transfer address */ 10520 IRTemp taT = newTemp(Ity_I32); 10521 assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT)); 10522 10523 /* update Rn if necessary -- in case 3, we're moving it down, so 10524 update before any memory reference, in order to keep Memcheck 10525 and V's stack-extending logic (on linux) happy */ 10526 if (summary == 3) { 10527 if (isT) 10528 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 10529 else 10530 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 10531 } 10532 10533 /* generate the transfers */ 10534 for (i = 0; i < nRegs; i++) { 10535 IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i)); 10536 if (bL) { 10537 putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID); 10538 } else { 10539 storeLE(addr, getDReg(dD + i)); 10540 } 10541 } 10542 10543 /* update Rn if necessary -- in case 2, we're moving it up, so 10544 update after any memory reference, in order to keep Memcheck 10545 and V's stack-extending logic (on linux) happy */ 10546 if (summary == 2) { 10547 if (isT) 10548 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 10549 else 10550 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 10551 } 10552 10553 HChar* nm = bL==1 ? "ld" : "st"; 10554 switch (summary) { 10555 case 1: DIP("f%smx%s r%u, {d%u-d%u}\n", 10556 nm, nCC(conq), rN, dD, dD + nRegs - 1); 10557 break; 10558 case 2: DIP("f%smiax%s r%u!, {d%u-d%u}\n", 10559 nm, nCC(conq), rN, dD, dD + nRegs - 1); 10560 break; 10561 case 3: DIP("f%smdbx%s r%u!, {d%u-d%u}\n", 10562 nm, nCC(conq), rN, dD, dD + nRegs - 1); 10563 break; 10564 default: vassert(0); 10565 } 10566 10567 goto decode_success_vfp; 10568 /* FIXME alignment constraints? */ 10569 } 10570 10571 after_vfp_fldmx_fstmx: 10572 10573 /* --------------------- fldmd, fstmd --------------------- */ 10574 /* 10575 31 27 23 19 15 11 7 0 10576 P U WL 10577 C4-96, C5-26 1 FSTMD cond 1100 1000 Rn Dd 1011 offset 10578 C4-96, C5-28 2 FSTMDIA cond 1100 1010 Rn Dd 1011 offset 10579 C4-96, C5-30 3 FSTMDDB cond 1101 0010 Rn Dd 1011 offset 10580 10581 C4-38, C5-26 1 FLDMD cond 1100 1001 Rn Dd 1011 offset 10582 C4-38, C5-28 2 FLDMIAD cond 1100 1011 Rn Dd 1011 offset 10583 C4-38, C5-30 3 FLDMDBD cond 1101 0011 Rn Dd 1011 offset 10584 10585 Regs transferred: Dd .. D(d + (offset-2)/2) 10586 offset must be even, must not imply a reg > 15 10587 IA/DB: Rn is changed by (8 x # regs transferred) 10588 10589 case coding: 10590 1 at-Rn (access at Rn) 10591 2 ia-Rn (access at Rn, then Rn += 8n) 10592 3 db-Rn (Rn -= 8n, then access at Rn) 10593 */ 10594 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0)) 10595 && INSN(11,8) == BITS4(1,0,1,1)) { 10596 UInt bP = (insn28 >> 24) & 1; 10597 UInt bU = (insn28 >> 23) & 1; 10598 UInt bW = (insn28 >> 21) & 1; 10599 UInt bL = (insn28 >> 20) & 1; 10600 UInt offset = (insn28 >> 0) & 0xFF; 10601 UInt rN = INSN(19,16); 10602 UInt dD = (INSN(22,22) << 4) | INSN(15,12); 10603 UInt nRegs = offset / 2; 10604 UInt summary = 0; 10605 Int i; 10606 10607 /**/ if (bP == 0 && bU == 1 && bW == 0) { 10608 summary = 1; 10609 } 10610 else if (bP == 0 && bU == 1 && bW == 1) { 10611 summary = 2; 10612 } 10613 else if (bP == 1 && bU == 0 && bW == 1) { 10614 summary = 3; 10615 } 10616 else goto after_vfp_fldmd_fstmd; 10617 10618 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */ 10619 if (rN == 15 && (summary == 2 || summary == 3 || isT)) 10620 goto after_vfp_fldmd_fstmd; 10621 10622 /* offset must be even, and specify at least one register */ 10623 if (1 == (offset & 1) || offset < 2) 10624 goto after_vfp_fldmd_fstmd; 10625 10626 /* can't transfer regs after D15 */ 10627 if (dD + nRegs - 1 >= 32) 10628 goto after_vfp_fldmd_fstmd; 10629 10630 /* Now, we can't do a conditional load or store, since that very 10631 likely will generate an exception. So we have to take a side 10632 exit at this point if the condition is false. */ 10633 if (condT != IRTemp_INVALID) { 10634 if (isT) 10635 mk_skip_over_T32_if_cond_is_false( condT ); 10636 else 10637 mk_skip_over_A32_if_cond_is_false( condT ); 10638 condT = IRTemp_INVALID; 10639 } 10640 /* Ok, now we're unconditional. Do the load or store. */ 10641 10642 /* get the old Rn value */ 10643 IRTemp rnT = newTemp(Ity_I32); 10644 assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN), 10645 rN == 15)); 10646 10647 /* make a new value for Rn, post-insn */ 10648 IRTemp rnTnew = IRTemp_INVALID; 10649 if (summary == 2 || summary == 3) { 10650 rnTnew = newTemp(Ity_I32); 10651 assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32, 10652 mkexpr(rnT), 10653 mkU32(8 * nRegs))); 10654 } 10655 10656 /* decide on the base transfer address */ 10657 IRTemp taT = newTemp(Ity_I32); 10658 assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT)); 10659 10660 /* update Rn if necessary -- in case 3, we're moving it down, so 10661 update before any memory reference, in order to keep Memcheck 10662 and V's stack-extending logic (on linux) happy */ 10663 if (summary == 3) { 10664 if (isT) 10665 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 10666 else 10667 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 10668 } 10669 10670 /* generate the transfers */ 10671 for (i = 0; i < nRegs; i++) { 10672 IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i)); 10673 if (bL) { 10674 putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID); 10675 } else { 10676 storeLE(addr, getDReg(dD + i)); 10677 } 10678 } 10679 10680 /* update Rn if necessary -- in case 2, we're moving it up, so 10681 update after any memory reference, in order to keep Memcheck 10682 and V's stack-extending logic (on linux) happy */ 10683 if (summary == 2) { 10684 if (isT) 10685 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 10686 else 10687 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 10688 } 10689 10690 HChar* nm = bL==1 ? "ld" : "st"; 10691 switch (summary) { 10692 case 1: DIP("f%smd%s r%u, {d%u-d%u}\n", 10693 nm, nCC(conq), rN, dD, dD + nRegs - 1); 10694 break; 10695 case 2: DIP("f%smiad%s r%u!, {d%u-d%u}\n", 10696 nm, nCC(conq), rN, dD, dD + nRegs - 1); 10697 break; 10698 case 3: DIP("f%smdbd%s r%u!, {d%u-d%u}\n", 10699 nm, nCC(conq), rN, dD, dD + nRegs - 1); 10700 break; 10701 default: vassert(0); 10702 } 10703 10704 goto decode_success_vfp; 10705 /* FIXME alignment constraints? */ 10706 } 10707 10708 after_vfp_fldmd_fstmd: 10709 10710 /* ------------------- fmrx, fmxr ------------------- */ 10711 if (BITS8(1,1,1,0,1,1,1,1) == INSN(27,20) 10712 && BITS4(1,0,1,0) == INSN(11,8) 10713 && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) { 10714 UInt rD = INSN(15,12); 10715 UInt reg = INSN(19,16); 10716 if (reg == BITS4(0,0,0,1)) { 10717 if (rD == 15) { 10718 IRTemp nzcvT = newTemp(Ity_I32); 10719 /* When rD is 15, we are copying the top 4 bits of FPSCR 10720 into CPSR. That is, set the flags thunk to COPY and 10721 install FPSCR[31:28] as the value to copy. */ 10722 assign(nzcvT, binop(Iop_And32, 10723 IRExpr_Get(OFFB_FPSCR, Ity_I32), 10724 mkU32(0xF0000000))); 10725 setFlags_D1(ARMG_CC_OP_COPY, nzcvT, condT); 10726 DIP("fmstat%s\n", nCC(conq)); 10727 } else { 10728 /* Otherwise, merely transfer FPSCR to r0 .. r14. */ 10729 IRExpr* e = IRExpr_Get(OFFB_FPSCR, Ity_I32); 10730 if (isT) 10731 putIRegT(rD, e, condT); 10732 else 10733 putIRegA(rD, e, condT, Ijk_Boring); 10734 DIP("fmrx%s r%u, fpscr\n", nCC(conq), rD); 10735 } 10736 goto decode_success_vfp; 10737 } 10738 /* fall through */ 10739 } 10740 10741 if (BITS8(1,1,1,0,1,1,1,0) == INSN(27,20) 10742 && BITS4(1,0,1,0) == INSN(11,8) 10743 && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) { 10744 UInt rD = INSN(15,12); 10745 UInt reg = INSN(19,16); 10746 if (reg == BITS4(0,0,0,1)) { 10747 putMiscReg32(OFFB_FPSCR, 10748 isT ? getIRegT(rD) : getIRegA(rD), condT); 10749 DIP("fmxr%s fpscr, r%u\n", nCC(conq), rD); 10750 goto decode_success_vfp; 10751 } 10752 /* fall through */ 10753 } 10754 10755 /* --------------------- vmov --------------------- */ 10756 // VMOV dM, rD, rN 10757 if (0x0C400B10 == (insn28 & 0x0FF00FD0)) { 10758 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 10759 UInt rD = INSN(15,12); /* lo32 */ 10760 UInt rN = INSN(19,16); /* hi32 */ 10761 if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))) { 10762 /* fall through */ 10763 } else { 10764 putDReg(dM, 10765 unop(Iop_ReinterpI64asF64, 10766 binop(Iop_32HLto64, 10767 isT ? getIRegT(rN) : getIRegA(rN), 10768 isT ? getIRegT(rD) : getIRegA(rD))), 10769 condT); 10770 DIP("vmov%s d%u, r%u, r%u\n", nCC(conq), dM, rD, rN); 10771 goto decode_success_vfp; 10772 } 10773 /* fall through */ 10774 } 10775 10776 // VMOV rD, rN, dM 10777 if (0x0C500B10 == (insn28 & 0x0FF00FD0)) { 10778 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 10779 UInt rD = INSN(15,12); /* lo32 */ 10780 UInt rN = INSN(19,16); /* hi32 */ 10781 if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13)) 10782 || rD == rN) { 10783 /* fall through */ 10784 } else { 10785 IRTemp i64 = newTemp(Ity_I64); 10786 assign(i64, unop(Iop_ReinterpF64asI64, getDReg(dM))); 10787 IRExpr* hi32 = unop(Iop_64HIto32, mkexpr(i64)); 10788 IRExpr* lo32 = unop(Iop_64to32, mkexpr(i64)); 10789 if (isT) { 10790 putIRegT(rN, hi32, condT); 10791 putIRegT(rD, lo32, condT); 10792 } else { 10793 putIRegA(rN, hi32, condT, Ijk_Boring); 10794 putIRegA(rD, lo32, condT, Ijk_Boring); 10795 } 10796 DIP("vmov%s r%u, r%u, d%u\n", nCC(conq), rD, rN, dM); 10797 goto decode_success_vfp; 10798 } 10799 /* fall through */ 10800 } 10801 10802 // VMOV sD, sD+1, rN, rM 10803 if (0x0C400A10 == (insn28 & 0x0FF00FD0)) { 10804 UInt sD = (INSN(3,0) << 1) | INSN(5,5); 10805 UInt rN = INSN(15,12); 10806 UInt rM = INSN(19,16); 10807 if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13)) 10808 || sD == 31) { 10809 /* fall through */ 10810 } else { 10811 putFReg(sD, 10812 unop(Iop_ReinterpI32asF32, isT ? getIRegT(rN) : getIRegA(rN)), 10813 condT); 10814 putFReg(sD+1, 10815 unop(Iop_ReinterpI32asF32, isT ? getIRegT(rM) : getIRegA(rM)), 10816 condT); 10817 DIP("vmov%s, s%u, s%u, r%u, r%u\n", 10818 nCC(conq), sD, sD + 1, rN, rM); 10819 goto decode_success_vfp; 10820 } 10821 } 10822 10823 // VMOV rN, rM, sD, sD+1 10824 if (0x0C500A10 == (insn28 & 0x0FF00FD0)) { 10825 UInt sD = (INSN(3,0) << 1) | INSN(5,5); 10826 UInt rN = INSN(15,12); 10827 UInt rM = INSN(19,16); 10828 if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13)) 10829 || sD == 31 || rN == rM) { 10830 /* fall through */ 10831 } else { 10832 IRExpr* res0 = unop(Iop_ReinterpF32asI32, getFReg(sD)); 10833 IRExpr* res1 = unop(Iop_ReinterpF32asI32, getFReg(sD+1)); 10834 if (isT) { 10835 putIRegT(rN, res0, condT); 10836 putIRegT(rM, res1, condT); 10837 } else { 10838 putIRegA(rN, res0, condT, Ijk_Boring); 10839 putIRegA(rM, res1, condT, Ijk_Boring); 10840 } 10841 DIP("vmov%s, r%u, r%u, s%u, s%u\n", 10842 nCC(conq), rN, rM, sD, sD + 1); 10843 goto decode_success_vfp; 10844 } 10845 } 10846 10847 // VMOV rD[x], rT (ARM core register to scalar) 10848 if (0x0E000B10 == (insn28 & 0x0F900F1F)) { 10849 UInt rD = (INSN(7,7) << 4) | INSN(19,16); 10850 UInt rT = INSN(15,12); 10851 UInt opc = (INSN(22,21) << 2) | INSN(6,5); 10852 UInt index; 10853 if (rT == 15 || (isT && rT == 13)) { 10854 /* fall through */ 10855 } else { 10856 if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) { 10857 index = opc & 7; 10858 putDRegI64(rD, triop(Iop_SetElem8x8, 10859 getDRegI64(rD), 10860 mkU8(index), 10861 unop(Iop_32to8, 10862 isT ? getIRegT(rT) : getIRegA(rT))), 10863 condT); 10864 DIP("vmov%s.8 d%u[%u], r%u\n", nCC(conq), rD, index, rT); 10865 goto decode_success_vfp; 10866 } 10867 else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) { 10868 index = (opc >> 1) & 3; 10869 putDRegI64(rD, triop(Iop_SetElem16x4, 10870 getDRegI64(rD), 10871 mkU8(index), 10872 unop(Iop_32to16, 10873 isT ? getIRegT(rT) : getIRegA(rT))), 10874 condT); 10875 DIP("vmov%s.16 d%u[%u], r%u\n", nCC(conq), rD, index, rT); 10876 goto decode_success_vfp; 10877 } 10878 else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0)) { 10879 index = (opc >> 2) & 1; 10880 putDRegI64(rD, triop(Iop_SetElem32x2, 10881 getDRegI64(rD), 10882 mkU8(index), 10883 isT ? getIRegT(rT) : getIRegA(rT)), 10884 condT); 10885 DIP("vmov%s.32 d%u[%u], r%u\n", nCC(conq), rD, index, rT); 10886 goto decode_success_vfp; 10887 } else { 10888 /* fall through */ 10889 } 10890 } 10891 } 10892 10893 // VMOV (scalar to ARM core register) 10894 // VMOV rT, rD[x] 10895 if (0x0E100B10 == (insn28 & 0x0F100F1F)) { 10896 UInt rN = (INSN(7,7) << 4) | INSN(19,16); 10897 UInt rT = INSN(15,12); 10898 UInt U = INSN(23,23); 10899 UInt opc = (INSN(22,21) << 2) | INSN(6,5); 10900 UInt index; 10901 if (rT == 15 || (isT && rT == 13)) { 10902 /* fall through */ 10903 } else { 10904 if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) { 10905 index = opc & 7; 10906 IRExpr* e = unop(U ? Iop_8Uto32 : Iop_8Sto32, 10907 binop(Iop_GetElem8x8, 10908 getDRegI64(rN), 10909 mkU8(index))); 10910 if (isT) 10911 putIRegT(rT, e, condT); 10912 else 10913 putIRegA(rT, e, condT, Ijk_Boring); 10914 DIP("vmov%s.%c8 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's', 10915 rT, rN, index); 10916 goto decode_success_vfp; 10917 } 10918 else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) { 10919 index = (opc >> 1) & 3; 10920 IRExpr* e = unop(U ? Iop_16Uto32 : Iop_16Sto32, 10921 binop(Iop_GetElem16x4, 10922 getDRegI64(rN), 10923 mkU8(index))); 10924 if (isT) 10925 putIRegT(rT, e, condT); 10926 else 10927 putIRegA(rT, e, condT, Ijk_Boring); 10928 DIP("vmov%s.%c16 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's', 10929 rT, rN, index); 10930 goto decode_success_vfp; 10931 } 10932 else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0) && U == 0) { 10933 index = (opc >> 2) & 1; 10934 IRExpr* e = binop(Iop_GetElem32x2, getDRegI64(rN), mkU8(index)); 10935 if (isT) 10936 putIRegT(rT, e, condT); 10937 else 10938 putIRegA(rT, e, condT, Ijk_Boring); 10939 DIP("vmov%s.32 r%u, d%u[%u]\n", nCC(conq), rT, rN, index); 10940 goto decode_success_vfp; 10941 } else { 10942 /* fall through */ 10943 } 10944 } 10945 } 10946 10947 // VMOV.F32 sD, #imm 10948 // FCONSTS sD, #imm 10949 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 10950 && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,0)) { 10951 UInt rD = (INSN(15,12) << 1) | INSN(22,22); 10952 UInt imm8 = (INSN(19,16) << 4) | INSN(3,0); 10953 UInt b = (imm8 >> 6) & 1; 10954 UInt imm; 10955 imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,(imm8 >> 5) & 1) << 8) 10956 | ((imm8 & 0x1f) << 3); 10957 imm <<= 16; 10958 putFReg(rD, unop(Iop_ReinterpI32asF32, mkU32(imm)), condT); 10959 DIP("fconsts%s s%u #%u", nCC(conq), rD, imm8); 10960 goto decode_success_vfp; 10961 } 10962 10963 // VMOV.F64 dD, #imm 10964 // FCONSTD dD, #imm 10965 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 10966 && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,1)) { 10967 UInt rD = INSN(15,12) | (INSN(22,22) << 4); 10968 UInt imm8 = (INSN(19,16) << 4) | INSN(3,0); 10969 UInt b = (imm8 >> 6) & 1; 10970 ULong imm; 10971 imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,b) << 8) 10972 | BITS8(b,b,0,0,0,0,0,0) | (imm8 & 0x3f); 10973 imm <<= 48; 10974 putDReg(rD, unop(Iop_ReinterpI64asF64, mkU64(imm)), condT); 10975 DIP("fconstd%s d%u #%u", nCC(conq), rD, imm8); 10976 goto decode_success_vfp; 10977 } 10978 10979 /* ---------------------- vdup ------------------------- */ 10980 // VDUP dD, rT 10981 // VDUP qD, rT 10982 if (BITS8(1,1,1,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,1)) 10983 && BITS4(1,0,1,1) == INSN(11,8) && INSN(6,6) == 0 && INSN(4,4) == 1) { 10984 UInt rD = (INSN(7,7) << 4) | INSN(19,16); 10985 UInt rT = INSN(15,12); 10986 UInt Q = INSN(21,21); 10987 UInt size = (INSN(22,22) << 1) | INSN(5,5); 10988 if (rT == 15 || (isT && rT == 13) || size == 3 || (Q && (rD & 1))) { 10989 /* fall through */ 10990 } else { 10991 IRExpr* e = isT ? getIRegT(rT) : getIRegA(rT); 10992 if (Q) { 10993 rD >>= 1; 10994 switch (size) { 10995 case 0: 10996 putQReg(rD, unop(Iop_Dup32x4, e), condT); 10997 break; 10998 case 1: 10999 putQReg(rD, unop(Iop_Dup16x8, unop(Iop_32to16, e)), 11000 condT); 11001 break; 11002 case 2: 11003 putQReg(rD, unop(Iop_Dup8x16, unop(Iop_32to8, e)), 11004 condT); 11005 break; 11006 default: 11007 vassert(0); 11008 } 11009 DIP("vdup.%u q%u, r%u\n", 32 / (1<<size), rD, rT); 11010 } else { 11011 switch (size) { 11012 case 0: 11013 putDRegI64(rD, unop(Iop_Dup32x2, e), condT); 11014 break; 11015 case 1: 11016 putDRegI64(rD, unop(Iop_Dup16x4, unop(Iop_32to16, e)), 11017 condT); 11018 break; 11019 case 2: 11020 putDRegI64(rD, unop(Iop_Dup8x8, unop(Iop_32to8, e)), 11021 condT); 11022 break; 11023 default: 11024 vassert(0); 11025 } 11026 DIP("vdup.%u d%u, r%u\n", 32 / (1<<size), rD, rT); 11027 } 11028 goto decode_success_vfp; 11029 } 11030 } 11031 11032 /* --------------------- f{ld,st}d --------------------- */ 11033 // FLDD, FSTD 11034 if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0)) 11035 && BITS4(1,0,1,1) == INSN(11,8)) { 11036 UInt dD = INSN(15,12) | (INSN(22,22) << 4); 11037 UInt rN = INSN(19,16); 11038 UInt offset = (insn28 & 0xFF) << 2; 11039 UInt bU = (insn28 >> 23) & 1; /* 1: +offset 0: -offset */ 11040 UInt bL = (insn28 >> 20) & 1; /* 1: load 0: store */ 11041 /* make unconditional */ 11042 if (condT != IRTemp_INVALID) { 11043 if (isT) 11044 mk_skip_over_T32_if_cond_is_false( condT ); 11045 else 11046 mk_skip_over_A32_if_cond_is_false( condT ); 11047 condT = IRTemp_INVALID; 11048 } 11049 IRTemp ea = newTemp(Ity_I32); 11050 assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32, 11051 align4if(isT ? getIRegT(rN) : getIRegA(rN), 11052 rN == 15), 11053 mkU32(offset))); 11054 if (bL) { 11055 putDReg(dD, loadLE(Ity_F64,mkexpr(ea)), IRTemp_INVALID); 11056 } else { 11057 storeLE(mkexpr(ea), getDReg(dD)); 11058 } 11059 DIP("f%sd%s d%u, [r%u, %c#%u]\n", 11060 bL ? "ld" : "st", nCC(conq), dD, rN, 11061 bU ? '+' : '-', offset); 11062 goto decode_success_vfp; 11063 } 11064 11065 /* --------------------- dp insns (D) --------------------- */ 11066 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0)) 11067 && BITS4(1,0,1,1) == INSN(11,8) 11068 && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) { 11069 UInt dM = INSN(3,0) | (INSN(5,5) << 4); /* argR */ 11070 UInt dD = INSN(15,12) | (INSN(22,22) << 4); /* dst/acc */ 11071 UInt dN = INSN(19,16) | (INSN(7,7) << 4); /* argL */ 11072 UInt bP = (insn28 >> 23) & 1; 11073 UInt bQ = (insn28 >> 21) & 1; 11074 UInt bR = (insn28 >> 20) & 1; 11075 UInt bS = (insn28 >> 6) & 1; 11076 UInt opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS; 11077 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */ 11078 switch (opc) { 11079 case BITS4(0,0,0,0): /* MAC: d + n * m */ 11080 putDReg(dD, triop(Iop_AddF64, rm, 11081 getDReg(dD), 11082 triop(Iop_MulF64, rm, getDReg(dN), 11083 getDReg(dM))), 11084 condT); 11085 DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11086 goto decode_success_vfp; 11087 case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */ 11088 putDReg(dD, triop(Iop_AddF64, rm, 11089 getDReg(dD), 11090 unop(Iop_NegF64, 11091 triop(Iop_MulF64, rm, getDReg(dN), 11092 getDReg(dM)))), 11093 condT); 11094 DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11095 goto decode_success_vfp; 11096 case BITS4(0,0,1,0): /* MSC: - d + n * m */ 11097 putDReg(dD, triop(Iop_AddF64, rm, 11098 unop(Iop_NegF64, getDReg(dD)), 11099 triop(Iop_MulF64, rm, getDReg(dN), 11100 getDReg(dM))), 11101 condT); 11102 DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11103 goto decode_success_vfp; 11104 case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */ 11105 putDReg(dD, triop(Iop_AddF64, rm, 11106 unop(Iop_NegF64, getDReg(dD)), 11107 unop(Iop_NegF64, 11108 triop(Iop_MulF64, rm, getDReg(dN), 11109 getDReg(dM)))), 11110 condT); 11111 DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11112 goto decode_success_vfp; 11113 case BITS4(0,1,0,0): /* MUL: n * m */ 11114 putDReg(dD, triop(Iop_MulF64, rm, getDReg(dN), getDReg(dM)), 11115 condT); 11116 DIP("fmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11117 goto decode_success_vfp; 11118 case BITS4(0,1,0,1): /* NMUL: - n * m */ 11119 putDReg(dD, unop(Iop_NegF64, 11120 triop(Iop_MulF64, rm, getDReg(dN), 11121 getDReg(dM))), 11122 condT); 11123 DIP("fnmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11124 goto decode_success_vfp; 11125 case BITS4(0,1,1,0): /* ADD: n + m */ 11126 putDReg(dD, triop(Iop_AddF64, rm, getDReg(dN), getDReg(dM)), 11127 condT); 11128 DIP("faddd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11129 goto decode_success_vfp; 11130 case BITS4(0,1,1,1): /* SUB: n - m */ 11131 putDReg(dD, triop(Iop_SubF64, rm, getDReg(dN), getDReg(dM)), 11132 condT); 11133 DIP("fsubd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11134 goto decode_success_vfp; 11135 case BITS4(1,0,0,0): /* DIV: n / m */ 11136 putDReg(dD, triop(Iop_DivF64, rm, getDReg(dN), getDReg(dM)), 11137 condT); 11138 DIP("fdivd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM); 11139 goto decode_success_vfp; 11140 default: 11141 break; 11142 } 11143 } 11144 11145 /* --------------------- compares (D) --------------------- */ 11146 /* 31 27 23 19 15 11 7 3 11147 28 24 20 16 12 8 4 0 11148 FCMPD cond 1110 1D11 0100 Dd 1011 0100 Dm 11149 FCMPED cond 1110 1D11 0100 Dd 1011 1100 Dm 11150 FCMPZD cond 1110 1D11 0101 Dd 1011 0100 0000 11151 FCMPZED cond 1110 1D11 0101 Dd 1011 1100 0000 11152 Z N 11153 11154 Z=0 Compare Dd vs Dm and set FPSCR 31:28 accordingly 11155 Z=1 Compare Dd vs zero 11156 11157 N=1 generates Invalid Operation exn if either arg is any kind of NaN 11158 N=0 generates Invalid Operation exn if either arg is a signalling NaN 11159 (Not that we pay any attention to N here) 11160 */ 11161 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11162 && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 11163 && BITS4(1,0,1,1) == INSN(11,8) 11164 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11165 UInt bZ = (insn28 >> 16) & 1; 11166 UInt bN = (insn28 >> 7) & 1; 11167 UInt dD = INSN(15,12) | (INSN(22,22) << 4); 11168 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 11169 if (bZ && INSN(3,0) != 0) { 11170 /* does not decode; fall through */ 11171 } else { 11172 IRTemp argL = newTemp(Ity_F64); 11173 IRTemp argR = newTemp(Ity_F64); 11174 IRTemp irRes = newTemp(Ity_I32); 11175 assign(argL, getDReg(dD)); 11176 assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0)) : getDReg(dM)); 11177 assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR))); 11178 11179 IRTemp nzcv = IRTemp_INVALID; 11180 IRTemp oldFPSCR = newTemp(Ity_I32); 11181 IRTemp newFPSCR = newTemp(Ity_I32); 11182 11183 /* This is where the fun starts. We have to convert 'irRes' 11184 from an IR-convention return result (IRCmpF64Result) to an 11185 ARM-encoded (N,Z,C,V) group. The final result is in the 11186 bottom 4 bits of 'nzcv'. */ 11187 /* Map compare result from IR to ARM(nzcv) */ 11188 /* 11189 FP cmp result | IR | ARM(nzcv) 11190 -------------------------------- 11191 UN 0x45 0011 11192 LT 0x01 1000 11193 GT 0x00 0010 11194 EQ 0x40 0110 11195 */ 11196 nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes); 11197 11198 /* And update FPSCR accordingly */ 11199 assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32)); 11200 assign(newFPSCR, 11201 binop(Iop_Or32, 11202 binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)), 11203 binop(Iop_Shl32, mkexpr(nzcv), mkU8(28)))); 11204 11205 putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT); 11206 11207 if (bZ) { 11208 DIP("fcmpz%sd%s d%u\n", bN ? "e" : "", nCC(conq), dD); 11209 } else { 11210 DIP("fcmp%sd%s d%u, d%u\n", bN ? "e" : "", nCC(conq), dD, dM); 11211 } 11212 goto decode_success_vfp; 11213 } 11214 /* fall through */ 11215 } 11216 11217 /* --------------------- unary (D) --------------------- */ 11218 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11219 && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 11220 && BITS4(1,0,1,1) == INSN(11,8) 11221 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11222 UInt dD = INSN(15,12) | (INSN(22,22) << 4); 11223 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 11224 UInt b16 = (insn28 >> 16) & 1; 11225 UInt b7 = (insn28 >> 7) & 1; 11226 /**/ if (b16 == 0 && b7 == 0) { 11227 // FCPYD 11228 putDReg(dD, getDReg(dM), condT); 11229 DIP("fcpyd%s d%u, d%u\n", nCC(conq), dD, dM); 11230 goto decode_success_vfp; 11231 } 11232 else if (b16 == 0 && b7 == 1) { 11233 // FABSD 11234 putDReg(dD, unop(Iop_AbsF64, getDReg(dM)), condT); 11235 DIP("fabsd%s d%u, d%u\n", nCC(conq), dD, dM); 11236 goto decode_success_vfp; 11237 } 11238 else if (b16 == 1 && b7 == 0) { 11239 // FNEGD 11240 putDReg(dD, unop(Iop_NegF64, getDReg(dM)), condT); 11241 DIP("fnegd%s d%u, d%u\n", nCC(conq), dD, dM); 11242 goto decode_success_vfp; 11243 } 11244 else if (b16 == 1 && b7 == 1) { 11245 // FSQRTD 11246 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */ 11247 putDReg(dD, binop(Iop_SqrtF64, rm, getDReg(dM)), condT); 11248 DIP("fsqrtd%s d%u, d%u\n", nCC(conq), dD, dM); 11249 goto decode_success_vfp; 11250 } 11251 else 11252 vassert(0); 11253 11254 /* fall through */ 11255 } 11256 11257 /* ----------------- I <-> D conversions ----------------- */ 11258 11259 // F{S,U}ITOD dD, fM 11260 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11261 && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1)) 11262 && BITS4(1,0,1,1) == INSN(11,8) 11263 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11264 UInt bM = (insn28 >> 5) & 1; 11265 UInt fM = (INSN(3,0) << 1) | bM; 11266 UInt dD = INSN(15,12) | (INSN(22,22) << 4); 11267 UInt syned = (insn28 >> 7) & 1; 11268 if (syned) { 11269 // FSITOD 11270 putDReg(dD, unop(Iop_I32StoF64, 11271 unop(Iop_ReinterpF32asI32, getFReg(fM))), 11272 condT); 11273 DIP("fsitod%s d%u, s%u\n", nCC(conq), dD, fM); 11274 } else { 11275 // FUITOD 11276 putDReg(dD, unop(Iop_I32UtoF64, 11277 unop(Iop_ReinterpF32asI32, getFReg(fM))), 11278 condT); 11279 DIP("fuitod%s d%u, s%u\n", nCC(conq), dD, fM); 11280 } 11281 goto decode_success_vfp; 11282 } 11283 11284 // FTO{S,U}ID fD, dM 11285 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11286 && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 11287 && BITS4(1,0,1,1) == INSN(11,8) 11288 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11289 UInt bD = (insn28 >> 22) & 1; 11290 UInt fD = (INSN(15,12) << 1) | bD; 11291 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 11292 UInt bZ = (insn28 >> 7) & 1; 11293 UInt syned = (insn28 >> 16) & 1; 11294 IRTemp rmode = newTemp(Ity_I32); 11295 assign(rmode, bZ ? mkU32(Irrm_ZERO) 11296 : mkexpr(mk_get_IR_rounding_mode())); 11297 if (syned) { 11298 // FTOSID 11299 putFReg(fD, unop(Iop_ReinterpI32asF32, 11300 binop(Iop_F64toI32S, mkexpr(rmode), 11301 getDReg(dM))), 11302 condT); 11303 DIP("ftosi%sd%s s%u, d%u\n", bZ ? "z" : "", 11304 nCC(conq), fD, dM); 11305 } else { 11306 // FTOUID 11307 putFReg(fD, unop(Iop_ReinterpI32asF32, 11308 binop(Iop_F64toI32U, mkexpr(rmode), 11309 getDReg(dM))), 11310 condT); 11311 DIP("ftoui%sd%s s%u, d%u\n", bZ ? "z" : "", 11312 nCC(conq), fD, dM); 11313 } 11314 goto decode_success_vfp; 11315 } 11316 11317 /* ----------------------------------------------------------- */ 11318 /* -- VFP instructions -- single precision -- */ 11319 /* ----------------------------------------------------------- */ 11320 11321 /* --------------------- fldms, fstms --------------------- */ 11322 /* 11323 31 27 23 19 15 11 7 0 11324 P UDWL 11325 C4-98, C5-26 1 FSTMD cond 1100 1x00 Rn Fd 1010 offset 11326 C4-98, C5-28 2 FSTMDIA cond 1100 1x10 Rn Fd 1010 offset 11327 C4-98, C5-30 3 FSTMDDB cond 1101 0x10 Rn Fd 1010 offset 11328 11329 C4-40, C5-26 1 FLDMD cond 1100 1x01 Rn Fd 1010 offset 11330 C4-40, C5-26 2 FLDMIAD cond 1100 1x11 Rn Fd 1010 offset 11331 C4-40, C5-26 3 FLDMDBD cond 1101 0x11 Rn Fd 1010 offset 11332 11333 Regs transferred: F(Fd:D) .. F(Fd:d + offset) 11334 offset must not imply a reg > 15 11335 IA/DB: Rn is changed by (4 x # regs transferred) 11336 11337 case coding: 11338 1 at-Rn (access at Rn) 11339 2 ia-Rn (access at Rn, then Rn += 4n) 11340 3 db-Rn (Rn -= 4n, then access at Rn) 11341 */ 11342 if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0)) 11343 && INSN(11,8) == BITS4(1,0,1,0)) { 11344 UInt bP = (insn28 >> 24) & 1; 11345 UInt bU = (insn28 >> 23) & 1; 11346 UInt bW = (insn28 >> 21) & 1; 11347 UInt bL = (insn28 >> 20) & 1; 11348 UInt bD = (insn28 >> 22) & 1; 11349 UInt offset = (insn28 >> 0) & 0xFF; 11350 UInt rN = INSN(19,16); 11351 UInt fD = (INSN(15,12) << 1) | bD; 11352 UInt nRegs = offset; 11353 UInt summary = 0; 11354 Int i; 11355 11356 /**/ if (bP == 0 && bU == 1 && bW == 0) { 11357 summary = 1; 11358 } 11359 else if (bP == 0 && bU == 1 && bW == 1) { 11360 summary = 2; 11361 } 11362 else if (bP == 1 && bU == 0 && bW == 1) { 11363 summary = 3; 11364 } 11365 else goto after_vfp_fldms_fstms; 11366 11367 /* no writebacks to r15 allowed. No use of r15 in thumb mode. */ 11368 if (rN == 15 && (summary == 2 || summary == 3 || isT)) 11369 goto after_vfp_fldms_fstms; 11370 11371 /* offset must specify at least one register */ 11372 if (offset < 1) 11373 goto after_vfp_fldms_fstms; 11374 11375 /* can't transfer regs after S31 */ 11376 if (fD + nRegs - 1 >= 32) 11377 goto after_vfp_fldms_fstms; 11378 11379 /* Now, we can't do a conditional load or store, since that very 11380 likely will generate an exception. So we have to take a side 11381 exit at this point if the condition is false. */ 11382 if (condT != IRTemp_INVALID) { 11383 if (isT) 11384 mk_skip_over_T32_if_cond_is_false( condT ); 11385 else 11386 mk_skip_over_A32_if_cond_is_false( condT ); 11387 condT = IRTemp_INVALID; 11388 } 11389 /* Ok, now we're unconditional. Do the load or store. */ 11390 11391 /* get the old Rn value */ 11392 IRTemp rnT = newTemp(Ity_I32); 11393 assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN), 11394 rN == 15)); 11395 11396 /* make a new value for Rn, post-insn */ 11397 IRTemp rnTnew = IRTemp_INVALID; 11398 if (summary == 2 || summary == 3) { 11399 rnTnew = newTemp(Ity_I32); 11400 assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32, 11401 mkexpr(rnT), 11402 mkU32(4 * nRegs))); 11403 } 11404 11405 /* decide on the base transfer address */ 11406 IRTemp taT = newTemp(Ity_I32); 11407 assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT)); 11408 11409 /* update Rn if necessary -- in case 3, we're moving it down, so 11410 update before any memory reference, in order to keep Memcheck 11411 and V's stack-extending logic (on linux) happy */ 11412 if (summary == 3) { 11413 if (isT) 11414 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 11415 else 11416 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 11417 } 11418 11419 /* generate the transfers */ 11420 for (i = 0; i < nRegs; i++) { 11421 IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(4*i)); 11422 if (bL) { 11423 putFReg(fD + i, loadLE(Ity_F32, addr), IRTemp_INVALID); 11424 } else { 11425 storeLE(addr, getFReg(fD + i)); 11426 } 11427 } 11428 11429 /* update Rn if necessary -- in case 2, we're moving it up, so 11430 update after any memory reference, in order to keep Memcheck 11431 and V's stack-extending logic (on linux) happy */ 11432 if (summary == 2) { 11433 if (isT) 11434 putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID); 11435 else 11436 putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring); 11437 } 11438 11439 HChar* nm = bL==1 ? "ld" : "st"; 11440 switch (summary) { 11441 case 1: DIP("f%sms%s r%u, {s%u-s%u}\n", 11442 nm, nCC(conq), rN, fD, fD + nRegs - 1); 11443 break; 11444 case 2: DIP("f%smias%s r%u!, {s%u-s%u}\n", 11445 nm, nCC(conq), rN, fD, fD + nRegs - 1); 11446 break; 11447 case 3: DIP("f%smdbs%s r%u!, {s%u-s%u}\n", 11448 nm, nCC(conq), rN, fD, fD + nRegs - 1); 11449 break; 11450 default: vassert(0); 11451 } 11452 11453 goto decode_success_vfp; 11454 /* FIXME alignment constraints? */ 11455 } 11456 11457 after_vfp_fldms_fstms: 11458 11459 /* --------------------- fmsr, fmrs --------------------- */ 11460 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0)) 11461 && BITS4(1,0,1,0) == INSN(11,8) 11462 && BITS4(0,0,0,0) == INSN(3,0) 11463 && BITS4(0,0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) { 11464 UInt rD = INSN(15,12); 11465 UInt b7 = (insn28 >> 7) & 1; 11466 UInt fN = (INSN(19,16) << 1) | b7; 11467 UInt b20 = (insn28 >> 20) & 1; 11468 if (rD == 15) { 11469 /* fall through */ 11470 /* Let's assume that no sane person would want to do 11471 floating-point transfers to or from the program counter, 11472 and simply decline to decode the instruction. The ARM ARM 11473 doesn't seem to explicitly disallow this case, though. */ 11474 } else { 11475 if (b20) { 11476 IRExpr* res = unop(Iop_ReinterpF32asI32, getFReg(fN)); 11477 if (isT) 11478 putIRegT(rD, res, condT); 11479 else 11480 putIRegA(rD, res, condT, Ijk_Boring); 11481 DIP("fmrs%s r%u, s%u\n", nCC(conq), rD, fN); 11482 } else { 11483 putFReg(fN, unop(Iop_ReinterpI32asF32, 11484 isT ? getIRegT(rD) : getIRegA(rD)), 11485 condT); 11486 DIP("fmsr%s s%u, r%u\n", nCC(conq), fN, rD); 11487 } 11488 goto decode_success_vfp; 11489 } 11490 /* fall through */ 11491 } 11492 11493 /* --------------------- f{ld,st}s --------------------- */ 11494 // FLDS, FSTS 11495 if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0)) 11496 && BITS4(1,0,1,0) == INSN(11,8)) { 11497 UInt bD = (insn28 >> 22) & 1; 11498 UInt fD = (INSN(15,12) << 1) | bD; 11499 UInt rN = INSN(19,16); 11500 UInt offset = (insn28 & 0xFF) << 2; 11501 UInt bU = (insn28 >> 23) & 1; /* 1: +offset 0: -offset */ 11502 UInt bL = (insn28 >> 20) & 1; /* 1: load 0: store */ 11503 /* make unconditional */ 11504 if (condT != IRTemp_INVALID) { 11505 if (isT) 11506 mk_skip_over_T32_if_cond_is_false( condT ); 11507 else 11508 mk_skip_over_A32_if_cond_is_false( condT ); 11509 condT = IRTemp_INVALID; 11510 } 11511 IRTemp ea = newTemp(Ity_I32); 11512 assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32, 11513 align4if(isT ? getIRegT(rN) : getIRegA(rN), 11514 rN == 15), 11515 mkU32(offset))); 11516 if (bL) { 11517 putFReg(fD, loadLE(Ity_F32,mkexpr(ea)), IRTemp_INVALID); 11518 } else { 11519 storeLE(mkexpr(ea), getFReg(fD)); 11520 } 11521 DIP("f%ss%s s%u, [r%u, %c#%u]\n", 11522 bL ? "ld" : "st", nCC(conq), fD, rN, 11523 bU ? '+' : '-', offset); 11524 goto decode_success_vfp; 11525 } 11526 11527 /* --------------------- dp insns (F) --------------------- */ 11528 if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0)) 11529 && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0)) 11530 && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) { 11531 UInt bM = (insn28 >> 5) & 1; 11532 UInt bD = (insn28 >> 22) & 1; 11533 UInt bN = (insn28 >> 7) & 1; 11534 UInt fM = (INSN(3,0) << 1) | bM; /* argR */ 11535 UInt fD = (INSN(15,12) << 1) | bD; /* dst/acc */ 11536 UInt fN = (INSN(19,16) << 1) | bN; /* argL */ 11537 UInt bP = (insn28 >> 23) & 1; 11538 UInt bQ = (insn28 >> 21) & 1; 11539 UInt bR = (insn28 >> 20) & 1; 11540 UInt bS = (insn28 >> 6) & 1; 11541 UInt opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS; 11542 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */ 11543 switch (opc) { 11544 case BITS4(0,0,0,0): /* MAC: d + n * m */ 11545 putFReg(fD, triop(Iop_AddF32, rm, 11546 getFReg(fD), 11547 triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))), 11548 condT); 11549 DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 11550 goto decode_success_vfp; 11551 case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */ 11552 putFReg(fD, triop(Iop_AddF32, rm, 11553 getFReg(fD), 11554 unop(Iop_NegF32, 11555 triop(Iop_MulF32, rm, getFReg(fN), 11556 getFReg(fM)))), 11557 condT); 11558 DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 11559 goto decode_success_vfp; 11560 case BITS4(0,0,1,0): /* MSC: - d + n * m */ 11561 putFReg(fD, triop(Iop_AddF32, rm, 11562 unop(Iop_NegF32, getFReg(fD)), 11563 triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))), 11564 condT); 11565 DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 11566 goto decode_success_vfp; 11567 case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */ 11568 putFReg(fD, triop(Iop_AddF32, rm, 11569 unop(Iop_NegF32, getFReg(fD)), 11570 unop(Iop_NegF32, 11571 triop(Iop_MulF32, rm, 11572 getFReg(fN), 11573 getFReg(fM)))), 11574 condT); 11575 DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 11576 goto decode_success_vfp; 11577 case BITS4(0,1,0,0): /* MUL: n * m */ 11578 putFReg(fD, triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM)), 11579 condT); 11580 DIP("fmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 11581 goto decode_success_vfp; 11582 case BITS4(0,1,0,1): /* NMUL: - n * m */ 11583 putFReg(fD, unop(Iop_NegF32, 11584 triop(Iop_MulF32, rm, getFReg(fN), 11585 getFReg(fM))), 11586 condT); 11587 DIP("fnmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 11588 goto decode_success_vfp; 11589 case BITS4(0,1,1,0): /* ADD: n + m */ 11590 putFReg(fD, triop(Iop_AddF32, rm, getFReg(fN), getFReg(fM)), 11591 condT); 11592 DIP("fadds%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 11593 goto decode_success_vfp; 11594 case BITS4(0,1,1,1): /* SUB: n - m */ 11595 putFReg(fD, triop(Iop_SubF32, rm, getFReg(fN), getFReg(fM)), 11596 condT); 11597 DIP("fsubs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 11598 goto decode_success_vfp; 11599 case BITS4(1,0,0,0): /* DIV: n / m */ 11600 putFReg(fD, triop(Iop_DivF32, rm, getFReg(fN), getFReg(fM)), 11601 condT); 11602 DIP("fdivs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM); 11603 goto decode_success_vfp; 11604 default: 11605 break; 11606 } 11607 } 11608 11609 /* --------------------- compares (S) --------------------- */ 11610 /* 31 27 23 19 15 11 7 3 11611 28 24 20 16 12 8 4 0 11612 FCMPS cond 1110 1D11 0100 Fd 1010 01M0 Fm 11613 FCMPES cond 1110 1D11 0100 Fd 1010 11M0 Fm 11614 FCMPZS cond 1110 1D11 0101 Fd 1010 0100 0000 11615 FCMPZED cond 1110 1D11 0101 Fd 1010 1100 0000 11616 Z N 11617 11618 Z=0 Compare Fd:D vs Fm:M and set FPSCR 31:28 accordingly 11619 Z=1 Compare Fd:D vs zero 11620 11621 N=1 generates Invalid Operation exn if either arg is any kind of NaN 11622 N=0 generates Invalid Operation exn if either arg is a signalling NaN 11623 (Not that we pay any attention to N here) 11624 */ 11625 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11626 && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 11627 && BITS4(1,0,1,0) == INSN(11,8) 11628 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11629 UInt bZ = (insn28 >> 16) & 1; 11630 UInt bN = (insn28 >> 7) & 1; 11631 UInt bD = (insn28 >> 22) & 1; 11632 UInt bM = (insn28 >> 5) & 1; 11633 UInt fD = (INSN(15,12) << 1) | bD; 11634 UInt fM = (INSN(3,0) << 1) | bM; 11635 if (bZ && (INSN(3,0) != 0 || (INSN(7,4) & 3) != 0)) { 11636 /* does not decode; fall through */ 11637 } else { 11638 IRTemp argL = newTemp(Ity_F64); 11639 IRTemp argR = newTemp(Ity_F64); 11640 IRTemp irRes = newTemp(Ity_I32); 11641 11642 assign(argL, unop(Iop_F32toF64, getFReg(fD))); 11643 assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0)) 11644 : unop(Iop_F32toF64, getFReg(fM))); 11645 assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR))); 11646 11647 IRTemp nzcv = IRTemp_INVALID; 11648 IRTemp oldFPSCR = newTemp(Ity_I32); 11649 IRTemp newFPSCR = newTemp(Ity_I32); 11650 11651 /* This is where the fun starts. We have to convert 'irRes' 11652 from an IR-convention return result (IRCmpF64Result) to an 11653 ARM-encoded (N,Z,C,V) group. The final result is in the 11654 bottom 4 bits of 'nzcv'. */ 11655 /* Map compare result from IR to ARM(nzcv) */ 11656 /* 11657 FP cmp result | IR | ARM(nzcv) 11658 -------------------------------- 11659 UN 0x45 0011 11660 LT 0x01 1000 11661 GT 0x00 0010 11662 EQ 0x40 0110 11663 */ 11664 nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes); 11665 11666 /* And update FPSCR accordingly */ 11667 assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32)); 11668 assign(newFPSCR, 11669 binop(Iop_Or32, 11670 binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)), 11671 binop(Iop_Shl32, mkexpr(nzcv), mkU8(28)))); 11672 11673 putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT); 11674 11675 if (bZ) { 11676 DIP("fcmpz%ss%s s%u\n", bN ? "e" : "", nCC(conq), fD); 11677 } else { 11678 DIP("fcmp%ss%s s%u, s%u\n", bN ? "e" : "", 11679 nCC(conq), fD, fM); 11680 } 11681 goto decode_success_vfp; 11682 } 11683 /* fall through */ 11684 } 11685 11686 /* --------------------- unary (S) --------------------- */ 11687 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11688 && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 11689 && BITS4(1,0,1,0) == INSN(11,8) 11690 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11691 UInt bD = (insn28 >> 22) & 1; 11692 UInt bM = (insn28 >> 5) & 1; 11693 UInt fD = (INSN(15,12) << 1) | bD; 11694 UInt fM = (INSN(3,0) << 1) | bM; 11695 UInt b16 = (insn28 >> 16) & 1; 11696 UInt b7 = (insn28 >> 7) & 1; 11697 /**/ if (b16 == 0 && b7 == 0) { 11698 // FCPYS 11699 putFReg(fD, getFReg(fM), condT); 11700 DIP("fcpys%s s%u, s%u\n", nCC(conq), fD, fM); 11701 goto decode_success_vfp; 11702 } 11703 else if (b16 == 0 && b7 == 1) { 11704 // FABSS 11705 putFReg(fD, unop(Iop_AbsF32, getFReg(fM)), condT); 11706 DIP("fabss%s s%u, s%u\n", nCC(conq), fD, fM); 11707 goto decode_success_vfp; 11708 } 11709 else if (b16 == 1 && b7 == 0) { 11710 // FNEGS 11711 putFReg(fD, unop(Iop_NegF32, getFReg(fM)), condT); 11712 DIP("fnegs%s s%u, s%u\n", nCC(conq), fD, fM); 11713 goto decode_success_vfp; 11714 } 11715 else if (b16 == 1 && b7 == 1) { 11716 // FSQRTS 11717 IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */ 11718 putFReg(fD, binop(Iop_SqrtF32, rm, getFReg(fM)), condT); 11719 DIP("fsqrts%s s%u, s%u\n", nCC(conq), fD, fM); 11720 goto decode_success_vfp; 11721 } 11722 else 11723 vassert(0); 11724 11725 /* fall through */ 11726 } 11727 11728 /* ----------------- I <-> S conversions ----------------- */ 11729 11730 // F{S,U}ITOS fD, fM 11731 /* These are more complex than FSITOD/FUITOD. In the D cases, a 32 11732 bit int will always fit within the 53 bit mantissa, so there's 11733 no possibility of a loss of precision, but that's obviously not 11734 the case here. Hence this case possibly requires rounding, and 11735 so it drags in the current rounding mode. */ 11736 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11737 && BITS4(1,0,0,0) == INSN(19,16) 11738 && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0)) 11739 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11740 UInt bM = (insn28 >> 5) & 1; 11741 UInt bD = (insn28 >> 22) & 1; 11742 UInt fM = (INSN(3,0) << 1) | bM; 11743 UInt fD = (INSN(15,12) << 1) | bD; 11744 UInt syned = (insn28 >> 7) & 1; 11745 IRTemp rmode = newTemp(Ity_I32); 11746 assign(rmode, mkexpr(mk_get_IR_rounding_mode())); 11747 if (syned) { 11748 // FSITOS 11749 putFReg(fD, binop(Iop_F64toF32, 11750 mkexpr(rmode), 11751 unop(Iop_I32StoF64, 11752 unop(Iop_ReinterpF32asI32, getFReg(fM)))), 11753 condT); 11754 DIP("fsitos%s s%u, s%u\n", nCC(conq), fD, fM); 11755 } else { 11756 // FUITOS 11757 putFReg(fD, binop(Iop_F64toF32, 11758 mkexpr(rmode), 11759 unop(Iop_I32UtoF64, 11760 unop(Iop_ReinterpF32asI32, getFReg(fM)))), 11761 condT); 11762 DIP("fuitos%s s%u, s%u\n", nCC(conq), fD, fM); 11763 } 11764 goto decode_success_vfp; 11765 } 11766 11767 // FTO{S,U}IS fD, fM 11768 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11769 && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0)) 11770 && BITS4(1,0,1,0) == INSN(11,8) 11771 && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) { 11772 UInt bM = (insn28 >> 5) & 1; 11773 UInt bD = (insn28 >> 22) & 1; 11774 UInt fD = (INSN(15,12) << 1) | bD; 11775 UInt fM = (INSN(3,0) << 1) | bM; 11776 UInt bZ = (insn28 >> 7) & 1; 11777 UInt syned = (insn28 >> 16) & 1; 11778 IRTemp rmode = newTemp(Ity_I32); 11779 assign(rmode, bZ ? mkU32(Irrm_ZERO) 11780 : mkexpr(mk_get_IR_rounding_mode())); 11781 if (syned) { 11782 // FTOSIS 11783 putFReg(fD, unop(Iop_ReinterpI32asF32, 11784 binop(Iop_F64toI32S, mkexpr(rmode), 11785 unop(Iop_F32toF64, getFReg(fM)))), 11786 condT); 11787 DIP("ftosi%ss%s s%u, d%u\n", bZ ? "z" : "", 11788 nCC(conq), fD, fM); 11789 goto decode_success_vfp; 11790 } else { 11791 // FTOUIS 11792 putFReg(fD, unop(Iop_ReinterpI32asF32, 11793 binop(Iop_F64toI32U, mkexpr(rmode), 11794 unop(Iop_F32toF64, getFReg(fM)))), 11795 condT); 11796 DIP("ftoui%ss%s s%u, d%u\n", bZ ? "z" : "", 11797 nCC(conq), fD, fM); 11798 goto decode_success_vfp; 11799 } 11800 } 11801 11802 /* ----------------- S <-> D conversions ----------------- */ 11803 11804 // FCVTDS 11805 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11806 && BITS4(0,1,1,1) == INSN(19,16) 11807 && BITS4(1,0,1,0) == INSN(11,8) 11808 && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) { 11809 UInt dD = INSN(15,12) | (INSN(22,22) << 4); 11810 UInt bM = (insn28 >> 5) & 1; 11811 UInt fM = (INSN(3,0) << 1) | bM; 11812 putDReg(dD, unop(Iop_F32toF64, getFReg(fM)), condT); 11813 DIP("fcvtds%s d%u, s%u\n", nCC(conq), dD, fM); 11814 goto decode_success_vfp; 11815 } 11816 11817 // FCVTSD 11818 if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 11819 && BITS4(0,1,1,1) == INSN(19,16) 11820 && BITS4(1,0,1,1) == INSN(11,8) 11821 && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) { 11822 UInt bD = (insn28 >> 22) & 1; 11823 UInt fD = (INSN(15,12) << 1) | bD; 11824 UInt dM = INSN(3,0) | (INSN(5,5) << 4); 11825 IRTemp rmode = newTemp(Ity_I32); 11826 assign(rmode, mkexpr(mk_get_IR_rounding_mode())); 11827 putFReg(fD, binop(Iop_F64toF32, mkexpr(rmode), getDReg(dM)), 11828 condT); 11829 DIP("fcvtsd%s s%u, d%u\n", nCC(conq), fD, dM); 11830 goto decode_success_vfp; 11831 } 11832 11833 /* FAILURE */ 11834 return False; 11835 11836 decode_success_vfp: 11837 /* Check that any accepted insn really is a CP10 or CP11 insn, iow, 11838 assert that we aren't accepting, in this fn, insns that actually 11839 should be handled somewhere else. */ 11840 vassert(INSN(11,9) == BITS3(1,0,1)); // 11:8 = 1010 or 1011 11841 return True; 11842 11843 # undef INSN 11844 } 11845 11846 11847 /*------------------------------------------------------------*/ 11848 /*--- Instructions in NV (never) space ---*/ 11849 /*------------------------------------------------------------*/ 11850 11851 /* ARM only */ 11852 /* Translate a NV space instruction. If successful, returns True and 11853 *dres may or may not be updated. If failure, returns False and 11854 doesn't change *dres nor create any IR. 11855 11856 Note that all NEON instructions (in ARM mode) are handled through 11857 here, since they are all in NV space. 11858 */ 11859 static Bool decode_NV_instruction ( /*MOD*/DisResult* dres, 11860 VexArchInfo* archinfo, 11861 UInt insn ) 11862 { 11863 # define INSN(_bMax,_bMin) SLICE_UInt(insn, (_bMax), (_bMin)) 11864 # define INSN_COND SLICE_UInt(insn, 31, 28) 11865 11866 HChar dis_buf[128]; 11867 11868 // Should only be called for NV instructions 11869 vassert(BITS4(1,1,1,1) == INSN_COND); 11870 11871 /* ------------------------ pld ------------------------ */ 11872 if (BITS8(0,1,0,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) 11873 && BITS4(1,1,1,1) == INSN(15,12)) { 11874 UInt rN = INSN(19,16); 11875 UInt imm12 = INSN(11,0); 11876 UInt bU = INSN(23,23); 11877 DIP("pld [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12); 11878 return True; 11879 } 11880 11881 if (BITS8(0,1,1,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) 11882 && BITS4(1,1,1,1) == INSN(15,12) 11883 && 0 == INSN(4,4)) { 11884 UInt rN = INSN(19,16); 11885 UInt rM = INSN(3,0); 11886 UInt imm5 = INSN(11,7); 11887 UInt sh2 = INSN(6,5); 11888 UInt bU = INSN(23,23); 11889 if (rM != 15) { 11890 IRExpr* eaE = mk_EA_reg_plusminus_shifted_reg(rN, bU, rM, 11891 sh2, imm5, dis_buf); 11892 IRTemp eaT = newTemp(Ity_I32); 11893 /* Bind eaE to a temp merely for debugging-vex purposes, so we 11894 can check it's a plausible decoding. It will get removed 11895 by iropt a little later on. */ 11896 vassert(eaE); 11897 assign(eaT, eaE); 11898 DIP("pld %s\n", dis_buf); 11899 return True; 11900 } 11901 /* fall through */ 11902 } 11903 11904 /* ------------------------ pli ------------------------ */ 11905 if (BITS8(0,1,0,0, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1)) 11906 && BITS4(1,1,1,1) == INSN(15,12)) { 11907 UInt rN = INSN(19,16); 11908 UInt imm12 = INSN(11,0); 11909 UInt bU = INSN(23,23); 11910 DIP("pli [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12); 11911 return True; 11912 } 11913 11914 /* --------------------- Interworking branches --------------------- */ 11915 11916 // BLX (1), viz, unconditional branch and link to R15+simm24 11917 // and set CPSR.T = 1, that is, switch to Thumb mode 11918 if (INSN(31,25) == BITS7(1,1,1,1,1,0,1)) { 11919 UInt bitH = INSN(24,24); 11920 Int uimm24 = INSN(23,0); 11921 Int simm24 = (((uimm24 << 8) >> 8) << 2) + (bitH << 1); 11922 /* Now this is a bit tricky. Since we're decoding an ARM insn, 11923 it is implies that CPSR.T == 0. Hence the current insn's 11924 address is guaranteed to be of the form X--(30)--X00. So, no 11925 need to mask any bits off it. But need to set the lowest bit 11926 to 1 to denote we're in Thumb mode after this, since 11927 guest_R15T has CPSR.T as the lowest bit. And we can't chase 11928 into the call, so end the block at this point. */ 11929 UInt dst = guest_R15_curr_instr_notENC + 8 + (simm24 | 1); 11930 putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4), 11931 IRTemp_INVALID/*because AL*/, Ijk_Boring ); 11932 irsb->next = mkU32(dst); 11933 irsb->jumpkind = Ijk_Call; 11934 dres->whatNext = Dis_StopHere; 11935 DIP("blx 0x%x (and switch to Thumb mode)\n", dst - 1); 11936 return True; 11937 } 11938 11939 /* ------------------- v7 barrier insns ------------------- */ 11940 switch (insn) { 11941 case 0xF57FF06F: /* ISB */ 11942 stmt( IRStmt_MBE(Imbe_Fence) ); 11943 DIP("ISB\n"); 11944 return True; 11945 case 0xF57FF04F: /* DSB sy */ 11946 case 0xF57FF04E: /* DSB st */ 11947 case 0xF57FF04B: /* DSB ish */ 11948 case 0xF57FF04A: /* DSB ishst */ 11949 case 0xF57FF047: /* DSB nsh */ 11950 case 0xF57FF046: /* DSB nshst */ 11951 case 0xF57FF043: /* DSB osh */ 11952 case 0xF57FF042: /* DSB oshst */ 11953 stmt( IRStmt_MBE(Imbe_Fence) ); 11954 DIP("DSB\n"); 11955 return True; 11956 case 0xF57FF05F: /* DMB sy */ 11957 case 0xF57FF05E: /* DMB st */ 11958 case 0xF57FF05B: /* DMB ish */ 11959 case 0xF57FF05A: /* DMB ishst */ 11960 case 0xF57FF057: /* DMB nsh */ 11961 case 0xF57FF056: /* DMB nshst */ 11962 case 0xF57FF053: /* DMB osh */ 11963 case 0xF57FF052: /* DMB oshst */ 11964 stmt( IRStmt_MBE(Imbe_Fence) ); 11965 DIP("DMB\n"); 11966 return True; 11967 default: 11968 break; 11969 } 11970 11971 /* ------------------- NEON ------------------- */ 11972 if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) { 11973 Bool ok_neon = decode_NEON_instruction( 11974 dres, insn, IRTemp_INVALID/*unconditional*/, 11975 False/*!isT*/ 11976 ); 11977 if (ok_neon) 11978 return True; 11979 } 11980 11981 // unrecognised 11982 return False; 11983 11984 # undef INSN_COND 11985 # undef INSN 11986 } 11987 11988 11989 /*------------------------------------------------------------*/ 11990 /*--- Disassemble a single ARM instruction ---*/ 11991 /*------------------------------------------------------------*/ 11992 11993 /* Disassemble a single ARM instruction into IR. The instruction is 11994 located in host memory at guest_instr, and has (decoded) guest IP 11995 of guest_R15_curr_instr_notENC, which will have been set before the 11996 call here. */ 11997 11998 static 11999 DisResult disInstr_ARM_WRK ( 12000 Bool put_IP, 12001 Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ), 12002 Bool resteerCisOk, 12003 void* callback_opaque, 12004 UChar* guest_instr, 12005 VexArchInfo* archinfo, 12006 VexAbiInfo* abiinfo 12007 ) 12008 { 12009 // A macro to fish bits out of 'insn'. 12010 # define INSN(_bMax,_bMin) SLICE_UInt(insn, (_bMax), (_bMin)) 12011 # define INSN_COND SLICE_UInt(insn, 31, 28) 12012 12013 DisResult dres; 12014 UInt insn; 12015 //Bool allow_VFP = False; 12016 //UInt hwcaps = archinfo->hwcaps; 12017 IRTemp condT; /* :: Ity_I32 */ 12018 UInt summary; 12019 HChar dis_buf[128]; // big enough to hold LDMIA etc text 12020 12021 /* What insn variants are we supporting today? */ 12022 //allow_VFP = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP)); 12023 // etc etc 12024 12025 /* Set result defaults. */ 12026 dres.whatNext = Dis_Continue; 12027 dres.len = 4; 12028 dres.continueAt = 0; 12029 12030 /* Set default actions for post-insn handling of writes to r15, if 12031 required. */ 12032 r15written = False; 12033 r15guard = IRTemp_INVALID; /* unconditional */ 12034 r15kind = Ijk_Boring; 12035 12036 /* At least this is simple on ARM: insns are all 4 bytes long, and 12037 4-aligned. So just fish the whole thing out of memory right now 12038 and have done. */ 12039 insn = getUIntLittleEndianly( guest_instr ); 12040 12041 if (0) vex_printf("insn: 0x%x\n", insn); 12042 12043 DIP("\t(arm) 0x%x: ", (UInt)guest_R15_curr_instr_notENC); 12044 12045 /* We may be asked to update the guest R15 before going further. */ 12046 vassert(0 == (guest_R15_curr_instr_notENC & 3)); 12047 if (put_IP) { 12048 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) ); 12049 } 12050 12051 /* ----------------------------------------------------------- */ 12052 12053 /* Spot "Special" instructions (see comment at top of file). */ 12054 { 12055 UChar* code = (UChar*)guest_instr; 12056 /* Spot the 16-byte preamble: 12057 12058 e1a0c1ec mov r12, r12, ROR #3 12059 e1a0c6ec mov r12, r12, ROR #13 12060 e1a0ceec mov r12, r12, ROR #29 12061 e1a0c9ec mov r12, r12, ROR #19 12062 */ 12063 UInt word1 = 0xE1A0C1EC; 12064 UInt word2 = 0xE1A0C6EC; 12065 UInt word3 = 0xE1A0CEEC; 12066 UInt word4 = 0xE1A0C9EC; 12067 if (getUIntLittleEndianly(code+ 0) == word1 && 12068 getUIntLittleEndianly(code+ 4) == word2 && 12069 getUIntLittleEndianly(code+ 8) == word3 && 12070 getUIntLittleEndianly(code+12) == word4) { 12071 /* Got a "Special" instruction preamble. Which one is it? */ 12072 if (getUIntLittleEndianly(code+16) == 0xE18AA00A 12073 /* orr r10,r10,r10 */) { 12074 /* R3 = client_request ( R4 ) */ 12075 DIP("r3 = client_request ( %%r4 )\n"); 12076 irsb->next = mkU32( guest_R15_curr_instr_notENC + 20 ); 12077 irsb->jumpkind = Ijk_ClientReq; 12078 dres.whatNext = Dis_StopHere; 12079 goto decode_success; 12080 } 12081 else 12082 if (getUIntLittleEndianly(code+16) == 0xE18BB00B 12083 /* orr r11,r11,r11 */) { 12084 /* R3 = guest_NRADDR */ 12085 DIP("r3 = guest_NRADDR\n"); 12086 dres.len = 20; 12087 llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 )); 12088 goto decode_success; 12089 } 12090 else 12091 if (getUIntLittleEndianly(code+16) == 0xE18CC00C 12092 /* orr r12,r12,r12 */) { 12093 /* branch-and-link-to-noredir R4 */ 12094 DIP("branch-and-link-to-noredir r4\n"); 12095 llPutIReg(14, mkU32( guest_R15_curr_instr_notENC + 20) ); 12096 irsb->next = llGetIReg(4); 12097 irsb->jumpkind = Ijk_NoRedir; 12098 dres.whatNext = Dis_StopHere; 12099 goto decode_success; 12100 } 12101 /* We don't know what it is. Set opc1/opc2 so decode_failure 12102 can print the insn following the Special-insn preamble. */ 12103 insn = getUIntLittleEndianly(code+16); 12104 goto decode_failure; 12105 /*NOTREACHED*/ 12106 } 12107 12108 } 12109 12110 /* ----------------------------------------------------------- */ 12111 12112 /* Main ARM instruction decoder starts here. */ 12113 12114 /* Deal with the condition. Strategy is to merely generate a 12115 condition temporary at this point (or IRTemp_INVALID, meaning 12116 unconditional). We leave it to lower-level instruction decoders 12117 to decide whether they can generate straight-line code, or 12118 whether they must generate a side exit before the instruction. 12119 condT :: Ity_I32 and is always either zero or one. */ 12120 condT = IRTemp_INVALID; 12121 switch ( (ARMCondcode)INSN_COND ) { 12122 case ARMCondNV: { 12123 // Illegal instruction prior to v5 (see ARM ARM A3-5), but 12124 // some cases are acceptable 12125 Bool ok = decode_NV_instruction(&dres, archinfo, insn); 12126 if (ok) 12127 goto decode_success; 12128 else 12129 goto decode_failure; 12130 } 12131 case ARMCondAL: // Always executed 12132 break; 12133 case ARMCondEQ: case ARMCondNE: case ARMCondHS: case ARMCondLO: 12134 case ARMCondMI: case ARMCondPL: case ARMCondVS: case ARMCondVC: 12135 case ARMCondHI: case ARMCondLS: case ARMCondGE: case ARMCondLT: 12136 case ARMCondGT: case ARMCondLE: 12137 condT = newTemp(Ity_I32); 12138 assign( condT, mk_armg_calculate_condition( INSN_COND )); 12139 break; 12140 } 12141 12142 /* ----------------------------------------------------------- */ 12143 /* -- ARMv5 integer instructions -- */ 12144 /* ----------------------------------------------------------- */ 12145 12146 /* ---------------- Data processing ops ------------------- */ 12147 12148 if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) 12149 && !(INSN(25,25) == 0 && INSN(7,7) == 1 && INSN(4,4) == 1)) { 12150 IRTemp shop = IRTemp_INVALID; /* shifter operand */ 12151 IRTemp shco = IRTemp_INVALID; /* shifter carry out */ 12152 UInt rD = (insn >> 12) & 0xF; /* 15:12 */ 12153 UInt rN = (insn >> 16) & 0xF; /* 19:16 */ 12154 UInt bitS = (insn >> 20) & 1; /* 20:20 */ 12155 IRTemp rNt = IRTemp_INVALID; 12156 IRTemp res = IRTemp_INVALID; 12157 IRTemp oldV = IRTemp_INVALID; 12158 IRTemp oldC = IRTemp_INVALID; 12159 HChar* name = NULL; 12160 IROp op = Iop_INVALID; 12161 Bool ok; 12162 12163 switch (INSN(24,21)) { 12164 12165 /* --------- ADD, SUB, AND, OR --------- */ 12166 case BITS4(0,1,0,0): /* ADD: Rd = Rn + shifter_operand */ 12167 name = "add"; op = Iop_Add32; goto rd_eq_rn_op_SO; 12168 case BITS4(0,0,1,0): /* SUB: Rd = Rn - shifter_operand */ 12169 name = "sub"; op = Iop_Sub32; goto rd_eq_rn_op_SO; 12170 case BITS4(0,0,1,1): /* RSB: Rd = shifter_operand - Rn */ 12171 name = "rsb"; op = Iop_Sub32; goto rd_eq_rn_op_SO; 12172 case BITS4(0,0,0,0): /* AND: Rd = Rn & shifter_operand */ 12173 name = "and"; op = Iop_And32; goto rd_eq_rn_op_SO; 12174 case BITS4(1,1,0,0): /* OR: Rd = Rn | shifter_operand */ 12175 name = "orr"; op = Iop_Or32; goto rd_eq_rn_op_SO; 12176 case BITS4(0,0,0,1): /* EOR: Rd = Rn ^ shifter_operand */ 12177 name = "eor"; op = Iop_Xor32; goto rd_eq_rn_op_SO; 12178 case BITS4(1,1,1,0): /* BIC: Rd = Rn & ~shifter_operand */ 12179 name = "bic"; op = Iop_And32; goto rd_eq_rn_op_SO; 12180 rd_eq_rn_op_SO: { 12181 Bool isRSB = False; 12182 Bool isBIC = False; 12183 switch (INSN(24,21)) { 12184 case BITS4(0,0,1,1): 12185 vassert(op == Iop_Sub32); isRSB = True; break; 12186 case BITS4(1,1,1,0): 12187 vassert(op == Iop_And32); isBIC = True; break; 12188 default: 12189 break; 12190 } 12191 rNt = newTemp(Ity_I32); 12192 assign(rNt, getIRegA(rN)); 12193 ok = mk_shifter_operand( 12194 INSN(25,25), INSN(11,0), 12195 &shop, bitS ? &shco : NULL, dis_buf 12196 ); 12197 if (!ok) 12198 break; 12199 res = newTemp(Ity_I32); 12200 // compute the main result 12201 if (isRSB) { 12202 // reverse-subtract: shifter_operand - Rn 12203 vassert(op == Iop_Sub32); 12204 assign(res, binop(op, mkexpr(shop), mkexpr(rNt)) ); 12205 } else if (isBIC) { 12206 // andn: shifter_operand & ~Rn 12207 vassert(op == Iop_And32); 12208 assign(res, binop(op, mkexpr(rNt), 12209 unop(Iop_Not32, mkexpr(shop))) ); 12210 } else { 12211 // normal: Rn op shifter_operand 12212 assign(res, binop(op, mkexpr(rNt), mkexpr(shop)) ); 12213 } 12214 // but don't commit it until after we've finished 12215 // all necessary reads from the guest state 12216 if (bitS 12217 && (op == Iop_And32 || op == Iop_Or32 || op == Iop_Xor32)) { 12218 oldV = newTemp(Ity_I32); 12219 assign( oldV, mk_armg_calculate_flag_v() ); 12220 } 12221 // can't safely read guest state after here 12222 // now safe to put the main result 12223 putIRegA( rD, mkexpr(res), condT, Ijk_Boring ); 12224 // XXXX!! not safe to read any guest state after 12225 // this point (I think the code below doesn't do that). 12226 if (!bitS) 12227 vassert(shco == IRTemp_INVALID); 12228 /* Update the flags thunk if necessary */ 12229 if (bitS) { 12230 vassert(shco != IRTemp_INVALID); 12231 switch (op) { 12232 case Iop_Add32: 12233 setFlags_D1_D2( ARMG_CC_OP_ADD, rNt, shop, condT ); 12234 break; 12235 case Iop_Sub32: 12236 if (isRSB) { 12237 setFlags_D1_D2( ARMG_CC_OP_SUB, shop, rNt, condT ); 12238 } else { 12239 setFlags_D1_D2( ARMG_CC_OP_SUB, rNt, shop, condT ); 12240 } 12241 break; 12242 case Iop_And32: /* BIC and AND set the flags the same */ 12243 case Iop_Or32: 12244 case Iop_Xor32: 12245 // oldV has been read just above 12246 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, 12247 res, shco, oldV, condT ); 12248 break; 12249 default: 12250 vassert(0); 12251 } 12252 } 12253 DIP("%s%s%s r%u, r%u, %s\n", 12254 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf ); 12255 goto decode_success; 12256 } 12257 12258 /* --------- MOV, MVN --------- */ 12259 case BITS4(1,1,0,1): /* MOV: Rd = shifter_operand */ 12260 case BITS4(1,1,1,1): { /* MVN: Rd = not(shifter_operand) */ 12261 Bool isMVN = INSN(24,21) == BITS4(1,1,1,1); 12262 if (rN != 0) 12263 break; /* rN must be zero */ 12264 ok = mk_shifter_operand( 12265 INSN(25,25), INSN(11,0), 12266 &shop, bitS ? &shco : NULL, dis_buf 12267 ); 12268 if (!ok) 12269 break; 12270 res = newTemp(Ity_I32); 12271 assign( res, isMVN ? unop(Iop_Not32, mkexpr(shop)) 12272 : mkexpr(shop) ); 12273 if (bitS) { 12274 vassert(shco != IRTemp_INVALID); 12275 oldV = newTemp(Ity_I32); 12276 assign( oldV, mk_armg_calculate_flag_v() ); 12277 } else { 12278 vassert(shco == IRTemp_INVALID); 12279 } 12280 // can't safely read guest state after here 12281 putIRegA( rD, mkexpr(res), condT, Ijk_Boring ); 12282 /* Update the flags thunk if necessary */ 12283 if (bitS) { 12284 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, 12285 res, shco, oldV, condT ); 12286 } 12287 DIP("%s%s%s r%u, %s\n", 12288 isMVN ? "mvn" : "mov", 12289 nCC(INSN_COND), bitS ? "s" : "", rD, dis_buf ); 12290 goto decode_success; 12291 } 12292 12293 /* --------- CMP --------- */ 12294 case BITS4(1,0,1,0): /* CMP: (void) Rn - shifter_operand */ 12295 case BITS4(1,0,1,1): { /* CMN: (void) Rn + shifter_operand */ 12296 Bool isCMN = INSN(24,21) == BITS4(1,0,1,1); 12297 if (rD != 0) 12298 break; /* rD must be zero */ 12299 if (bitS == 0) 12300 break; /* if S (bit 20) is not set, it's not CMP/CMN */ 12301 rNt = newTemp(Ity_I32); 12302 assign(rNt, getIRegA(rN)); 12303 ok = mk_shifter_operand( 12304 INSN(25,25), INSN(11,0), 12305 &shop, NULL, dis_buf 12306 ); 12307 if (!ok) 12308 break; 12309 // can't safely read guest state after here 12310 /* Update the flags thunk. */ 12311 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB, 12312 rNt, shop, condT ); 12313 DIP("%s%s r%u, %s\n", 12314 isCMN ? "cmn" : "cmp", 12315 nCC(INSN_COND), rN, dis_buf ); 12316 goto decode_success; 12317 } 12318 12319 /* --------- TST --------- */ 12320 case BITS4(1,0,0,0): /* TST: (void) Rn & shifter_operand */ 12321 case BITS4(1,0,0,1): { /* TEQ: (void) Rn ^ shifter_operand */ 12322 Bool isTEQ = INSN(24,21) == BITS4(1,0,0,1); 12323 if (rD != 0) 12324 break; /* rD must be zero */ 12325 if (bitS == 0) 12326 break; /* if S (bit 20) is not set, it's not TST/TEQ */ 12327 rNt = newTemp(Ity_I32); 12328 assign(rNt, getIRegA(rN)); 12329 ok = mk_shifter_operand( 12330 INSN(25,25), INSN(11,0), 12331 &shop, &shco, dis_buf 12332 ); 12333 if (!ok) 12334 break; 12335 /* Update the flags thunk. */ 12336 res = newTemp(Ity_I32); 12337 assign( res, binop(isTEQ ? Iop_Xor32 : Iop_And32, 12338 mkexpr(rNt), mkexpr(shop)) ); 12339 oldV = newTemp(Ity_I32); 12340 assign( oldV, mk_armg_calculate_flag_v() ); 12341 // can't safely read guest state after here 12342 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, 12343 res, shco, oldV, condT ); 12344 DIP("%s%s r%u, %s\n", 12345 isTEQ ? "teq" : "tst", 12346 nCC(INSN_COND), rN, dis_buf ); 12347 goto decode_success; 12348 } 12349 12350 /* --------- ADC, SBC, RSC --------- */ 12351 case BITS4(0,1,0,1): /* ADC: Rd = Rn + shifter_operand + oldC */ 12352 name = "adc"; goto rd_eq_rn_op_SO_op_oldC; 12353 case BITS4(0,1,1,0): /* SBC: Rd = Rn - shifter_operand - (oldC ^ 1) */ 12354 name = "sbc"; goto rd_eq_rn_op_SO_op_oldC; 12355 case BITS4(0,1,1,1): /* RSC: Rd = shifter_operand - Rn - (oldC ^ 1) */ 12356 name = "rsc"; goto rd_eq_rn_op_SO_op_oldC; 12357 rd_eq_rn_op_SO_op_oldC: { 12358 // FIXME: shco isn't used for anything. Get rid of it. 12359 rNt = newTemp(Ity_I32); 12360 assign(rNt, getIRegA(rN)); 12361 ok = mk_shifter_operand( 12362 INSN(25,25), INSN(11,0), 12363 &shop, bitS ? &shco : NULL, dis_buf 12364 ); 12365 if (!ok) 12366 break; 12367 oldC = newTemp(Ity_I32); 12368 assign( oldC, mk_armg_calculate_flag_c() ); 12369 res = newTemp(Ity_I32); 12370 // compute the main result 12371 switch (INSN(24,21)) { 12372 case BITS4(0,1,0,1): /* ADC */ 12373 assign(res, 12374 binop(Iop_Add32, 12375 binop(Iop_Add32, mkexpr(rNt), mkexpr(shop)), 12376 mkexpr(oldC) )); 12377 break; 12378 case BITS4(0,1,1,0): /* SBC */ 12379 assign(res, 12380 binop(Iop_Sub32, 12381 binop(Iop_Sub32, mkexpr(rNt), mkexpr(shop)), 12382 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) )); 12383 break; 12384 case BITS4(0,1,1,1): /* RSC */ 12385 assign(res, 12386 binop(Iop_Sub32, 12387 binop(Iop_Sub32, mkexpr(shop), mkexpr(rNt)), 12388 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) )); 12389 break; 12390 default: 12391 vassert(0); 12392 } 12393 // but don't commit it until after we've finished 12394 // all necessary reads from the guest state 12395 // now safe to put the main result 12396 putIRegA( rD, mkexpr(res), condT, Ijk_Boring ); 12397 // XXXX!! not safe to read any guest state after 12398 // this point (I think the code below doesn't do that). 12399 if (!bitS) 12400 vassert(shco == IRTemp_INVALID); 12401 /* Update the flags thunk if necessary */ 12402 if (bitS) { 12403 vassert(shco != IRTemp_INVALID); 12404 switch (INSN(24,21)) { 12405 case BITS4(0,1,0,1): /* ADC */ 12406 setFlags_D1_D2_ND( ARMG_CC_OP_ADC, 12407 rNt, shop, oldC, condT ); 12408 break; 12409 case BITS4(0,1,1,0): /* SBC */ 12410 setFlags_D1_D2_ND( ARMG_CC_OP_SBB, 12411 rNt, shop, oldC, condT ); 12412 break; 12413 case BITS4(0,1,1,1): /* RSC */ 12414 setFlags_D1_D2_ND( ARMG_CC_OP_SBB, 12415 shop, rNt, oldC, condT ); 12416 break; 12417 default: 12418 vassert(0); 12419 } 12420 } 12421 DIP("%s%s%s r%u, r%u, %s\n", 12422 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf ); 12423 goto decode_success; 12424 } 12425 12426 /* --------- ??? --------- */ 12427 default: 12428 break; 12429 } 12430 } /* if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) */ 12431 12432 /* --------------------- Load/store (ubyte & word) -------- */ 12433 // LDR STR LDRB STRB 12434 /* 31 27 23 19 15 11 6 4 3 # highest bit 12435 28 24 20 16 12 12436 A5-20 1 | 16 cond 0101 UB0L Rn Rd imm12 12437 A5-22 1 | 32 cond 0111 UBOL Rn Rd imm5 sh2 0 Rm 12438 A5-24 2 | 16 cond 0101 UB1L Rn Rd imm12 12439 A5-26 2 | 32 cond 0111 UB1L Rn Rd imm5 sh2 0 Rm 12440 A5-28 3 | 16 cond 0100 UB0L Rn Rd imm12 12441 A5-32 3 | 32 cond 0110 UB0L Rn Rd imm5 sh2 0 Rm 12442 */ 12443 /* case coding: 12444 1 at-ea (access at ea) 12445 2 at-ea-then-upd (access at ea, then Rn = ea) 12446 3 at-Rn-then-upd (access at Rn, then Rn = ea) 12447 ea coding 12448 16 Rn +/- imm12 12449 32 Rn +/- Rm sh2 imm5 12450 */ 12451 /* Quickly skip over all of this for hopefully most instructions */ 12452 if ((INSN(27,24) & BITS4(1,1,0,0)) != BITS4(0,1,0,0)) 12453 goto after_load_store_ubyte_or_word; 12454 12455 summary = 0; 12456 12457 /**/ if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 0) { 12458 summary = 1 | 16; 12459 } 12460 else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 0 12461 && INSN(4,4) == 0) { 12462 summary = 1 | 32; 12463 } 12464 else if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 1) { 12465 summary = 2 | 16; 12466 } 12467 else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 1 12468 && INSN(4,4) == 0) { 12469 summary = 2 | 32; 12470 } 12471 else if (INSN(27,24) == BITS4(0,1,0,0) && INSN(21,21) == 0) { 12472 summary = 3 | 16; 12473 } 12474 else if (INSN(27,24) == BITS4(0,1,1,0) && INSN(21,21) == 0 12475 && INSN(4,4) == 0) { 12476 summary = 3 | 32; 12477 } 12478 else goto after_load_store_ubyte_or_word; 12479 12480 { UInt rN = (insn >> 16) & 0xF; /* 19:16 */ 12481 UInt rD = (insn >> 12) & 0xF; /* 15:12 */ 12482 UInt rM = (insn >> 0) & 0xF; /* 3:0 */ 12483 UInt bU = (insn >> 23) & 1; /* 23 */ 12484 UInt bB = (insn >> 22) & 1; /* 22 */ 12485 UInt bL = (insn >> 20) & 1; /* 20 */ 12486 UInt imm12 = (insn >> 0) & 0xFFF; /* 11:0 */ 12487 UInt imm5 = (insn >> 7) & 0x1F; /* 11:7 */ 12488 UInt sh2 = (insn >> 5) & 3; /* 6:5 */ 12489 12490 /* Skip some invalid cases, which would lead to two competing 12491 updates to the same register, or which are otherwise 12492 disallowed by the spec. */ 12493 switch (summary) { 12494 case 1 | 16: 12495 break; 12496 case 1 | 32: 12497 if (rM == 15) goto after_load_store_ubyte_or_word; 12498 break; 12499 case 2 | 16: case 3 | 16: 12500 if (rN == 15) goto after_load_store_ubyte_or_word; 12501 if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word; 12502 break; 12503 case 2 | 32: case 3 | 32: 12504 if (rM == 15) goto after_load_store_ubyte_or_word; 12505 if (rN == 15) goto after_load_store_ubyte_or_word; 12506 if (rN == rM) goto after_load_store_ubyte_or_word; 12507 if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word; 12508 break; 12509 default: 12510 vassert(0); 12511 } 12512 12513 /* Now, we can't do a conditional load or store, since that very 12514 likely will generate an exception. So we have to take a side 12515 exit at this point if the condition is false. */ 12516 if (condT != IRTemp_INVALID) { 12517 mk_skip_over_A32_if_cond_is_false( condT ); 12518 condT = IRTemp_INVALID; 12519 } 12520 /* Ok, now we're unconditional. Do the load or store. */ 12521 12522 /* compute the effective address. Bind it to a tmp since we 12523 may need to use it twice. */ 12524 IRExpr* eaE = NULL; 12525 switch (summary & 0xF0) { 12526 case 16: 12527 eaE = mk_EA_reg_plusminus_imm12( rN, bU, imm12, dis_buf ); 12528 break; 12529 case 32: 12530 eaE = mk_EA_reg_plusminus_shifted_reg( rN, bU, rM, sh2, imm5, 12531 dis_buf ); 12532 break; 12533 } 12534 vassert(eaE); 12535 IRTemp eaT = newTemp(Ity_I32); 12536 assign(eaT, eaE); 12537 12538 /* get the old Rn value */ 12539 IRTemp rnT = newTemp(Ity_I32); 12540 assign(rnT, getIRegA(rN)); 12541 12542 /* decide on the transfer address */ 12543 IRTemp taT = IRTemp_INVALID; 12544 switch (summary & 0x0F) { 12545 case 1: case 2: taT = eaT; break; 12546 case 3: taT = rnT; break; 12547 } 12548 vassert(taT != IRTemp_INVALID); 12549 12550 if (bL == 0) { 12551 /* Store. If necessary, update the base register before the 12552 store itself, so that the common idiom of "str rX, [sp, 12553 #-4]!" (store rX at sp-4, then do new sp = sp-4, a.k.a "push 12554 rX") doesn't cause Memcheck to complain that the access is 12555 below the stack pointer. Also, not updating sp before the 12556 store confuses Valgrind's dynamic stack-extending logic. So 12557 do it before the store. Hence we need to snarf the store 12558 data before doing the basereg update. */ 12559 12560 /* get hold of the data to be stored */ 12561 IRTemp rDt = newTemp(Ity_I32); 12562 assign(rDt, getIRegA(rD)); 12563 12564 /* Update Rn if necessary. */ 12565 switch (summary & 0x0F) { 12566 case 2: case 3: 12567 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring ); 12568 break; 12569 } 12570 12571 /* generate the transfer */ 12572 if (bB == 0) { // word store 12573 storeLE( mkexpr(taT), mkexpr(rDt) ); 12574 } else { // byte store 12575 vassert(bB == 1); 12576 storeLE( mkexpr(taT), unop(Iop_32to8, mkexpr(rDt)) ); 12577 } 12578 12579 } else { 12580 /* Load */ 12581 vassert(bL == 1); 12582 12583 /* generate the transfer */ 12584 if (bB == 0) { // word load 12585 putIRegA( rD, loadLE(Ity_I32, mkexpr(taT)), 12586 IRTemp_INVALID, Ijk_Boring ); 12587 } else { // byte load 12588 vassert(bB == 1); 12589 putIRegA( rD, unop(Iop_8Uto32, loadLE(Ity_I8, mkexpr(taT))), 12590 IRTemp_INVALID, Ijk_Boring ); 12591 } 12592 12593 /* Update Rn if necessary. */ 12594 switch (summary & 0x0F) { 12595 case 2: case 3: 12596 // should be assured by logic above: 12597 if (bL == 1) 12598 vassert(rD != rN); /* since we just wrote rD */ 12599 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring ); 12600 break; 12601 } 12602 } 12603 12604 switch (summary & 0x0F) { 12605 case 1: DIP("%sr%s%s r%u, %s\n", 12606 bL == 0 ? "st" : "ld", 12607 bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf); 12608 break; 12609 case 2: DIP("%sr%s%s r%u, %s! (at-EA-then-Rn=EA)\n", 12610 bL == 0 ? "st" : "ld", 12611 bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf); 12612 break; 12613 case 3: DIP("%sr%s%s r%u, %s! (at-Rn-then-Rn=EA)\n", 12614 bL == 0 ? "st" : "ld", 12615 bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf); 12616 break; 12617 default: vassert(0); 12618 } 12619 12620 /* XXX deal with alignment constraints */ 12621 12622 goto decode_success; 12623 12624 /* Complications: 12625 12626 For all loads: if the Amode specifies base register 12627 writeback, and the same register is specified for Rd and Rn, 12628 the results are UNPREDICTABLE. 12629 12630 For all loads and stores: if R15 is written, branch to 12631 that address afterwards. 12632 12633 STRB: straightforward 12634 LDRB: loaded data is zero extended 12635 STR: lowest 2 bits of address are ignored 12636 LDR: if the lowest 2 bits of the address are nonzero 12637 then the loaded value is rotated right by 8 * the lowest 2 bits 12638 */ 12639 } 12640 12641 after_load_store_ubyte_or_word: 12642 12643 /* --------------------- Load/store (sbyte & hword) -------- */ 12644 // LDRH LDRSH STRH LDRSB 12645 /* 31 27 23 19 15 11 7 3 # highest bit 12646 28 24 20 16 12 8 4 0 12647 A5-36 1 | 16 cond 0001 U10L Rn Rd im4h 1SH1 im4l 12648 A5-38 1 | 32 cond 0001 U00L Rn Rd 0000 1SH1 Rm 12649 A5-40 2 | 16 cond 0001 U11L Rn Rd im4h 1SH1 im4l 12650 A5-42 2 | 32 cond 0001 U01L Rn Rd 0000 1SH1 Rm 12651 A5-44 3 | 16 cond 0000 U10L Rn Rd im4h 1SH1 im4l 12652 A5-46 3 | 32 cond 0000 U00L Rn Rd 0000 1SH1 Rm 12653 */ 12654 /* case coding: 12655 1 at-ea (access at ea) 12656 2 at-ea-then-upd (access at ea, then Rn = ea) 12657 3 at-Rn-then-upd (access at Rn, then Rn = ea) 12658 ea coding 12659 16 Rn +/- imm8 12660 32 Rn +/- Rm 12661 */ 12662 /* Quickly skip over all of this for hopefully most instructions */ 12663 if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0)) 12664 goto after_load_store_sbyte_or_hword; 12665 12666 /* Check the "1SH1" thing. */ 12667 if ((INSN(7,4) & BITS4(1,0,0,1)) != BITS4(1,0,0,1)) 12668 goto after_load_store_sbyte_or_hword; 12669 12670 summary = 0; 12671 12672 /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,0)) { 12673 summary = 1 | 16; 12674 } 12675 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,0)) { 12676 summary = 1 | 32; 12677 } 12678 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,1)) { 12679 summary = 2 | 16; 12680 } 12681 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,1)) { 12682 summary = 2 | 32; 12683 } 12684 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(1,0)) { 12685 summary = 3 | 16; 12686 } 12687 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(0,0)) { 12688 summary = 3 | 32; 12689 } 12690 else goto after_load_store_sbyte_or_hword; 12691 12692 { UInt rN = (insn >> 16) & 0xF; /* 19:16 */ 12693 UInt rD = (insn >> 12) & 0xF; /* 15:12 */ 12694 UInt rM = (insn >> 0) & 0xF; /* 3:0 */ 12695 UInt bU = (insn >> 23) & 1; /* 23 U=1 offset+, U=0 offset- */ 12696 UInt bL = (insn >> 20) & 1; /* 20 L=1 load, L=0 store */ 12697 UInt bH = (insn >> 5) & 1; /* H=1 halfword, H=0 byte */ 12698 UInt bS = (insn >> 6) & 1; /* S=1 signed, S=0 unsigned */ 12699 UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */ 12700 12701 /* Skip combinations that are either meaningless or already 12702 handled by main word-or-unsigned-byte load-store 12703 instructions. */ 12704 if (bS == 0 && bH == 0) /* "unsigned byte" */ 12705 goto after_load_store_sbyte_or_hword; 12706 if (bS == 1 && bL == 0) /* "signed store" */ 12707 goto after_load_store_sbyte_or_hword; 12708 12709 /* Require 11:8 == 0 for Rn +/- Rm cases */ 12710 if ((summary & 32) != 0 && (imm8 & 0xF0) != 0) 12711 goto after_load_store_sbyte_or_hword; 12712 12713 /* Skip some invalid cases, which would lead to two competing 12714 updates to the same register, or which are otherwise 12715 disallowed by the spec. */ 12716 switch (summary) { 12717 case 1 | 16: 12718 break; 12719 case 1 | 32: 12720 if (rM == 15) goto after_load_store_sbyte_or_hword; 12721 break; 12722 case 2 | 16: case 3 | 16: 12723 if (rN == 15) goto after_load_store_sbyte_or_hword; 12724 if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword; 12725 break; 12726 case 2 | 32: case 3 | 32: 12727 if (rM == 15) goto after_load_store_sbyte_or_hword; 12728 if (rN == 15) goto after_load_store_sbyte_or_hword; 12729 if (rN == rM) goto after_load_store_sbyte_or_hword; 12730 if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword; 12731 break; 12732 default: 12733 vassert(0); 12734 } 12735 12736 /* Now, we can't do a conditional load or store, since that very 12737 likely will generate an exception. So we have to take a side 12738 exit at this point if the condition is false. */ 12739 if (condT != IRTemp_INVALID) { 12740 mk_skip_over_A32_if_cond_is_false( condT ); 12741 condT = IRTemp_INVALID; 12742 } 12743 /* Ok, now we're unconditional. Do the load or store. */ 12744 12745 /* compute the effective address. Bind it to a tmp since we 12746 may need to use it twice. */ 12747 IRExpr* eaE = NULL; 12748 switch (summary & 0xF0) { 12749 case 16: 12750 eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf ); 12751 break; 12752 case 32: 12753 eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf ); 12754 break; 12755 } 12756 vassert(eaE); 12757 IRTemp eaT = newTemp(Ity_I32); 12758 assign(eaT, eaE); 12759 12760 /* get the old Rn value */ 12761 IRTemp rnT = newTemp(Ity_I32); 12762 assign(rnT, getIRegA(rN)); 12763 12764 /* decide on the transfer address */ 12765 IRTemp taT = IRTemp_INVALID; 12766 switch (summary & 0x0F) { 12767 case 1: case 2: taT = eaT; break; 12768 case 3: taT = rnT; break; 12769 } 12770 vassert(taT != IRTemp_INVALID); 12771 12772 /* halfword store H 1 L 0 S 0 12773 uhalf load H 1 L 1 S 0 12774 shalf load H 1 L 1 S 1 12775 sbyte load H 0 L 1 S 1 12776 */ 12777 HChar* name = NULL; 12778 /* generate the transfer */ 12779 /**/ if (bH == 1 && bL == 0 && bS == 0) { // halfword store 12780 storeLE( mkexpr(taT), unop(Iop_32to16, getIRegA(rD)) ); 12781 name = "strh"; 12782 } 12783 else if (bH == 1 && bL == 1 && bS == 0) { // uhalf load 12784 putIRegA( rD, unop(Iop_16Uto32, loadLE(Ity_I16, mkexpr(taT))), 12785 IRTemp_INVALID, Ijk_Boring ); 12786 name = "ldrh"; 12787 } 12788 else if (bH == 1 && bL == 1 && bS == 1) { // shalf load 12789 putIRegA( rD, unop(Iop_16Sto32, loadLE(Ity_I16, mkexpr(taT))), 12790 IRTemp_INVALID, Ijk_Boring ); 12791 name = "ldrsh"; 12792 } 12793 else if (bH == 0 && bL == 1 && bS == 1) { // sbyte load 12794 putIRegA( rD, unop(Iop_8Sto32, loadLE(Ity_I8, mkexpr(taT))), 12795 IRTemp_INVALID, Ijk_Boring ); 12796 name = "ldrsb"; 12797 } 12798 else 12799 vassert(0); // should be assured by logic above 12800 12801 /* Update Rn if necessary. */ 12802 switch (summary & 0x0F) { 12803 case 2: case 3: 12804 // should be assured by logic above: 12805 if (bL == 1) 12806 vassert(rD != rN); /* since we just wrote rD */ 12807 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring ); 12808 break; 12809 } 12810 12811 switch (summary & 0x0F) { 12812 case 1: DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf); 12813 break; 12814 case 2: DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n", 12815 name, nCC(INSN_COND), rD, dis_buf); 12816 break; 12817 case 3: DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n", 12818 name, nCC(INSN_COND), rD, dis_buf); 12819 break; 12820 default: vassert(0); 12821 } 12822 12823 /* XXX deal with alignment constraints */ 12824 12825 goto decode_success; 12826 12827 /* Complications: 12828 12829 For all loads: if the Amode specifies base register 12830 writeback, and the same register is specified for Rd and Rn, 12831 the results are UNPREDICTABLE. 12832 12833 For all loads and stores: if R15 is written, branch to 12834 that address afterwards. 12835 12836 Misaligned halfword stores => Unpredictable 12837 Misaligned halfword loads => Unpredictable 12838 */ 12839 } 12840 12841 after_load_store_sbyte_or_hword: 12842 12843 /* --------------------- Load/store multiple -------------- */ 12844 // LD/STMIA LD/STMIB LD/STMDA LD/STMDB 12845 // Remarkably complex and difficult to get right 12846 // match 27:20 as 100XX0WL 12847 if (BITS8(1,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,1,0,0))) { 12848 // A5-50 LD/STMIA cond 1000 10WL Rn RegList 12849 // A5-51 LD/STMIB cond 1001 10WL Rn RegList 12850 // A5-53 LD/STMDA cond 1000 00WL Rn RegList 12851 // A5-53 LD/STMDB cond 1001 00WL Rn RegList 12852 // 28 24 20 16 0 12853 12854 UInt bINC = (insn >> 23) & 1; 12855 UInt bBEFORE = (insn >> 24) & 1; 12856 12857 UInt bL = (insn >> 20) & 1; /* load=1, store=0 */ 12858 UInt bW = (insn >> 21) & 1; /* Rn wback=1, no wback=0 */ 12859 UInt rN = (insn >> 16) & 0xF; 12860 UInt regList = insn & 0xFFFF; 12861 /* Skip some invalid cases, which would lead to two competing 12862 updates to the same register, or which are otherwise 12863 disallowed by the spec. Note the test above has required 12864 that S == 0, since that looks like a kernel-mode only thing. 12865 Done by forcing the real pattern, viz 100XXSWL to actually be 12866 100XX0WL. */ 12867 if (rN == 15) goto after_load_store_multiple; 12868 // reglist can't be empty 12869 if (regList == 0) goto after_load_store_multiple; 12870 // if requested to writeback Rn, and this is a load instruction, 12871 // then Rn can't appear in RegList, since we'd have two competing 12872 // new values for Rn. We do however accept this case for store 12873 // instructions. 12874 if (bW == 1 && bL == 1 && ((1 << rN) & regList) > 0) 12875 goto after_load_store_multiple; 12876 12877 /* Now, we can't do a conditional load or store, since that very 12878 likely will generate an exception. So we have to take a side 12879 exit at this point if the condition is false. */ 12880 if (condT != IRTemp_INVALID) { 12881 mk_skip_over_A32_if_cond_is_false( condT ); 12882 condT = IRTemp_INVALID; 12883 } 12884 12885 /* Ok, now we're unconditional. Generate the IR. */ 12886 mk_ldm_stm( True/*arm*/, rN, bINC, bBEFORE, bW, bL, regList ); 12887 12888 DIP("%sm%c%c%s r%u%s, {0x%04x}\n", 12889 bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a', 12890 nCC(INSN_COND), 12891 rN, bW ? "!" : "", regList); 12892 12893 goto decode_success; 12894 } 12895 12896 after_load_store_multiple: 12897 12898 /* --------------------- Control flow --------------------- */ 12899 // B, BL (Branch, or Branch-and-Link, to immediate offset) 12900 // 12901 if (BITS8(1,0,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))) { 12902 UInt link = (insn >> 24) & 1; 12903 UInt uimm24 = insn & ((1<<24)-1); 12904 Int simm24 = (Int)uimm24; 12905 UInt dst = guest_R15_curr_instr_notENC + 8 12906 + (((simm24 << 8) >> 8) << 2); 12907 IRJumpKind jk = link ? Ijk_Call : Ijk_Boring; 12908 if (link) { 12909 putIRegA(14, mkU32(guest_R15_curr_instr_notENC + 4), 12910 condT, Ijk_Boring); 12911 } 12912 if (condT == IRTemp_INVALID) { 12913 /* unconditional transfer to 'dst'. See if we can simply 12914 continue tracing at the destination. */ 12915 if (resteerOkFn( callback_opaque, (Addr64)dst )) { 12916 /* yes */ 12917 dres.whatNext = Dis_ResteerU; 12918 dres.continueAt = (Addr64)dst; 12919 } else { 12920 /* no; terminate the SB at this point. */ 12921 irsb->next = mkU32(dst); 12922 irsb->jumpkind = jk; 12923 dres.whatNext = Dis_StopHere; 12924 } 12925 DIP("b%s 0x%x\n", link ? "l" : "", dst); 12926 } else { 12927 /* conditional transfer to 'dst' */ 12928 HChar* comment = ""; 12929 12930 /* First see if we can do some speculative chasing into one 12931 arm or the other. Be conservative and only chase if 12932 !link, that is, this is a normal conditional branch to a 12933 known destination. */ 12934 if (!link 12935 && resteerCisOk 12936 && vex_control.guest_chase_cond 12937 && dst < guest_R15_curr_instr_notENC 12938 && resteerOkFn( callback_opaque, (Addr64)(Addr32)dst) ) { 12939 /* Speculation: assume this backward branch is taken. So 12940 we need to emit a side-exit to the insn following this 12941 one, on the negation of the condition, and continue at 12942 the branch target address (dst). */ 12943 stmt( IRStmt_Exit( unop(Iop_Not1, 12944 unop(Iop_32to1, mkexpr(condT))), 12945 Ijk_Boring, 12946 IRConst_U32(guest_R15_curr_instr_notENC+4) )); 12947 dres.whatNext = Dis_ResteerC; 12948 dres.continueAt = (Addr64)(Addr32)dst; 12949 comment = "(assumed taken)"; 12950 } 12951 else 12952 if (!link 12953 && resteerCisOk 12954 && vex_control.guest_chase_cond 12955 && dst >= guest_R15_curr_instr_notENC 12956 && resteerOkFn( callback_opaque, 12957 (Addr64)(Addr32) 12958 (guest_R15_curr_instr_notENC+4)) ) { 12959 /* Speculation: assume this forward branch is not taken. 12960 So we need to emit a side-exit to dst (the dest) and 12961 continue disassembling at the insn immediately 12962 following this one. */ 12963 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)), 12964 Ijk_Boring, 12965 IRConst_U32(dst) )); 12966 dres.whatNext = Dis_ResteerC; 12967 dres.continueAt = (Addr64)(Addr32) 12968 (guest_R15_curr_instr_notENC+4); 12969 comment = "(assumed not taken)"; 12970 } 12971 else { 12972 /* Conservative default translation - end the block at 12973 this point. */ 12974 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)), 12975 jk, IRConst_U32(dst) )); 12976 irsb->next = mkU32(guest_R15_curr_instr_notENC + 4); 12977 irsb->jumpkind = jk; 12978 dres.whatNext = Dis_StopHere; 12979 } 12980 DIP("b%s%s 0x%x %s\n", link ? "l" : "", nCC(INSN_COND), 12981 dst, comment); 12982 } 12983 goto decode_success; 12984 } 12985 12986 // B, BL (Branch, or Branch-and-Link, to a register) 12987 // NB: interworking branch 12988 if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0) 12989 && INSN(19,12) == BITS8(1,1,1,1,1,1,1,1) 12990 && (INSN(11,4) == BITS8(1,1,1,1,0,0,1,1) 12991 || INSN(11,4) == BITS8(1,1,1,1,0,0,0,1))) { 12992 IRExpr* dst; 12993 UInt link = (INSN(11,4) >> 1) & 1; 12994 UInt rM = INSN(3,0); 12995 // we don't decode the case (link && rM == 15), as that's 12996 // Unpredictable. 12997 if (!(link && rM == 15)) { 12998 if (condT != IRTemp_INVALID) { 12999 mk_skip_over_A32_if_cond_is_false( condT ); 13000 } 13001 // rM contains an interworking address exactly as we require 13002 // (with continuation CPSR.T in bit 0), so we can use it 13003 // as-is, with no masking. 13004 dst = getIRegA(rM); 13005 if (link) { 13006 putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4), 13007 IRTemp_INVALID/*because AL*/, Ijk_Boring ); 13008 } 13009 irsb->next = dst; 13010 irsb->jumpkind = link ? Ijk_Call 13011 : (rM == 14 ? Ijk_Ret : Ijk_Boring); 13012 dres.whatNext = Dis_StopHere; 13013 if (condT == IRTemp_INVALID) { 13014 DIP("b%sx r%u\n", link ? "l" : "", rM); 13015 } else { 13016 DIP("b%sx%s r%u\n", link ? "l" : "", nCC(INSN_COND), rM); 13017 } 13018 goto decode_success; 13019 } 13020 /* else: (link && rM == 15): just fall through */ 13021 } 13022 13023 /* --- NB: ARM interworking branches are in NV space, hence 13024 are handled elsewhere by decode_NV_instruction. 13025 --- 13026 */ 13027 13028 /* --------------------- Clz --------------------- */ 13029 // CLZ 13030 if (INSN(27,20) == BITS8(0,0,0,1,0,1,1,0) 13031 && INSN(19,16) == BITS4(1,1,1,1) 13032 && INSN(11,4) == BITS8(1,1,1,1,0,0,0,1)) { 13033 UInt rD = INSN(15,12); 13034 UInt rM = INSN(3,0); 13035 IRTemp arg = newTemp(Ity_I32); 13036 IRTemp res = newTemp(Ity_I32); 13037 assign(arg, getIRegA(rM)); 13038 assign(res, IRExpr_Mux0X( 13039 unop(Iop_1Uto8,binop(Iop_CmpEQ32, mkexpr(arg), 13040 mkU32(0))), 13041 unop(Iop_Clz32, mkexpr(arg)), 13042 mkU32(32) 13043 )); 13044 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 13045 DIP("clz%s r%u, r%u\n", nCC(INSN_COND), rD, rM); 13046 goto decode_success; 13047 } 13048 13049 /* --------------------- Mul etc --------------------- */ 13050 // MUL 13051 if (BITS8(0,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0)) 13052 && INSN(15,12) == BITS4(0,0,0,0) 13053 && INSN(7,4) == BITS4(1,0,0,1)) { 13054 UInt bitS = (insn >> 20) & 1; /* 20:20 */ 13055 UInt rD = INSN(19,16); 13056 UInt rS = INSN(11,8); 13057 UInt rM = INSN(3,0); 13058 if (rD == 15 || rM == 15 || rS == 15) { 13059 /* Unpredictable; don't decode; fall through */ 13060 } else { 13061 IRTemp argL = newTemp(Ity_I32); 13062 IRTemp argR = newTemp(Ity_I32); 13063 IRTemp res = newTemp(Ity_I32); 13064 IRTemp oldC = IRTemp_INVALID; 13065 IRTemp oldV = IRTemp_INVALID; 13066 assign( argL, getIRegA(rM)); 13067 assign( argR, getIRegA(rS)); 13068 assign( res, binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) ); 13069 if (bitS) { 13070 oldC = newTemp(Ity_I32); 13071 assign(oldC, mk_armg_calculate_flag_c()); 13072 oldV = newTemp(Ity_I32); 13073 assign(oldV, mk_armg_calculate_flag_v()); 13074 } 13075 // now update guest state 13076 putIRegA( rD, mkexpr(res), condT, Ijk_Boring ); 13077 if (bitS) { 13078 IRTemp pair = newTemp(Ity_I32); 13079 assign( pair, binop(Iop_Or32, 13080 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)), 13081 mkexpr(oldV)) ); 13082 setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT ); 13083 } 13084 DIP("mul%c%s r%u, r%u, r%u\n", 13085 bitS ? 's' : ' ', nCC(INSN_COND), rD, rM, rS); 13086 goto decode_success; 13087 } 13088 /* fall through */ 13089 } 13090 13091 // MLA, MLS 13092 if (BITS8(0,0,0,0,0,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0)) 13093 && INSN(7,4) == BITS4(1,0,0,1)) { 13094 UInt bitS = (insn >> 20) & 1; /* 20:20 */ 13095 UInt isMLS = (insn >> 22) & 1; /* 22:22 */ 13096 UInt rD = INSN(19,16); 13097 UInt rN = INSN(15,12); 13098 UInt rS = INSN(11,8); 13099 UInt rM = INSN(3,0); 13100 if (bitS == 1 && isMLS == 1) { 13101 /* This isn't allowed (MLS that sets flags). don't decode; 13102 fall through */ 13103 } 13104 else 13105 if (rD == 15 || rM == 15 || rS == 15 || rN == 15) { 13106 /* Unpredictable; don't decode; fall through */ 13107 } else { 13108 IRTemp argL = newTemp(Ity_I32); 13109 IRTemp argR = newTemp(Ity_I32); 13110 IRTemp argP = newTemp(Ity_I32); 13111 IRTemp res = newTemp(Ity_I32); 13112 IRTemp oldC = IRTemp_INVALID; 13113 IRTemp oldV = IRTemp_INVALID; 13114 assign( argL, getIRegA(rM)); 13115 assign( argR, getIRegA(rS)); 13116 assign( argP, getIRegA(rN)); 13117 assign( res, binop(isMLS ? Iop_Sub32 : Iop_Add32, 13118 mkexpr(argP), 13119 binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) )); 13120 if (bitS) { 13121 vassert(!isMLS); // guaranteed above 13122 oldC = newTemp(Ity_I32); 13123 assign(oldC, mk_armg_calculate_flag_c()); 13124 oldV = newTemp(Ity_I32); 13125 assign(oldV, mk_armg_calculate_flag_v()); 13126 } 13127 // now update guest state 13128 putIRegA( rD, mkexpr(res), condT, Ijk_Boring ); 13129 if (bitS) { 13130 IRTemp pair = newTemp(Ity_I32); 13131 assign( pair, binop(Iop_Or32, 13132 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)), 13133 mkexpr(oldV)) ); 13134 setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT ); 13135 } 13136 DIP("ml%c%c%s r%u, r%u, r%u, r%u\n", 13137 isMLS ? 's' : 'a', bitS ? 's' : ' ', 13138 nCC(INSN_COND), rD, rM, rS, rN); 13139 goto decode_success; 13140 } 13141 /* fall through */ 13142 } 13143 13144 // SMULL, UMULL 13145 if (BITS8(0,0,0,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0)) 13146 && INSN(7,4) == BITS4(1,0,0,1)) { 13147 UInt bitS = (insn >> 20) & 1; /* 20:20 */ 13148 UInt rDhi = INSN(19,16); 13149 UInt rDlo = INSN(15,12); 13150 UInt rS = INSN(11,8); 13151 UInt rM = INSN(3,0); 13152 UInt isS = (INSN(27,20) >> 2) & 1; /* 22:22 */ 13153 if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo) { 13154 /* Unpredictable; don't decode; fall through */ 13155 } else { 13156 IRTemp argL = newTemp(Ity_I32); 13157 IRTemp argR = newTemp(Ity_I32); 13158 IRTemp res = newTemp(Ity_I64); 13159 IRTemp resHi = newTemp(Ity_I32); 13160 IRTemp resLo = newTemp(Ity_I32); 13161 IRTemp oldC = IRTemp_INVALID; 13162 IRTemp oldV = IRTemp_INVALID; 13163 IROp mulOp = isS ? Iop_MullS32 : Iop_MullU32; 13164 assign( argL, getIRegA(rM)); 13165 assign( argR, getIRegA(rS)); 13166 assign( res, binop(mulOp, mkexpr(argL), mkexpr(argR)) ); 13167 assign( resHi, unop(Iop_64HIto32, mkexpr(res)) ); 13168 assign( resLo, unop(Iop_64to32, mkexpr(res)) ); 13169 if (bitS) { 13170 oldC = newTemp(Ity_I32); 13171 assign(oldC, mk_armg_calculate_flag_c()); 13172 oldV = newTemp(Ity_I32); 13173 assign(oldV, mk_armg_calculate_flag_v()); 13174 } 13175 // now update guest state 13176 putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring ); 13177 putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring ); 13178 if (bitS) { 13179 IRTemp pair = newTemp(Ity_I32); 13180 assign( pair, binop(Iop_Or32, 13181 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)), 13182 mkexpr(oldV)) ); 13183 setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT ); 13184 } 13185 DIP("%cmull%c%s r%u, r%u, r%u, r%u\n", 13186 isS ? 's' : 'u', bitS ? 's' : ' ', 13187 nCC(INSN_COND), rDlo, rDhi, rM, rS); 13188 goto decode_success; 13189 } 13190 /* fall through */ 13191 } 13192 13193 // SMLAL, UMLAL 13194 if (BITS8(0,0,0,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0)) 13195 && INSN(7,4) == BITS4(1,0,0,1)) { 13196 UInt bitS = (insn >> 20) & 1; /* 20:20 */ 13197 UInt rDhi = INSN(19,16); 13198 UInt rDlo = INSN(15,12); 13199 UInt rS = INSN(11,8); 13200 UInt rM = INSN(3,0); 13201 UInt isS = (INSN(27,20) >> 2) & 1; /* 22:22 */ 13202 if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo) { 13203 /* Unpredictable; don't decode; fall through */ 13204 } else { 13205 IRTemp argL = newTemp(Ity_I32); 13206 IRTemp argR = newTemp(Ity_I32); 13207 IRTemp old = newTemp(Ity_I64); 13208 IRTemp res = newTemp(Ity_I64); 13209 IRTemp resHi = newTemp(Ity_I32); 13210 IRTemp resLo = newTemp(Ity_I32); 13211 IRTemp oldC = IRTemp_INVALID; 13212 IRTemp oldV = IRTemp_INVALID; 13213 IROp mulOp = isS ? Iop_MullS32 : Iop_MullU32; 13214 assign( argL, getIRegA(rM)); 13215 assign( argR, getIRegA(rS)); 13216 assign( old, binop(Iop_32HLto64, getIRegA(rDhi), getIRegA(rDlo)) ); 13217 assign( res, binop(Iop_Add64, 13218 mkexpr(old), 13219 binop(mulOp, mkexpr(argL), mkexpr(argR))) ); 13220 assign( resHi, unop(Iop_64HIto32, mkexpr(res)) ); 13221 assign( resLo, unop(Iop_64to32, mkexpr(res)) ); 13222 if (bitS) { 13223 oldC = newTemp(Ity_I32); 13224 assign(oldC, mk_armg_calculate_flag_c()); 13225 oldV = newTemp(Ity_I32); 13226 assign(oldV, mk_armg_calculate_flag_v()); 13227 } 13228 // now update guest state 13229 putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring ); 13230 putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring ); 13231 if (bitS) { 13232 IRTemp pair = newTemp(Ity_I32); 13233 assign( pair, binop(Iop_Or32, 13234 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)), 13235 mkexpr(oldV)) ); 13236 setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT ); 13237 } 13238 DIP("%cmlal%c%s r%u, r%u, r%u, r%u\n", 13239 isS ? 's' : 'u', bitS ? 's' : ' ', nCC(INSN_COND), 13240 rDlo, rDhi, rM, rS); 13241 goto decode_success; 13242 } 13243 /* fall through */ 13244 } 13245 13246 /* --------------------- Msr etc --------------------- */ 13247 13248 // MSR apsr, #imm 13249 if (INSN(27,20) == BITS8(0,0,1,1,0,0,1,0) 13250 && INSN(17,12) == BITS6(0,0,1,1,1,1)) { 13251 UInt write_ge = INSN(18,18); 13252 UInt write_nzcvq = INSN(19,19); 13253 if (write_nzcvq || write_ge) { 13254 UInt imm = (INSN(11,0) >> 0) & 0xFF; 13255 UInt rot = 2 * ((INSN(11,0) >> 8) & 0xF); 13256 IRTemp immT = newTemp(Ity_I32); 13257 vassert(rot <= 30); 13258 imm = ROR32(imm, rot); 13259 assign(immT, mkU32(imm)); 13260 desynthesise_APSR( write_nzcvq, write_ge, immT, condT ); 13261 DIP("msr%s cpsr%s%sf, #0x%08x\n", nCC(INSN_COND), 13262 write_nzcvq ? "f" : "", write_ge ? "g" : "", imm); 13263 goto decode_success; 13264 } 13265 /* fall through */ 13266 } 13267 13268 // MSR apsr, reg 13269 if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0) 13270 && INSN(17,12) == BITS6(0,0,1,1,1,1) 13271 && INSN(11,4) == BITS8(0,0,0,0,0,0,0,0)) { 13272 UInt rN = INSN(3,0); 13273 UInt write_ge = INSN(18,18); 13274 UInt write_nzcvq = INSN(19,19); 13275 if (rN != 15 && (write_nzcvq || write_ge)) { 13276 IRTemp rNt = newTemp(Ity_I32); 13277 assign(rNt, getIRegA(rN)); 13278 desynthesise_APSR( write_nzcvq, write_ge, rNt, condT ); 13279 DIP("msr%s cpsr_%s%s, r%u\n", nCC(INSN_COND), 13280 write_nzcvq ? "f" : "", write_ge ? "g" : "", rN); 13281 goto decode_success; 13282 } 13283 /* fall through */ 13284 } 13285 13286 // MRS rD, cpsr 13287 if ((insn & 0x0FFF0FFF) == 0x010F0000) { 13288 UInt rD = INSN(15,12); 13289 if (rD != 15) { 13290 IRTemp apsr = synthesise_APSR(); 13291 putIRegA( rD, mkexpr(apsr), condT, Ijk_Boring ); 13292 DIP("mrs%s r%u, cpsr\n", nCC(INSN_COND), rD); 13293 goto decode_success; 13294 } 13295 /* fall through */ 13296 } 13297 13298 /* --------------------- Svc --------------------- */ 13299 if (BITS8(1,1,1,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))) { 13300 UInt imm24 = (insn >> 0) & 0xFFFFFF; 13301 if (imm24 == 0) { 13302 /* A syscall. We can't do this conditionally, hence: */ 13303 if (condT != IRTemp_INVALID) { 13304 mk_skip_over_A32_if_cond_is_false( condT ); 13305 } 13306 // AL after here 13307 irsb->next = mkU32( guest_R15_curr_instr_notENC + 4 ); 13308 irsb->jumpkind = Ijk_Sys_syscall; 13309 dres.whatNext = Dis_StopHere; 13310 DIP("svc%s #0x%08x\n", nCC(INSN_COND), imm24); 13311 goto decode_success; 13312 } 13313 /* fall through */ 13314 } 13315 13316 /* ------------------------ swp ------------------------ */ 13317 13318 // SWP, SWPB 13319 if (BITS8(0,0,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 13320 && BITS4(0,0,0,0) == INSN(11,8) 13321 && BITS4(1,0,0,1) == INSN(7,4)) { 13322 UInt rN = INSN(19,16); 13323 UInt rD = INSN(15,12); 13324 UInt rM = INSN(3,0); 13325 IRTemp tRn = newTemp(Ity_I32); 13326 IRTemp tNew = newTemp(Ity_I32); 13327 IRTemp tOld = IRTemp_INVALID; 13328 IRTemp tSC1 = newTemp(Ity_I1); 13329 UInt isB = (insn >> 22) & 1; 13330 13331 if (rD == 15 || rN == 15 || rM == 15 || rN == rM || rN == rD) { 13332 /* undecodable; fall through */ 13333 } else { 13334 /* make unconditional */ 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. Generate a LL-SC loop. */ 13340 assign(tRn, getIRegA(rN)); 13341 assign(tNew, getIRegA(rM)); 13342 if (isB) { 13343 /* swpb */ 13344 tOld = newTemp(Ity_I8); 13345 stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn), 13346 NULL/*=>isLL*/) ); 13347 stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn), 13348 unop(Iop_32to8, mkexpr(tNew))) ); 13349 } else { 13350 /* swp */ 13351 tOld = newTemp(Ity_I32); 13352 stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn), 13353 NULL/*=>isLL*/) ); 13354 stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn), 13355 mkexpr(tNew)) ); 13356 } 13357 stmt( IRStmt_Exit(unop(Iop_Not1, mkexpr(tSC1)), 13358 /*Ijk_NoRedir*/Ijk_Boring, 13359 IRConst_U32(guest_R15_curr_instr_notENC)) ); 13360 putIRegA(rD, isB ? unop(Iop_8Uto32, mkexpr(tOld)) : mkexpr(tOld), 13361 IRTemp_INVALID, Ijk_Boring); 13362 DIP("swp%s%s r%u, r%u, [r%u]\n", 13363 isB ? "b" : "", nCC(INSN_COND), rD, rM, rN); 13364 goto decode_success; 13365 } 13366 /* fall through */ 13367 } 13368 13369 /* ----------------------------------------------------------- */ 13370 /* -- ARMv6 instructions -- */ 13371 /* ----------------------------------------------------------- */ 13372 13373 /* --------------------- ldrex, strex --------------------- */ 13374 13375 // LDREX 13376 if (0x01900F9F == (insn & 0x0FF00FFF)) { 13377 UInt rT = INSN(15,12); 13378 UInt rN = INSN(19,16); 13379 if (rT == 15 || rN == 15) { 13380 /* undecodable; fall through */ 13381 } else { 13382 IRTemp res; 13383 /* make unconditional */ 13384 if (condT != IRTemp_INVALID) { 13385 mk_skip_over_A32_if_cond_is_false( condT ); 13386 condT = IRTemp_INVALID; 13387 } 13388 /* Ok, now we're unconditional. Do the load. */ 13389 res = newTemp(Ity_I32); 13390 stmt( IRStmt_LLSC(Iend_LE, res, getIRegA(rN), 13391 NULL/*this is a load*/) ); 13392 putIRegA(rT, mkexpr(res), IRTemp_INVALID, Ijk_Boring); 13393 DIP("ldrex%s r%u, [r%u]\n", nCC(INSN_COND), rT, rN); 13394 goto decode_success; 13395 } 13396 /* fall through */ 13397 } 13398 13399 // STREX 13400 if (0x01800F90 == (insn & 0x0FF00FF0)) { 13401 UInt rT = INSN(3,0); 13402 UInt rN = INSN(19,16); 13403 UInt rD = INSN(15,12); 13404 if (rT == 15 || rN == 15 || rD == 15 13405 || rD == rT || rD == rN) { 13406 /* undecodable; fall through */ 13407 } else { 13408 IRTemp resSC1, resSC32; 13409 13410 /* make unconditional */ 13411 if (condT != IRTemp_INVALID) { 13412 mk_skip_over_A32_if_cond_is_false( condT ); 13413 condT = IRTemp_INVALID; 13414 } 13415 13416 /* Ok, now we're unconditional. Do the store. */ 13417 resSC1 = newTemp(Ity_I1); 13418 stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegA(rN), getIRegA(rT)) ); 13419 13420 /* Set rD to 1 on failure, 0 on success. Currently we have 13421 resSC1 == 0 on failure, 1 on success. */ 13422 resSC32 = newTemp(Ity_I32); 13423 assign(resSC32, 13424 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1)))); 13425 13426 putIRegA(rD, mkexpr(resSC32), 13427 IRTemp_INVALID, Ijk_Boring); 13428 DIP("strex%s r%u, r%u, [r%u]\n", nCC(INSN_COND), rD, rT, rN); 13429 goto decode_success; 13430 } 13431 /* fall through */ 13432 } 13433 13434 /* --------------------- movw, movt --------------------- */ 13435 if (0x03000000 == (insn & 0x0FF00000) 13436 || 0x03400000 == (insn & 0x0FF00000)) /* pray for CSE */ { 13437 UInt rD = INSN(15,12); 13438 UInt imm16 = (insn & 0xFFF) | ((insn >> 4) & 0x0000F000); 13439 UInt isT = (insn >> 22) & 1; 13440 if (rD == 15) { 13441 /* forget it */ 13442 } else { 13443 if (isT) { 13444 putIRegA(rD, 13445 binop(Iop_Or32, 13446 binop(Iop_And32, getIRegA(rD), mkU32(0xFFFF)), 13447 mkU32(imm16 << 16)), 13448 condT, Ijk_Boring); 13449 DIP("movt%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16); 13450 goto decode_success; 13451 } else { 13452 putIRegA(rD, mkU32(imm16), condT, Ijk_Boring); 13453 DIP("movw%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16); 13454 goto decode_success; 13455 } 13456 } 13457 /* fall through */ 13458 } 13459 13460 /* ----------- uxtb, sxtb, uxth, sxth, uxtb16, sxtb16 ----------- */ 13461 /* FIXME: this is an exact duplicate of the Thumb version. They 13462 should be commoned up. */ 13463 if (BITS8(0,1,1,0,1, 0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,0)) 13464 && BITS4(1,1,1,1) == INSN(19,16) 13465 && BITS4(0,1,1,1) == INSN(7,4) 13466 && BITS4(0,0, 0,0) == (INSN(11,8) & BITS4(0,0,1,1))) { 13467 UInt subopc = INSN(27,20) & BITS8(0,0,0,0,0, 1,1,1); 13468 if (subopc != BITS4(0,0,0,1) && subopc != BITS4(0,1,0,1)) { 13469 Int rot = (INSN(11,8) >> 2) & 3; 13470 UInt rM = INSN(3,0); 13471 UInt rD = INSN(15,12); 13472 IRTemp srcT = newTemp(Ity_I32); 13473 IRTemp rotT = newTemp(Ity_I32); 13474 IRTemp dstT = newTemp(Ity_I32); 13475 HChar* nm = "???"; 13476 assign(srcT, getIRegA(rM)); 13477 assign(rotT, genROR32(srcT, 8 * rot)); /* 0, 8, 16 or 24 only */ 13478 switch (subopc) { 13479 case BITS4(0,1,1,0): // UXTB 13480 assign(dstT, unop(Iop_8Uto32, unop(Iop_32to8, mkexpr(rotT)))); 13481 nm = "uxtb"; 13482 break; 13483 case BITS4(0,0,1,0): // SXTB 13484 assign(dstT, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rotT)))); 13485 nm = "sxtb"; 13486 break; 13487 case BITS4(0,1,1,1): // UXTH 13488 assign(dstT, unop(Iop_16Uto32, unop(Iop_32to16, mkexpr(rotT)))); 13489 nm = "uxth"; 13490 break; 13491 case BITS4(0,0,1,1): // SXTH 13492 assign(dstT, unop(Iop_16Sto32, unop(Iop_32to16, mkexpr(rotT)))); 13493 nm = "sxth"; 13494 break; 13495 case BITS4(0,1,0,0): // UXTB16 13496 assign(dstT, binop(Iop_And32, mkexpr(rotT), mkU32(0x00FF00FF))); 13497 nm = "uxtb16"; 13498 break; 13499 case BITS4(0,0,0,0): { // SXTB16 13500 IRTemp lo32 = newTemp(Ity_I32); 13501 IRTemp hi32 = newTemp(Ity_I32); 13502 assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF))); 13503 assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16))); 13504 assign( 13505 dstT, 13506 binop(Iop_Or32, 13507 binop(Iop_And32, 13508 unop(Iop_8Sto32, 13509 unop(Iop_32to8, mkexpr(lo32))), 13510 mkU32(0xFFFF)), 13511 binop(Iop_Shl32, 13512 unop(Iop_8Sto32, 13513 unop(Iop_32to8, mkexpr(hi32))), 13514 mkU8(16)) 13515 )); 13516 nm = "sxtb16"; 13517 break; 13518 } 13519 default: 13520 vassert(0); // guarded by "if" above 13521 } 13522 putIRegA(rD, mkexpr(dstT), condT, Ijk_Boring); 13523 DIP("%s%s r%u, r%u, ROR #%u\n", nm, nCC(INSN_COND), rD, rM, rot); 13524 goto decode_success; 13525 } 13526 /* fall through */ 13527 } 13528 13529 /* ------------------- bfi, bfc ------------------- */ 13530 if (BITS8(0,1,1,1,1,1,0, 0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0)) 13531 && BITS4(0, 0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) { 13532 UInt rD = INSN(15,12); 13533 UInt rN = INSN(3,0); 13534 UInt msb = (insn >> 16) & 0x1F; /* 20:16 */ 13535 UInt lsb = (insn >> 7) & 0x1F; /* 11:7 */ 13536 if (rD == 15 || msb < lsb) { 13537 /* undecodable; fall through */ 13538 } else { 13539 IRTemp src = newTemp(Ity_I32); 13540 IRTemp olddst = newTemp(Ity_I32); 13541 IRTemp newdst = newTemp(Ity_I32); 13542 UInt mask = 1 << (msb - lsb); 13543 mask = (mask - 1) + mask; 13544 vassert(mask != 0); // guaranteed by "msb < lsb" check above 13545 mask <<= lsb; 13546 13547 assign(src, rN == 15 ? mkU32(0) : getIRegA(rN)); 13548 assign(olddst, getIRegA(rD)); 13549 assign(newdst, 13550 binop(Iop_Or32, 13551 binop(Iop_And32, 13552 binop(Iop_Shl32, mkexpr(src), mkU8(lsb)), 13553 mkU32(mask)), 13554 binop(Iop_And32, 13555 mkexpr(olddst), 13556 mkU32(~mask))) 13557 ); 13558 13559 putIRegA(rD, mkexpr(newdst), condT, Ijk_Boring); 13560 13561 if (rN == 15) { 13562 DIP("bfc%s r%u, #%u, #%u\n", 13563 nCC(INSN_COND), rD, lsb, msb-lsb+1); 13564 } else { 13565 DIP("bfi%s r%u, r%u, #%u, #%u\n", 13566 nCC(INSN_COND), rD, rN, lsb, msb-lsb+1); 13567 } 13568 goto decode_success; 13569 } 13570 /* fall through */ 13571 } 13572 13573 /* ------------------- {u,s}bfx ------------------- */ 13574 if (BITS8(0,1,1,1,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0)) 13575 && BITS4(0,1,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) { 13576 UInt rD = INSN(15,12); 13577 UInt rN = INSN(3,0); 13578 UInt wm1 = (insn >> 16) & 0x1F; /* 20:16 */ 13579 UInt lsb = (insn >> 7) & 0x1F; /* 11:7 */ 13580 UInt msb = lsb + wm1; 13581 UInt isU = (insn >> 22) & 1; /* 22:22 */ 13582 if (rD == 15 || rN == 15 || msb >= 32) { 13583 /* undecodable; fall through */ 13584 } else { 13585 IRTemp src = newTemp(Ity_I32); 13586 IRTemp tmp = newTemp(Ity_I32); 13587 IRTemp res = newTemp(Ity_I32); 13588 UInt mask = ((1 << wm1) - 1) + (1 << wm1); 13589 vassert(msb >= 0 && msb <= 31); 13590 vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive 13591 13592 assign(src, getIRegA(rN)); 13593 assign(tmp, binop(Iop_And32, 13594 binop(Iop_Shr32, mkexpr(src), mkU8(lsb)), 13595 mkU32(mask))); 13596 assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32, 13597 binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)), 13598 mkU8(31-wm1))); 13599 13600 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 13601 13602 DIP("%s%s r%u, r%u, #%u, #%u\n", 13603 isU ? "ubfx" : "sbfx", 13604 nCC(INSN_COND), rD, rN, lsb, wm1 + 1); 13605 goto decode_success; 13606 } 13607 /* fall through */ 13608 } 13609 13610 /* --------------------- Load/store doubleword ------------- */ 13611 // LDRD STRD 13612 /* 31 27 23 19 15 11 7 3 # highest bit 13613 28 24 20 16 12 8 4 0 13614 A5-36 1 | 16 cond 0001 U100 Rn Rd im4h 11S1 im4l 13615 A5-38 1 | 32 cond 0001 U000 Rn Rd 0000 11S1 Rm 13616 A5-40 2 | 16 cond 0001 U110 Rn Rd im4h 11S1 im4l 13617 A5-42 2 | 32 cond 0001 U010 Rn Rd 0000 11S1 Rm 13618 A5-44 3 | 16 cond 0000 U100 Rn Rd im4h 11S1 im4l 13619 A5-46 3 | 32 cond 0000 U000 Rn Rd 0000 11S1 Rm 13620 */ 13621 /* case coding: 13622 1 at-ea (access at ea) 13623 2 at-ea-then-upd (access at ea, then Rn = ea) 13624 3 at-Rn-then-upd (access at Rn, then Rn = ea) 13625 ea coding 13626 16 Rn +/- imm8 13627 32 Rn +/- Rm 13628 */ 13629 /* Quickly skip over all of this for hopefully most instructions */ 13630 if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0)) 13631 goto after_load_store_doubleword; 13632 13633 /* Check the "11S1" thing. */ 13634 if ((INSN(7,4) & BITS4(1,1,0,1)) != BITS4(1,1,0,1)) 13635 goto after_load_store_doubleword; 13636 13637 summary = 0; 13638 13639 /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,0,0)) { 13640 summary = 1 | 16; 13641 } 13642 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,0,0)) { 13643 summary = 1 | 32; 13644 } 13645 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,1,0)) { 13646 summary = 2 | 16; 13647 } 13648 else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,1,0)) { 13649 summary = 2 | 32; 13650 } 13651 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(1,0,0)) { 13652 summary = 3 | 16; 13653 } 13654 else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(0,0,0)) { 13655 summary = 3 | 32; 13656 } 13657 else goto after_load_store_doubleword; 13658 13659 { UInt rN = (insn >> 16) & 0xF; /* 19:16 */ 13660 UInt rD = (insn >> 12) & 0xF; /* 15:12 */ 13661 UInt rM = (insn >> 0) & 0xF; /* 3:0 */ 13662 UInt bU = (insn >> 23) & 1; /* 23 U=1 offset+, U=0 offset- */ 13663 UInt bS = (insn >> 5) & 1; /* S=1 store, S=0 load */ 13664 UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */ 13665 13666 /* Require rD to be an even numbered register */ 13667 if ((rD & 1) != 0) 13668 goto after_load_store_doubleword; 13669 13670 /* Require 11:8 == 0 for Rn +/- Rm cases */ 13671 if ((summary & 32) != 0 && (imm8 & 0xF0) != 0) 13672 goto after_load_store_doubleword; 13673 13674 /* Skip some invalid cases, which would lead to two competing 13675 updates to the same register, or which are otherwise 13676 disallowed by the spec. */ 13677 switch (summary) { 13678 case 1 | 16: 13679 break; 13680 case 1 | 32: 13681 if (rM == 15) goto after_load_store_doubleword; 13682 break; 13683 case 2 | 16: case 3 | 16: 13684 if (rN == 15) goto after_load_store_doubleword; 13685 if (bS == 0 && (rN == rD || rN == rD+1)) 13686 goto after_load_store_doubleword; 13687 break; 13688 case 2 | 32: case 3 | 32: 13689 if (rM == 15) goto after_load_store_doubleword; 13690 if (rN == 15) goto after_load_store_doubleword; 13691 if (rN == rM) goto after_load_store_doubleword; 13692 if (bS == 0 && (rN == rD || rN == rD+1)) 13693 goto after_load_store_doubleword; 13694 break; 13695 default: 13696 vassert(0); 13697 } 13698 13699 /* Now, we can't do a conditional load or store, since that very 13700 likely will generate an exception. So we have to take a side 13701 exit at this point if the condition is false. */ 13702 if (condT != IRTemp_INVALID) { 13703 mk_skip_over_A32_if_cond_is_false( condT ); 13704 condT = IRTemp_INVALID; 13705 } 13706 /* Ok, now we're unconditional. Do the load or store. */ 13707 13708 /* compute the effective address. Bind it to a tmp since we 13709 may need to use it twice. */ 13710 IRExpr* eaE = NULL; 13711 switch (summary & 0xF0) { 13712 case 16: 13713 eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf ); 13714 break; 13715 case 32: 13716 eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf ); 13717 break; 13718 } 13719 vassert(eaE); 13720 IRTemp eaT = newTemp(Ity_I32); 13721 assign(eaT, eaE); 13722 13723 /* get the old Rn value */ 13724 IRTemp rnT = newTemp(Ity_I32); 13725 assign(rnT, getIRegA(rN)); 13726 13727 /* decide on the transfer address */ 13728 IRTemp taT = IRTemp_INVALID; 13729 switch (summary & 0x0F) { 13730 case 1: case 2: taT = eaT; break; 13731 case 3: taT = rnT; break; 13732 } 13733 vassert(taT != IRTemp_INVALID); 13734 13735 /* XXX deal with alignment constraints */ 13736 /* XXX: but the A8 doesn't seem to trap for misaligned loads, so, 13737 ignore alignment issues for the time being. */ 13738 13739 /* doubleword store S 1 13740 doubleword load S 0 13741 */ 13742 HChar* name = NULL; 13743 /* generate the transfers */ 13744 if (bS == 1) { // doubleword store 13745 storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(0)), getIRegA(rD+0) ); 13746 storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(4)), getIRegA(rD+1) ); 13747 name = "strd"; 13748 } else { // doubleword load 13749 putIRegA( rD+0, 13750 loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(0))), 13751 IRTemp_INVALID, Ijk_Boring ); 13752 putIRegA( rD+1, 13753 loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(4))), 13754 IRTemp_INVALID, Ijk_Boring ); 13755 name = "ldrd"; 13756 } 13757 13758 /* Update Rn if necessary. */ 13759 switch (summary & 0x0F) { 13760 case 2: case 3: 13761 // should be assured by logic above: 13762 if (bS == 0) { 13763 vassert(rD+0 != rN); /* since we just wrote rD+0 */ 13764 vassert(rD+1 != rN); /* since we just wrote rD+1 */ 13765 } 13766 putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring ); 13767 break; 13768 } 13769 13770 switch (summary & 0x0F) { 13771 case 1: DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf); 13772 break; 13773 case 2: DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n", 13774 name, nCC(INSN_COND), rD, dis_buf); 13775 break; 13776 case 3: DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n", 13777 name, nCC(INSN_COND), rD, dis_buf); 13778 break; 13779 default: vassert(0); 13780 } 13781 13782 goto decode_success; 13783 } 13784 13785 after_load_store_doubleword: 13786 13787 /* ------------------- {s,u}xtab ------------- */ 13788 if (BITS8(0,1,1,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 13789 && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1)) 13790 && BITS4(0,1,1,1) == INSN(7,4)) { 13791 UInt rN = INSN(19,16); 13792 UInt rD = INSN(15,12); 13793 UInt rM = INSN(3,0); 13794 UInt rot = (insn >> 10) & 3; 13795 UInt isU = INSN(22,22); 13796 if (rN == 15/*it's {S,U}XTB*/ || rD == 15 || rM == 15) { 13797 /* undecodable; fall through */ 13798 } else { 13799 IRTemp srcL = newTemp(Ity_I32); 13800 IRTemp srcR = newTemp(Ity_I32); 13801 IRTemp res = newTemp(Ity_I32); 13802 assign(srcR, getIRegA(rM)); 13803 assign(srcL, getIRegA(rN)); 13804 assign(res, binop(Iop_Add32, 13805 mkexpr(srcL), 13806 unop(isU ? Iop_8Uto32 : Iop_8Sto32, 13807 unop(Iop_32to8, 13808 genROR32(srcR, 8 * rot))))); 13809 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 13810 DIP("%cxtab%s r%u, r%u, r%u, ror #%u\n", 13811 isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot); 13812 goto decode_success; 13813 } 13814 /* fall through */ 13815 } 13816 13817 /* ------------------- {s,u}xtah ------------- */ 13818 if (BITS8(0,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1)) 13819 && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1)) 13820 && BITS4(0,1,1,1) == INSN(7,4)) { 13821 UInt rN = INSN(19,16); 13822 UInt rD = INSN(15,12); 13823 UInt rM = INSN(3,0); 13824 UInt rot = (insn >> 10) & 3; 13825 UInt isU = INSN(22,22); 13826 if (rN == 15/*it's {S,U}XTH*/ || rD == 15 || rM == 15) { 13827 /* undecodable; fall through */ 13828 } else { 13829 IRTemp srcL = newTemp(Ity_I32); 13830 IRTemp srcR = newTemp(Ity_I32); 13831 IRTemp res = newTemp(Ity_I32); 13832 assign(srcR, getIRegA(rM)); 13833 assign(srcL, getIRegA(rN)); 13834 assign(res, binop(Iop_Add32, 13835 mkexpr(srcL), 13836 unop(isU ? Iop_16Uto32 : Iop_16Sto32, 13837 unop(Iop_32to16, 13838 genROR32(srcR, 8 * rot))))); 13839 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 13840 13841 DIP("%cxtah%s r%u, r%u, r%u, ror #%u\n", 13842 isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot); 13843 goto decode_success; 13844 } 13845 /* fall through */ 13846 } 13847 13848 /* ------------------- rev16, rev ------------------ */ 13849 if (INSN(27,16) == 0x6BF 13850 && (INSN(11,4) == 0xFB/*rev16*/ || INSN(11,4) == 0xF3/*rev*/)) { 13851 Bool isREV = INSN(11,4) == 0xF3; 13852 UInt rM = INSN(3,0); 13853 UInt rD = INSN(15,12); 13854 if (rM != 15 && rD != 15) { 13855 IRTemp rMt = newTemp(Ity_I32); 13856 assign(rMt, getIRegA(rM)); 13857 IRTemp res = isREV ? gen_REV(rMt) : gen_REV16(rMt); 13858 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 13859 DIP("rev%s%s r%u, r%u\n", isREV ? "" : "16", 13860 nCC(INSN_COND), rD, rM); 13861 goto decode_success; 13862 } 13863 } 13864 13865 /* ------------------- rbit ------------------ */ 13866 if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) { 13867 UInt rD = INSN(15,12); 13868 UInt rM = INSN(3,0); 13869 if (rD != 15 && rM != 15) { 13870 IRTemp arg = newTemp(Ity_I32); 13871 assign(arg, getIRegA(rM)); 13872 IRTemp res = gen_BITREV(arg); 13873 putIRegA(rD, mkexpr(res), condT, Ijk_Boring); 13874 DIP("rbit r%u, r%u\n", rD, rM); 13875 goto decode_success; 13876 } 13877 } 13878 13879 /* ------------------- smmul ------------------ */ 13880 if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1) 13881 && INSN(15,12) == BITS4(1,1,1,1) 13882 && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) { 13883 UInt bitR = INSN(5,5); 13884 UInt rD = INSN(19,16); 13885 UInt rM = INSN(11,8); 13886 UInt rN = INSN(3,0); 13887 if (rD != 15 && rM != 15 && rN != 15) { 13888 IRExpr* res 13889 = unop(Iop_64HIto32, 13890 binop(Iop_Add64, 13891 binop(Iop_MullS32, getIRegA(rN), getIRegA(rM)), 13892 mkU64(bitR ? 0x80000000ULL : 0ULL))); 13893 putIRegA(rD, res, condT, Ijk_Boring); 13894 DIP("smmul%s%s r%u, r%u, r%u\n", 13895 nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM); 13896 goto decode_success; 13897 } 13898 } 13899 13900 /* ------------------- NOP ------------------ */ 13901 if (0x0320F000 == (insn & 0x0FFFFFFF)) { 13902 DIP("nop%s\n", nCC(INSN_COND)); 13903 goto decode_success; 13904 } 13905 13906 /* ----------------------------------------------------------- */ 13907 /* -- ARMv7 instructions -- */ 13908 /* ----------------------------------------------------------- */ 13909 13910 /* -------------- read CP15 TPIDRURO register ------------- */ 13911 /* mrc p15, 0, r0, c13, c0, 3 up to 13912 mrc p15, 0, r14, c13, c0, 3 13913 */ 13914 /* I don't know whether this is really v7-only. But anyway, we 13915 have to support it since arm-linux uses TPIDRURO as a thread 13916 state register. */ 13917 if (0x0E1D0F70 == (insn & 0x0FFF0FFF)) { 13918 UInt rD = INSN(15,12); 13919 if (rD <= 14) { 13920 /* skip r15, that's too stupid to handle */ 13921 putIRegA(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), 13922 condT, Ijk_Boring); 13923 DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND), rD); 13924 goto decode_success; 13925 } 13926 /* fall through */ 13927 } 13928 13929 /* Handle various kinds of barriers. This is rather indiscriminate 13930 in the sense that they are all turned into an IR Fence, which 13931 means we don't know which they are, so the back end has to 13932 re-emit them all when it comes acrosss an IR Fence. 13933 */ 13934 if (0xEE070F9A == (insn & 0xFFFF0FFF)) { /* v6 */ 13935 /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7). Data 13936 Synch Barrier -- ensures completion of memory accesses. */ 13937 stmt( IRStmt_MBE(Imbe_Fence) ); 13938 DIP("mcr 15, 0, rX, c7, c10, 4 (data synch barrier)\n"); 13939 goto decode_success; 13940 } 13941 if (0xEE070FBA == (insn & 0xFFFF0FFF)) { /* v6 */ 13942 /* mcr 15, 0, r0, c7, c10, 5 (v6) equiv to DMB (v7). Data 13943 Memory Barrier -- ensures ordering of memory accesses. */ 13944 stmt( IRStmt_MBE(Imbe_Fence) ); 13945 DIP("mcr 15, 0, rX, c7, c10, 5 (data memory barrier)\n"); 13946 goto decode_success; 13947 } 13948 if (0xEE070F95 == (insn & 0xFFFF0FFF)) { /* v6 */ 13949 /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7). 13950 Instruction Synchronisation Barrier (or Flush Prefetch 13951 Buffer) -- a pipe flush, I think. I suspect we could 13952 ignore those, but to be on the safe side emit a fence 13953 anyway. */ 13954 stmt( IRStmt_MBE(Imbe_Fence) ); 13955 DIP("mcr 15, 0, rX, c7, c5, 4 (insn synch barrier)\n"); 13956 goto decode_success; 13957 } 13958 13959 // LDREXD 13960 if (0x01B00F9F == (insn & 0x0FF00FFF)) { 13961 UInt rT = INSN(15,12); 13962 UInt rN = INSN(19,16); 13963 if ((rT & 1) == 1 || rT == BITS4(1,1,1,0) || rN == 15) { 13964 /* undecodable; fall through */ 13965 } else { 13966 IRTemp res; 13967 /* make unconditional */ 13968 if (condT != IRTemp_INVALID) { 13969 mk_skip_over_A32_if_cond_is_false( condT ); 13970 condT = IRTemp_INVALID; 13971 } 13972 /* Ok, now we're unconditional. Do the load. */ 13973 res = newTemp(Ity_I64); 13974 stmt( IRStmt_LLSC(Iend_LE, res, getIRegA(rN), 13975 NULL/*this is a load*/) ); 13976 putIRegA(rT+0, unop(Iop_64HIto32, mkexpr(res)), IRTemp_INVALID, Ijk_Boring); 13977 putIRegA(rT+1, unop(Iop_64to32, mkexpr(res)), IRTemp_INVALID, Ijk_Boring); 13978 13979 DIP("ldrexd%s r%u, r%u, [r%u]\n", nCC(INSN_COND), rT+0, rT+1, rN); 13980 goto decode_success; 13981 } 13982 /* fall through */ 13983 } 13984 13985 // STREXD 13986 if (0x01A00F90 == (insn & 0xFF00FF0)) { 13987 UInt rT = INSN(3,0); 13988 UInt rD = INSN(15,12); 13989 UInt rN = INSN(19,16); 13990 if (rD == 15 || (rT & 1) == 1 || rT == BITS4(1,1,1,0) || rN == 15 13991 || rD == rN || rD == rT || rD == rT+1) { 13992 /* undecodable; fall through */ 13993 } else { 13994 IRTemp data; 13995 IRTemp resSC1, resSC32; 13996 13997 if (condT != IRTemp_INVALID) { 13998 mk_skip_over_A32_if_cond_is_false( condT ); 13999 condT = IRTemp_INVALID; 14000 } 14001 14002 /* Ok, now we're unconditional. Do the store. */ 14003 data = newTemp(Ity_I64); 14004 assign( data, binop(Iop_32HLto64, getIRegA(rT+0), getIRegA(rT+1)) ); 14005 resSC1 = newTemp(Ity_I1); 14006 stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegA(rN), mkexpr(data)) ); 14007 14008 /* Set rD to 1 on failure, 0 on success. Currently we have 14009 resSC1 == 0 on failure, 1 on success. */ 14010 resSC32 = newTemp(Ity_I32); 14011 assign(resSC32, 14012 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1)))); 14013 14014 putIRegA(rD, mkexpr(resSC32), 14015 IRTemp_INVALID, Ijk_Boring); 14016 DIP("strexd%s r%u, r%u, r%u, [r%u]\n", nCC(INSN_COND), rD, rT+0, rT+1, rN); 14017 goto decode_success; 14018 } 14019 /* fall through */ 14020 } 14021 14022 /* ----------------------------------------------------------- */ 14023 /* -- VFP (CP 10, CP 11) instructions (in ARM mode) -- */ 14024 /* ----------------------------------------------------------- */ 14025 14026 if (INSN_COND != ARMCondNV) { 14027 Bool ok_vfp = decode_CP10_CP11_instruction ( 14028 &dres, INSN(27,0), condT, INSN_COND, 14029 False/*!isT*/ 14030 ); 14031 if (ok_vfp) 14032 goto decode_success; 14033 } 14034 14035 /* ----------------------------------------------------------- */ 14036 /* -- NEON instructions (in ARM mode) -- */ 14037 /* ----------------------------------------------------------- */ 14038 14039 /* These are all in NV space, and so are taken care of (far) above, 14040 by a call from this function to decode_NV_instruction(). */ 14041 14042 /* ----------------------------------------------------------- */ 14043 /* -- v6 media instructions (in ARM mode) -- */ 14044 /* ----------------------------------------------------------- */ 14045 14046 { Bool ok_v6m = decode_V6MEDIA_instruction( 14047 &dres, INSN(27,0), condT, INSN_COND, 14048 False/*!isT*/ 14049 ); 14050 if (ok_v6m) 14051 goto decode_success; 14052 } 14053 14054 /* ----------------------------------------------------------- */ 14055 /* -- Undecodable -- */ 14056 /* ----------------------------------------------------------- */ 14057 14058 goto decode_failure; 14059 /*NOTREACHED*/ 14060 14061 decode_failure: 14062 /* All decode failures end up here. */ 14063 vex_printf("disInstr(arm): unhandled instruction: " 14064 "0x%x\n", insn); 14065 vex_printf(" cond=%d(0x%x) 27:20=%u(0x%02x) " 14066 "4:4=%d " 14067 "3:0=%u(0x%x)\n", 14068 (Int)INSN_COND, (UInt)INSN_COND, 14069 (Int)INSN(27,20), (UInt)INSN(27,20), 14070 (Int)INSN(4,4), 14071 (Int)INSN(3,0), (UInt)INSN(3,0) ); 14072 14073 /* Tell the dispatcher that this insn cannot be decoded, and so has 14074 not been executed, and (is currently) the next to be executed. 14075 R15 should be up-to-date since it made so at the start of each 14076 insn, but nevertheless be paranoid and update it again right 14077 now. */ 14078 vassert(0 == (guest_R15_curr_instr_notENC & 3)); 14079 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) ); 14080 irsb->next = mkU32(guest_R15_curr_instr_notENC); 14081 irsb->jumpkind = Ijk_NoDecode; 14082 dres.whatNext = Dis_StopHere; 14083 dres.len = 0; 14084 return dres; 14085 14086 decode_success: 14087 /* All decode successes end up here. */ 14088 DIP("\n"); 14089 14090 vassert(dres.len == 4 || dres.len == 20); 14091 14092 /* Now then. Do we have an implicit jump to r15 to deal with? */ 14093 if (r15written) { 14094 /* If we get jump to deal with, we assume that there's been no 14095 other competing branch stuff previously generated for this 14096 insn. That's reasonable, in the sense that the ARM insn set 14097 appears to declare as "Unpredictable" any instruction which 14098 generates more than one possible new value for r15. Hence 14099 just assert. The decoders themselves should check against 14100 all such instructions which are thusly Unpredictable, and 14101 decline to decode them. Hence we should never get here if we 14102 have competing new values for r15, and hence it is safe to 14103 assert here. */ 14104 vassert(dres.whatNext == Dis_Continue); 14105 vassert(irsb->next == NULL); 14106 vassert(irsb->jumpkind = Ijk_Boring); 14107 /* If r15 is unconditionally written, terminate the block by 14108 jumping to it. If it's conditionally written, still 14109 terminate the block (a shame, but we can't do side exits to 14110 arbitrary destinations), but first jump to the next 14111 instruction if the condition doesn't hold. */ 14112 /* We can't use getIReg(15) to get the destination, since that 14113 will produce r15+8, which isn't what we want. Must use 14114 llGetIReg(15) instead. */ 14115 if (r15guard == IRTemp_INVALID) { 14116 /* unconditional */ 14117 } else { 14118 /* conditional */ 14119 stmt( IRStmt_Exit( 14120 unop(Iop_32to1, 14121 binop(Iop_Xor32, 14122 mkexpr(r15guard), mkU32(1))), 14123 r15kind, 14124 IRConst_U32(guest_R15_curr_instr_notENC + 4) 14125 )); 14126 } 14127 irsb->next = llGetIReg(15); 14128 irsb->jumpkind = r15kind; 14129 dres.whatNext = Dis_StopHere; 14130 } 14131 14132 return dres; 14133 14134 # undef INSN_COND 14135 # undef INSN 14136 } 14137 14138 14139 /*------------------------------------------------------------*/ 14140 /*--- Disassemble a single Thumb2 instruction ---*/ 14141 /*------------------------------------------------------------*/ 14142 14143 /* NB: in Thumb mode we do fetches of regs with getIRegT, which 14144 automagically adds 4 to fetches of r15. However, writes to regs 14145 are done with putIRegT, which disallows writes to r15. Hence any 14146 r15 writes and associated jumps have to be done "by hand". */ 14147 14148 /* Disassemble a single Thumb instruction into IR. The instruction is 14149 located in host memory at guest_instr, and has (decoded) guest IP 14150 of guest_R15_curr_instr_notENC, which will have been set before the 14151 call here. */ 14152 14153 static 14154 DisResult disInstr_THUMB_WRK ( 14155 Bool put_IP, 14156 Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ), 14157 Bool resteerCisOk, 14158 void* callback_opaque, 14159 UChar* guest_instr, 14160 VexArchInfo* archinfo, 14161 VexAbiInfo* abiinfo 14162 ) 14163 { 14164 /* A macro to fish bits out of insn0. There's also INSN1, to fish 14165 bits out of insn1, but that's defined only after the end of the 14166 16-bit insn decoder, so as to stop it mistakenly being used 14167 therein. */ 14168 # define INSN0(_bMax,_bMin) SLICE_UInt(((UInt)insn0), (_bMax), (_bMin)) 14169 14170 DisResult dres; 14171 UShort insn0; /* first 16 bits of the insn */ 14172 //Bool allow_VFP = False; 14173 //UInt hwcaps = archinfo->hwcaps; 14174 HChar dis_buf[128]; // big enough to hold LDMIA etc text 14175 14176 /* Summary result of the ITxxx backwards analysis: False == safe 14177 but suboptimal. */ 14178 Bool guaranteedUnconditional = False; 14179 14180 /* What insn variants are we supporting today? */ 14181 //allow_VFP = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP)); 14182 // etc etc 14183 14184 /* Set result defaults. */ 14185 dres.whatNext = Dis_Continue; 14186 dres.len = 2; 14187 dres.continueAt = 0; 14188 14189 /* Set default actions for post-insn handling of writes to r15, if 14190 required. */ 14191 r15written = False; 14192 r15guard = IRTemp_INVALID; /* unconditional */ 14193 r15kind = Ijk_Boring; 14194 14195 /* Insns could be 2 or 4 bytes long. Just get the first 16 bits at 14196 this point. If we need the second 16, get them later. We can't 14197 get them both out immediately because it risks a fault (very 14198 unlikely, but ..) if the second 16 bits aren't actually 14199 necessary. */ 14200 insn0 = getUShortLittleEndianly( guest_instr ); 14201 14202 if (0) vex_printf("insn: 0x%x\n", insn0); 14203 14204 DIP("\t(thumb) 0x%x: ", (UInt)guest_R15_curr_instr_notENC); 14205 14206 /* We may be asked to update the guest R15 before going further. */ 14207 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 14208 if (put_IP) { 14209 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) ); 14210 } 14211 14212 /* ----------------------------------------------------------- */ 14213 /* Spot "Special" instructions (see comment at top of file). */ 14214 { 14215 UChar* code = (UChar*)guest_instr; 14216 /* Spot the 16-byte preamble: 14217 14218 ea4f 0cfc mov.w ip, ip, ror #3 14219 ea4f 3c7c mov.w ip, ip, ror #13 14220 ea4f 7c7c mov.w ip, ip, ror #29 14221 ea4f 4cfc mov.w ip, ip, ror #19 14222 */ 14223 UInt word1 = 0x0CFCEA4F; 14224 UInt word2 = 0x3C7CEA4F; 14225 UInt word3 = 0x7C7CEA4F; 14226 UInt word4 = 0x4CFCEA4F; 14227 if (getUIntLittleEndianly(code+ 0) == word1 && 14228 getUIntLittleEndianly(code+ 4) == word2 && 14229 getUIntLittleEndianly(code+ 8) == word3 && 14230 getUIntLittleEndianly(code+12) == word4) { 14231 /* Got a "Special" instruction preamble. Which one is it? */ 14232 // 0x 0A 0A EA 4A 14233 if (getUIntLittleEndianly(code+16) == 0x0A0AEA4A 14234 /* orr.w r10,r10,r10 */) { 14235 /* R3 = client_request ( R4 ) */ 14236 DIP("r3 = client_request ( %%r4 )\n"); 14237 irsb->next = mkU32( (guest_R15_curr_instr_notENC + 20) | 1 ); 14238 irsb->jumpkind = Ijk_ClientReq; 14239 dres.whatNext = Dis_StopHere; 14240 goto decode_success; 14241 } 14242 else 14243 // 0x 0B 0B EA 4B 14244 if (getUIntLittleEndianly(code+16) == 0x0B0BEA4B 14245 /* orr r11,r11,r11 */) { 14246 /* R3 = guest_NRADDR */ 14247 DIP("r3 = guest_NRADDR\n"); 14248 dres.len = 20; 14249 llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 )); 14250 goto decode_success; 14251 } 14252 else 14253 // 0x 0C 0C EA 4C 14254 if (getUIntLittleEndianly(code+16) == 0x0C0CEA4C 14255 /* orr r12,r12,r12 */) { 14256 /* branch-and-link-to-noredir R4 */ 14257 DIP("branch-and-link-to-noredir r4\n"); 14258 llPutIReg(14, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 )); 14259 irsb->next = getIRegT(4); 14260 irsb->jumpkind = Ijk_NoRedir; 14261 dres.whatNext = Dis_StopHere; 14262 goto decode_success; 14263 } 14264 /* We don't know what it is. Set insn0 so decode_failure 14265 can print the insn following the Special-insn preamble. */ 14266 insn0 = getUShortLittleEndianly(code+16); 14267 goto decode_failure; 14268 /*NOTREACHED*/ 14269 } 14270 14271 } 14272 14273 /* ----------------------------------------------------------- */ 14274 14275 /* Main Thumb instruction decoder starts here. It's a series of 14276 switches which examine ever longer bit sequences at the MSB of 14277 the instruction word, first for 16-bit insns, then for 32-bit 14278 insns. */ 14279 14280 /* --- BEGIN ITxxx optimisation analysis --- */ 14281 /* This is a crucial optimisation for the ITState boilerplate that 14282 follows. Examine the 9 halfwords preceding this instruction, 14283 and if we are absolutely sure that none of them constitute an 14284 'it' instruction, then we can be sure that this instruction is 14285 not under the control of any 'it' instruction, and so 14286 guest_ITSTATE must be zero. So write zero into ITSTATE right 14287 now, so that iropt can fold out almost all of the resulting 14288 junk. 14289 14290 If we aren't sure, we can always safely skip this step. So be a 14291 bit conservative about it: only poke around in the same page as 14292 this instruction, lest we get a fault from the previous page 14293 that would not otherwise have happened. The saving grace is 14294 that such skipping is pretty rare -- it only happens, 14295 statistically, 18/4096ths of the time, so is judged unlikely to 14296 be a performance problems. 14297 14298 FIXME: do better. Take into account the number of insns covered 14299 by any IT insns we find, to rule out cases where an IT clearly 14300 cannot cover this instruction. This would improve behaviour for 14301 branch targets immediately following an IT-guarded group that is 14302 not of full length. Eg, (and completely ignoring issues of 16- 14303 vs 32-bit insn length): 14304 14305 ite cond 14306 insn1 14307 insn2 14308 label: insn3 14309 insn4 14310 14311 The 'it' only conditionalises insn1 and insn2. However, the 14312 current analysis is conservative and considers insn3 and insn4 14313 also possibly guarded. Hence if 'label:' is the start of a hot 14314 loop we will get a big performance hit. 14315 */ 14316 { 14317 /* Summary result of this analysis: False == safe but 14318 suboptimal. */ 14319 vassert(guaranteedUnconditional == False); 14320 14321 UInt pc = guest_R15_curr_instr_notENC; 14322 vassert(0 == (pc & 1)); 14323 14324 UInt pageoff = pc & 0xFFF; 14325 if (pageoff >= 18) { 14326 /* It's safe to poke about in the 9 halfwords preceding this 14327 insn. So, have a look at them. */ 14328 guaranteedUnconditional = True; /* assume no 'it' insn found, till we do */ 14329 14330 UShort* hwp = (UShort*)(HWord)pc; 14331 Int i; 14332 for (i = -1; i >= -9; i--) { 14333 /* We're in the same page. (True, but commented out due 14334 to expense.) */ 14335 /* 14336 vassert( ( ((UInt)(&hwp[i])) & 0xFFFFF000 ) 14337 == ( pc & 0xFFFFF000 ) ); 14338 */ 14339 /* All valid IT instructions must have the form 0xBFxy, 14340 where x can be anything, but y must be nonzero. */ 14341 if ((hwp[i] & 0xFF00) == 0xBF00 && (hwp[i] & 0xF) != 0) { 14342 /* might be an 'it' insn. Play safe. */ 14343 guaranteedUnconditional = False; 14344 break; 14345 } 14346 } 14347 } 14348 } 14349 /* --- END ITxxx optimisation analysis --- */ 14350 14351 /* Generate the guarding condition for this insn, by examining 14352 ITSTATE. Assign it to condT. Also, generate new 14353 values for ITSTATE ready for stuffing back into the 14354 guest state, but don't actually do the Put yet, since it will 14355 need to stuffed back in only after the instruction gets to a 14356 point where it is sure to complete. Mostly we let the code at 14357 decode_success handle this, but in cases where the insn contains 14358 a side exit, we have to update them before the exit. */ 14359 14360 /* If the ITxxx optimisation analysis above could not prove that 14361 this instruction is guaranteed unconditional, we insert a 14362 lengthy IR preamble to compute the guarding condition at 14363 runtime. If it can prove it (which obviously we hope is the 14364 normal case) then we insert a minimal preamble, which is 14365 equivalent to setting guest_ITSTATE to zero and then folding 14366 that through the full preamble (which completely disappears). */ 14367 14368 IRTemp condT = IRTemp_INVALID; 14369 IRTemp old_itstate = IRTemp_INVALID; 14370 IRTemp new_itstate = IRTemp_INVALID; 14371 IRTemp cond_AND_notInIT_T = IRTemp_INVALID; 14372 14373 if (guaranteedUnconditional) { 14374 /* BEGIN "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */ 14375 14376 // ITSTATE = 0 :: I32 14377 IRTemp z32 = newTemp(Ity_I32); 14378 assign(z32, mkU32(0)); 14379 put_ITSTATE(z32); 14380 14381 // old_itstate = 0 :: I32 14382 // 14383 // old_itstate = get_ITSTATE(); 14384 old_itstate = z32; /* 0 :: I32 */ 14385 14386 // new_itstate = old_itstate >> 8 14387 // = 0 >> 8 14388 // = 0 :: I32 14389 // 14390 // new_itstate = newTemp(Ity_I32); 14391 // assign(new_itstate, 14392 // binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8))); 14393 new_itstate = z32; 14394 14395 // ITSTATE = 0 :: I32(again) 14396 // 14397 // put_ITSTATE(new_itstate); 14398 14399 // condT1 = calc_cond_dyn( xor(and(old_istate,0xF0), 0xE0) ) 14400 // = calc_cond_dyn( xor(0,0xE0) ) 14401 // = calc_cond_dyn ( 0xE0 ) 14402 // = 1 :: I32 14403 // Not that this matters, since the computed value is not used: 14404 // see condT folding below 14405 // 14406 // IRTemp condT1 = newTemp(Ity_I32); 14407 // assign(condT1, 14408 // mk_armg_calculate_condition_dyn( 14409 // binop(Iop_Xor32, 14410 // binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)), 14411 // mkU32(0xE0)) 14412 // ) 14413 // ); 14414 14415 // condT = 32to8(and32(old_itstate,0xF0)) == 0 ? 1 : condT1 14416 // = 32to8(and32(0,0xF0)) == 0 ? 1 : condT1 14417 // = 32to8(0) == 0 ? 1 : condT1 14418 // = 0 == 0 ? 1 : condT1 14419 // = 1 14420 // 14421 // condT = newTemp(Ity_I32); 14422 // assign(condT, IRExpr_Mux0X( 14423 // unop(Iop_32to8, binop(Iop_And32, 14424 // mkexpr(old_itstate), 14425 // mkU32(0xF0))), 14426 // mkU32(1), 14427 // mkexpr(condT1) 14428 // )); 14429 condT = newTemp(Ity_I32); 14430 assign(condT, mkU32(1)); 14431 14432 // notInITt = xor32(and32(old_itstate, 1), 1) 14433 // = xor32(and32(0, 1), 1) 14434 // = xor32(0, 1) 14435 // = 1 :: I32 14436 // 14437 // IRTemp notInITt = newTemp(Ity_I32); 14438 // assign(notInITt, 14439 // binop(Iop_Xor32, 14440 // binop(Iop_And32, mkexpr(old_itstate), mkU32(1)), 14441 // mkU32(1))); 14442 14443 // cond_AND_notInIT_T = and32(notInITt, condT) 14444 // = and32(1, 1) 14445 // = 1 14446 // 14447 // cond_AND_notInIT_T = newTemp(Ity_I32); 14448 // assign(cond_AND_notInIT_T, 14449 // binop(Iop_And32, mkexpr(notInITt), mkexpr(condT))); 14450 cond_AND_notInIT_T = condT; /* 1 :: I32 */ 14451 14452 /* END "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */ 14453 } else { 14454 /* BEGIN { STANDARD PREAMBLE; } */ 14455 14456 old_itstate = get_ITSTATE(); 14457 14458 new_itstate = newTemp(Ity_I32); 14459 assign(new_itstate, 14460 binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8))); 14461 14462 put_ITSTATE(new_itstate); 14463 14464 /* Same strategy as for ARM insns: generate a condition 14465 temporary at this point (or IRTemp_INVALID, meaning 14466 unconditional). We leave it to lower-level instruction 14467 decoders to decide whether they can generate straight-line 14468 code, or whether they must generate a side exit before the 14469 instruction. condT :: Ity_I32 and is always either zero or 14470 one. */ 14471 IRTemp condT1 = newTemp(Ity_I32); 14472 assign(condT1, 14473 mk_armg_calculate_condition_dyn( 14474 binop(Iop_Xor32, 14475 binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)), 14476 mkU32(0xE0)) 14477 ) 14478 ); 14479 14480 /* This is a bit complex, but needed to make Memcheck understand 14481 that, if the condition in old_itstate[7:4] denotes AL (that 14482 is, if this instruction is to be executed unconditionally), 14483 then condT does not depend on the results of calling the 14484 helper. 14485 14486 We test explicitly for old_itstate[7:4] == AL ^ 0xE, and in 14487 that case set condT directly to 1. Else we use the results 14488 of the helper. Since old_itstate is always defined and 14489 because Memcheck does lazy V-bit propagation through Mux0X, 14490 this will cause condT to always be a defined 1 if the 14491 condition is 'AL'. From an execution semantics point of view 14492 this is irrelevant since we're merely duplicating part of the 14493 behaviour of the helper. But it makes it clear to Memcheck, 14494 in this case, that condT does not in fact depend on the 14495 contents of the condition code thunk. Without it, we get 14496 quite a lot of false errors. 14497 14498 So, just to clarify: from a straight semantics point of view, 14499 we can simply do "assign(condT, mkexpr(condT1))", and the 14500 simulator still runs fine. It's just that we get loads of 14501 false errors from Memcheck. */ 14502 condT = newTemp(Ity_I32); 14503 assign(condT, IRExpr_Mux0X( 14504 unop(Iop_32to8, binop(Iop_And32, 14505 mkexpr(old_itstate), 14506 mkU32(0xF0))), 14507 mkU32(1), 14508 mkexpr(condT1) 14509 )); 14510 14511 /* Something we don't have in ARM: generate a 0 or 1 value 14512 indicating whether or not we are in an IT block (NB: 0 = in 14513 IT block, 1 = not in IT block). This is used to gate 14514 condition code updates in 16-bit Thumb instructions. */ 14515 IRTemp notInITt = newTemp(Ity_I32); 14516 assign(notInITt, 14517 binop(Iop_Xor32, 14518 binop(Iop_And32, mkexpr(old_itstate), mkU32(1)), 14519 mkU32(1))); 14520 14521 /* Compute 'condT && notInITt' -- that is, the instruction is 14522 going to execute, and we're not in an IT block. This is the 14523 gating condition for updating condition codes in 16-bit Thumb 14524 instructions, except for CMP, CMN and TST. */ 14525 cond_AND_notInIT_T = newTemp(Ity_I32); 14526 assign(cond_AND_notInIT_T, 14527 binop(Iop_And32, mkexpr(notInITt), mkexpr(condT))); 14528 /* END { STANDARD PREAMBLE; } */ 14529 } 14530 14531 14532 /* At this point: 14533 * ITSTATE has been updated 14534 * condT holds the guarding condition for this instruction (0 or 1), 14535 * notInITt is 1 if we're in "normal" code, 0 if in an IT block 14536 * cond_AND_notInIT_T is the AND of the above two. 14537 14538 If the instruction proper can't trap, then there's nothing else 14539 to do w.r.t. ITSTATE -- just go and and generate IR for the 14540 insn, taking into account the guarding condition. 14541 14542 If, however, the instruction might trap, then we must back up 14543 ITSTATE to the old value, and re-update it after the potentially 14544 trapping IR section. A trap can happen either via a memory 14545 reference or because we need to throw SIGILL. 14546 14547 If an instruction has a side exit, we need to be sure that any 14548 ITSTATE backup is re-updated before the side exit. 14549 */ 14550 14551 /* ----------------------------------------------------------- */ 14552 /* -- -- */ 14553 /* -- Thumb 16-bit integer instructions -- */ 14554 /* -- -- */ 14555 /* -- IMPORTANT: references to insn1 or INSN1 are -- */ 14556 /* -- not allowed in this section -- */ 14557 /* -- -- */ 14558 /* ----------------------------------------------------------- */ 14559 14560 /* 16-bit instructions inside an IT block, apart from CMP, CMN and 14561 TST, do not set the condition codes. Hence we must dynamically 14562 test for this case for every condition code update. */ 14563 14564 IROp anOp = Iop_INVALID; 14565 HChar* anOpNm = NULL; 14566 14567 /* ================ 16-bit 15:6 cases ================ */ 14568 14569 switch (INSN0(15,6)) { 14570 14571 case 0x10a: // CMP 14572 case 0x10b: { // CMN 14573 /* ---------------- CMP Rn, Rm ---------------- */ 14574 Bool isCMN = INSN0(15,6) == 0x10b; 14575 UInt rN = INSN0(2,0); 14576 UInt rM = INSN0(5,3); 14577 IRTemp argL = newTemp(Ity_I32); 14578 IRTemp argR = newTemp(Ity_I32); 14579 assign( argL, getIRegT(rN) ); 14580 assign( argR, getIRegT(rM) ); 14581 /* Update flags regardless of whether in an IT block or not. */ 14582 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB, 14583 argL, argR, condT ); 14584 DIP("%s r%u, r%u\n", isCMN ? "cmn" : "cmp", rN, rM); 14585 goto decode_success; 14586 } 14587 14588 case 0x108: { 14589 /* ---------------- TST Rn, Rm ---------------- */ 14590 UInt rN = INSN0(2,0); 14591 UInt rM = INSN0(5,3); 14592 IRTemp oldC = newTemp(Ity_I32); 14593 IRTemp oldV = newTemp(Ity_I32); 14594 IRTemp res = newTemp(Ity_I32); 14595 assign( oldC, mk_armg_calculate_flag_c() ); 14596 assign( oldV, mk_armg_calculate_flag_v() ); 14597 assign( res, binop(Iop_And32, getIRegT(rN), getIRegT(rM)) ); 14598 /* Update flags regardless of whether in an IT block or not. */ 14599 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT ); 14600 DIP("tst r%u, r%u\n", rN, rM); 14601 goto decode_success; 14602 } 14603 14604 case 0x109: { 14605 /* ---------------- NEGS Rd, Rm ---------------- */ 14606 /* Rd = -Rm */ 14607 UInt rM = INSN0(5,3); 14608 UInt rD = INSN0(2,0); 14609 IRTemp arg = newTemp(Ity_I32); 14610 IRTemp zero = newTemp(Ity_I32); 14611 assign(arg, getIRegT(rM)); 14612 assign(zero, mkU32(0)); 14613 // rD can never be r15 14614 putIRegT(rD, binop(Iop_Sub32, mkexpr(zero), mkexpr(arg)), condT); 14615 setFlags_D1_D2( ARMG_CC_OP_SUB, zero, arg, cond_AND_notInIT_T); 14616 DIP("negs r%u, r%u\n", rD, rM); 14617 goto decode_success; 14618 } 14619 14620 case 0x10F: { 14621 /* ---------------- MVNS Rd, Rm ---------------- */ 14622 /* Rd = ~Rm */ 14623 UInt rM = INSN0(5,3); 14624 UInt rD = INSN0(2,0); 14625 IRTemp oldV = newTemp(Ity_I32); 14626 IRTemp oldC = newTemp(Ity_I32); 14627 IRTemp res = newTemp(Ity_I32); 14628 assign( oldV, mk_armg_calculate_flag_v() ); 14629 assign( oldC, mk_armg_calculate_flag_c() ); 14630 assign(res, unop(Iop_Not32, getIRegT(rM))); 14631 // rD can never be r15 14632 putIRegT(rD, mkexpr(res), condT); 14633 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 14634 cond_AND_notInIT_T ); 14635 DIP("mvns r%u, r%u\n", rD, rM); 14636 goto decode_success; 14637 } 14638 14639 case 0x10C: 14640 /* ---------------- ORRS Rd, Rm ---------------- */ 14641 anOp = Iop_Or32; anOpNm = "orr"; goto and_orr_eor_mul; 14642 case 0x100: 14643 /* ---------------- ANDS Rd, Rm ---------------- */ 14644 anOp = Iop_And32; anOpNm = "and"; goto and_orr_eor_mul; 14645 case 0x101: 14646 /* ---------------- EORS Rd, Rm ---------------- */ 14647 anOp = Iop_Xor32; anOpNm = "eor"; goto and_orr_eor_mul; 14648 case 0x10d: 14649 /* ---------------- MULS Rd, Rm ---------------- */ 14650 anOp = Iop_Mul32; anOpNm = "mul"; goto and_orr_eor_mul; 14651 and_orr_eor_mul: { 14652 /* Rd = Rd `op` Rm */ 14653 UInt rM = INSN0(5,3); 14654 UInt rD = INSN0(2,0); 14655 IRTemp res = newTemp(Ity_I32); 14656 IRTemp oldV = newTemp(Ity_I32); 14657 IRTemp oldC = newTemp(Ity_I32); 14658 assign( oldV, mk_armg_calculate_flag_v() ); 14659 assign( oldC, mk_armg_calculate_flag_c() ); 14660 assign( res, binop(anOp, getIRegT(rD), getIRegT(rM) )); 14661 // not safe to read guest state after here 14662 // rD can never be r15 14663 putIRegT(rD, mkexpr(res), condT); 14664 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 14665 cond_AND_notInIT_T ); 14666 DIP("%s r%u, r%u\n", anOpNm, rD, rM); 14667 goto decode_success; 14668 } 14669 14670 case 0x10E: { 14671 /* ---------------- BICS Rd, Rm ---------------- */ 14672 /* Rd = Rd & ~Rm */ 14673 UInt rM = INSN0(5,3); 14674 UInt rD = INSN0(2,0); 14675 IRTemp res = newTemp(Ity_I32); 14676 IRTemp oldV = newTemp(Ity_I32); 14677 IRTemp oldC = newTemp(Ity_I32); 14678 assign( oldV, mk_armg_calculate_flag_v() ); 14679 assign( oldC, mk_armg_calculate_flag_c() ); 14680 assign( res, binop(Iop_And32, getIRegT(rD), 14681 unop(Iop_Not32, getIRegT(rM) ))); 14682 // not safe to read guest state after here 14683 // rD can never be r15 14684 putIRegT(rD, mkexpr(res), condT); 14685 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 14686 cond_AND_notInIT_T ); 14687 DIP("bics r%u, r%u\n", rD, rM); 14688 goto decode_success; 14689 } 14690 14691 case 0x105: { 14692 /* ---------------- ADCS Rd, Rm ---------------- */ 14693 /* Rd = Rd + Rm + oldC */ 14694 UInt rM = INSN0(5,3); 14695 UInt rD = INSN0(2,0); 14696 IRTemp argL = newTemp(Ity_I32); 14697 IRTemp argR = newTemp(Ity_I32); 14698 IRTemp oldC = newTemp(Ity_I32); 14699 IRTemp res = newTemp(Ity_I32); 14700 assign(argL, getIRegT(rD)); 14701 assign(argR, getIRegT(rM)); 14702 assign(oldC, mk_armg_calculate_flag_c()); 14703 assign(res, binop(Iop_Add32, 14704 binop(Iop_Add32, mkexpr(argL), mkexpr(argR)), 14705 mkexpr(oldC))); 14706 // rD can never be r15 14707 putIRegT(rD, mkexpr(res), condT); 14708 setFlags_D1_D2_ND( ARMG_CC_OP_ADC, argL, argR, oldC, 14709 cond_AND_notInIT_T ); 14710 DIP("adcs r%u, r%u\n", rD, rM); 14711 goto decode_success; 14712 } 14713 14714 case 0x106: { 14715 /* ---------------- SBCS Rd, Rm ---------------- */ 14716 /* Rd = Rd - Rm - (oldC ^ 1) */ 14717 UInt rM = INSN0(5,3); 14718 UInt rD = INSN0(2,0); 14719 IRTemp argL = newTemp(Ity_I32); 14720 IRTemp argR = newTemp(Ity_I32); 14721 IRTemp oldC = newTemp(Ity_I32); 14722 IRTemp res = newTemp(Ity_I32); 14723 assign(argL, getIRegT(rD)); 14724 assign(argR, getIRegT(rM)); 14725 assign(oldC, mk_armg_calculate_flag_c()); 14726 assign(res, binop(Iop_Sub32, 14727 binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)), 14728 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)))); 14729 // rD can never be r15 14730 putIRegT(rD, mkexpr(res), condT); 14731 setFlags_D1_D2_ND( ARMG_CC_OP_SBB, argL, argR, oldC, 14732 cond_AND_notInIT_T ); 14733 DIP("sbcs r%u, r%u\n", rD, rM); 14734 goto decode_success; 14735 } 14736 14737 case 0x2CB: { 14738 /* ---------------- UXTB Rd, Rm ---------------- */ 14739 /* Rd = 8Uto32(Rm) */ 14740 UInt rM = INSN0(5,3); 14741 UInt rD = INSN0(2,0); 14742 putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFF)), 14743 condT); 14744 DIP("uxtb r%u, r%u\n", rD, rM); 14745 goto decode_success; 14746 } 14747 14748 case 0x2C9: { 14749 /* ---------------- SXTB Rd, Rm ---------------- */ 14750 /* Rd = 8Sto32(Rm) */ 14751 UInt rM = INSN0(5,3); 14752 UInt rD = INSN0(2,0); 14753 putIRegT(rD, binop(Iop_Sar32, 14754 binop(Iop_Shl32, getIRegT(rM), mkU8(24)), 14755 mkU8(24)), 14756 condT); 14757 DIP("sxtb r%u, r%u\n", rD, rM); 14758 goto decode_success; 14759 } 14760 14761 case 0x2CA: { 14762 /* ---------------- UXTH Rd, Rm ---------------- */ 14763 /* Rd = 16Uto32(Rm) */ 14764 UInt rM = INSN0(5,3); 14765 UInt rD = INSN0(2,0); 14766 putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFFFF)), 14767 condT); 14768 DIP("uxth r%u, r%u\n", rD, rM); 14769 goto decode_success; 14770 } 14771 14772 case 0x2C8: { 14773 /* ---------------- SXTH Rd, Rm ---------------- */ 14774 /* Rd = 16Sto32(Rm) */ 14775 UInt rM = INSN0(5,3); 14776 UInt rD = INSN0(2,0); 14777 putIRegT(rD, binop(Iop_Sar32, 14778 binop(Iop_Shl32, getIRegT(rM), mkU8(16)), 14779 mkU8(16)), 14780 condT); 14781 DIP("sxth r%u, r%u\n", rD, rM); 14782 goto decode_success; 14783 } 14784 14785 case 0x102: // LSLS 14786 case 0x103: // LSRS 14787 case 0x104: // ASRS 14788 case 0x107: { // RORS 14789 /* ---------------- LSLS Rs, Rd ---------------- */ 14790 /* ---------------- LSRS Rs, Rd ---------------- */ 14791 /* ---------------- ASRS Rs, Rd ---------------- */ 14792 /* ---------------- RORS Rs, Rd ---------------- */ 14793 /* Rd = Rd `op` Rs, and set flags */ 14794 UInt rS = INSN0(5,3); 14795 UInt rD = INSN0(2,0); 14796 IRTemp oldV = newTemp(Ity_I32); 14797 IRTemp rDt = newTemp(Ity_I32); 14798 IRTemp rSt = newTemp(Ity_I32); 14799 IRTemp res = newTemp(Ity_I32); 14800 IRTemp resC = newTemp(Ity_I32); 14801 HChar* wot = "???"; 14802 assign(rSt, getIRegT(rS)); 14803 assign(rDt, getIRegT(rD)); 14804 assign(oldV, mk_armg_calculate_flag_v()); 14805 /* Does not appear to be the standard 'how' encoding. */ 14806 switch (INSN0(15,6)) { 14807 case 0x102: 14808 compute_result_and_C_after_LSL_by_reg( 14809 dis_buf, &res, &resC, rDt, rSt, rD, rS 14810 ); 14811 wot = "lsl"; 14812 break; 14813 case 0x103: 14814 compute_result_and_C_after_LSR_by_reg( 14815 dis_buf, &res, &resC, rDt, rSt, rD, rS 14816 ); 14817 wot = "lsr"; 14818 break; 14819 case 0x104: 14820 compute_result_and_C_after_ASR_by_reg( 14821 dis_buf, &res, &resC, rDt, rSt, rD, rS 14822 ); 14823 wot = "asr"; 14824 break; 14825 case 0x107: 14826 compute_result_and_C_after_ROR_by_reg( 14827 dis_buf, &res, &resC, rDt, rSt, rD, rS 14828 ); 14829 wot = "ror"; 14830 break; 14831 default: 14832 /*NOTREACHED*/vassert(0); 14833 } 14834 // not safe to read guest state after this point 14835 putIRegT(rD, mkexpr(res), condT); 14836 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV, 14837 cond_AND_notInIT_T ); 14838 DIP("%ss r%u, r%u\n", wot, rS, rD); 14839 goto decode_success; 14840 } 14841 14842 case 0x2E8: // REV 14843 case 0x2E9: { // REV16 14844 /* ---------------- REV Rd, Rm ---------------- */ 14845 /* ---------------- REV16 Rd, Rm ---------------- */ 14846 UInt rM = INSN0(5,3); 14847 UInt rD = INSN0(2,0); 14848 Bool isREV = INSN0(15,6) == 0x2E8; 14849 IRTemp arg = newTemp(Ity_I32); 14850 assign(arg, getIRegT(rM)); 14851 IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg); 14852 putIRegT(rD, mkexpr(res), condT); 14853 DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM); 14854 goto decode_success; 14855 } 14856 14857 default: 14858 break; /* examine the next shortest prefix */ 14859 14860 } 14861 14862 14863 /* ================ 16-bit 15:7 cases ================ */ 14864 14865 switch (INSN0(15,7)) { 14866 14867 case BITS9(1,0,1,1,0,0,0,0,0): { 14868 /* ------------ ADD SP, #imm7 * 4 ------------ */ 14869 UInt uimm7 = INSN0(6,0); 14870 putIRegT(13, binop(Iop_Add32, getIRegT(13), mkU32(uimm7 * 4)), 14871 condT); 14872 DIP("add sp, #%u\n", uimm7 * 4); 14873 goto decode_success; 14874 } 14875 14876 case BITS9(1,0,1,1,0,0,0,0,1): { 14877 /* ------------ SUB SP, #imm7 * 4 ------------ */ 14878 UInt uimm7 = INSN0(6,0); 14879 putIRegT(13, binop(Iop_Sub32, getIRegT(13), mkU32(uimm7 * 4)), 14880 condT); 14881 DIP("sub sp, #%u\n", uimm7 * 4); 14882 goto decode_success; 14883 } 14884 14885 case BITS9(0,1,0,0,0,1,1,1,0): { 14886 /* ---------------- BX rM ---------------- */ 14887 /* Branch to reg, and optionally switch modes. Reg contains a 14888 suitably encoded address therefore (w CPSR.T at the bottom). 14889 Have to special-case r15, as usual. */ 14890 UInt rM = (INSN0(6,6) << 3) | INSN0(5,3); 14891 if (BITS3(0,0,0) == INSN0(2,0)) { 14892 IRTemp dst = newTemp(Ity_I32); 14893 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 14894 mk_skip_over_T16_if_cond_is_false(condT); 14895 condT = IRTemp_INVALID; 14896 // now uncond 14897 if (rM <= 14) { 14898 assign( dst, getIRegT(rM) ); 14899 } else { 14900 vassert(rM == 15); 14901 assign( dst, mkU32(guest_R15_curr_instr_notENC + 4) ); 14902 } 14903 irsb->next = mkexpr(dst); 14904 irsb->jumpkind = Ijk_Boring; 14905 dres.whatNext = Dis_StopHere; 14906 DIP("bx r%u (possibly switch to ARM mode)\n", rM); 14907 goto decode_success; 14908 } 14909 break; 14910 } 14911 14912 /* ---------------- BLX rM ---------------- */ 14913 /* Branch and link to interworking address in rM. */ 14914 case BITS9(0,1,0,0,0,1,1,1,1): { 14915 if (BITS3(0,0,0) == INSN0(2,0)) { 14916 UInt rM = (INSN0(6,6) << 3) | INSN0(5,3); 14917 IRTemp dst = newTemp(Ity_I32); 14918 if (rM <= 14) { 14919 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 14920 mk_skip_over_T16_if_cond_is_false(condT); 14921 condT = IRTemp_INVALID; 14922 // now uncond 14923 /* We're returning to Thumb code, hence "| 1" */ 14924 assign( dst, getIRegT(rM) ); 14925 putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ), 14926 IRTemp_INVALID ); 14927 irsb->next = mkexpr(dst); 14928 irsb->jumpkind = Ijk_Call; 14929 dres.whatNext = Dis_StopHere; 14930 DIP("blx r%u (possibly switch to ARM mode)\n", rM); 14931 goto decode_success; 14932 } 14933 /* else unpredictable, fall through */ 14934 } 14935 break; 14936 } 14937 14938 default: 14939 break; /* examine the next shortest prefix */ 14940 14941 } 14942 14943 14944 /* ================ 16-bit 15:8 cases ================ */ 14945 14946 switch (INSN0(15,8)) { 14947 14948 case BITS8(1,1,0,1,1,1,1,1): { 14949 /* ---------------- SVC ---------------- */ 14950 UInt imm8 = INSN0(7,0); 14951 if (imm8 == 0) { 14952 /* A syscall. We can't do this conditionally, hence: */ 14953 mk_skip_over_T16_if_cond_is_false( condT ); 14954 // FIXME: what if we have to back up and restart this insn? 14955 // then ITSTATE will be wrong (we'll have it as "used") 14956 // when it isn't. Correct is to save ITSTATE in a 14957 // stash pseudo-reg, and back up from that if we have to 14958 // restart. 14959 // uncond after here 14960 irsb->next = mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ); 14961 irsb->jumpkind = Ijk_Sys_syscall; 14962 dres.whatNext = Dis_StopHere; 14963 DIP("svc #0x%08x\n", imm8); 14964 goto decode_success; 14965 } 14966 /* else fall through */ 14967 break; 14968 } 14969 14970 case BITS8(0,1,0,0,0,1,0,0): { 14971 /* ---------------- ADD(HI) Rd, Rm ---------------- */ 14972 UInt h1 = INSN0(7,7); 14973 UInt h2 = INSN0(6,6); 14974 UInt rM = (h2 << 3) | INSN0(5,3); 14975 UInt rD = (h1 << 3) | INSN0(2,0); 14976 //if (h1 == 0 && h2 == 0) { // Original T1 was more restrictive 14977 if (rD == 15 && rM == 15) { 14978 // then it's invalid 14979 } else { 14980 IRTemp res = newTemp(Ity_I32); 14981 assign( res, binop(Iop_Add32, getIRegT(rD), getIRegT(rM) )); 14982 if (rD != 15) { 14983 putIRegT( rD, mkexpr(res), condT ); 14984 } else { 14985 /* Only allowed outside or last-in IT block; SIGILL if not so. */ 14986 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 14987 /* jump over insn if not selected */ 14988 mk_skip_over_T16_if_cond_is_false(condT); 14989 condT = IRTemp_INVALID; 14990 // now uncond 14991 /* non-interworking branch */ 14992 irsb->next = binop(Iop_Or32, mkexpr(res), mkU32(1)); 14993 irsb->jumpkind = Ijk_Boring; 14994 dres.whatNext = Dis_StopHere; 14995 } 14996 DIP("add(hi) r%u, r%u\n", rD, rM); 14997 goto decode_success; 14998 } 14999 break; 15000 } 15001 15002 case BITS8(0,1,0,0,0,1,0,1): { 15003 /* ---------------- CMP(HI) Rd, Rm ---------------- */ 15004 UInt h1 = INSN0(7,7); 15005 UInt h2 = INSN0(6,6); 15006 UInt rM = (h2 << 3) | INSN0(5,3); 15007 UInt rN = (h1 << 3) | INSN0(2,0); 15008 if (h1 != 0 || h2 != 0) { 15009 IRTemp argL = newTemp(Ity_I32); 15010 IRTemp argR = newTemp(Ity_I32); 15011 assign( argL, getIRegT(rN) ); 15012 assign( argR, getIRegT(rM) ); 15013 /* Update flags regardless of whether in an IT block or not. */ 15014 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT ); 15015 DIP("cmphi r%u, r%u\n", rN, rM); 15016 goto decode_success; 15017 } 15018 break; 15019 } 15020 15021 case BITS8(0,1,0,0,0,1,1,0): { 15022 /* ---------------- MOV(HI) Rd, Rm ---------------- */ 15023 UInt h1 = INSN0(7,7); 15024 UInt h2 = INSN0(6,6); 15025 UInt rM = (h2 << 3) | INSN0(5,3); 15026 UInt rD = (h1 << 3) | INSN0(2,0); 15027 /* The old ARM ARM seems to disallow the case where both Rd and 15028 Rm are "low" registers, but newer versions allow it. */ 15029 if (1 /*h1 != 0 || h2 != 0*/) { 15030 IRTemp val = newTemp(Ity_I32); 15031 assign( val, getIRegT(rM) ); 15032 if (rD != 15) { 15033 putIRegT( rD, mkexpr(val), condT ); 15034 } else { 15035 /* Only allowed outside or last-in IT block; SIGILL if not so. */ 15036 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 15037 /* jump over insn if not selected */ 15038 mk_skip_over_T16_if_cond_is_false(condT); 15039 condT = IRTemp_INVALID; 15040 // now uncond 15041 /* non-interworking branch */ 15042 irsb->next = binop(Iop_Or32, mkexpr(val), mkU32(1)); 15043 irsb->jumpkind = Ijk_Boring; 15044 dres.whatNext = Dis_StopHere; 15045 } 15046 DIP("mov r%u, r%u\n", rD, rM); 15047 goto decode_success; 15048 } 15049 break; 15050 } 15051 15052 case BITS8(1,0,1,1,1,1,1,1): { 15053 /* ---------------- IT (if-then) ---------------- */ 15054 UInt firstcond = INSN0(7,4); 15055 UInt mask = INSN0(3,0); 15056 UInt newITSTATE = 0; 15057 /* This is the ITSTATE represented as described in 15058 libvex_guest_arm.h. It is not the ARM ARM representation. */ 15059 UChar c1 = '.'; 15060 UChar c2 = '.'; 15061 UChar c3 = '.'; 15062 Bool valid = compute_ITSTATE( &newITSTATE, &c1, &c2, &c3, 15063 firstcond, mask ); 15064 if (valid && firstcond != 0xF/*NV*/) { 15065 /* Not allowed in an IT block; SIGILL if so. */ 15066 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate); 15067 15068 IRTemp t = newTemp(Ity_I32); 15069 assign(t, mkU32(newITSTATE)); 15070 put_ITSTATE(t); 15071 15072 DIP("it%c%c%c %s\n", c1, c2, c3, nCC(firstcond)); 15073 goto decode_success; 15074 } 15075 break; 15076 } 15077 15078 case BITS8(1,0,1,1,0,0,0,1): 15079 case BITS8(1,0,1,1,0,0,1,1): 15080 case BITS8(1,0,1,1,1,0,0,1): 15081 case BITS8(1,0,1,1,1,0,1,1): { 15082 /* ---------------- CB{N}Z ---------------- */ 15083 UInt rN = INSN0(2,0); 15084 UInt bOP = INSN0(11,11); 15085 UInt imm32 = (INSN0(9,9) << 6) | (INSN0(7,3) << 1); 15086 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate); 15087 /* It's a conditional branch forward. */ 15088 IRTemp kond = newTemp(Ity_I1); 15089 assign( kond, binop(bOP ? Iop_CmpNE32 : Iop_CmpEQ32, 15090 getIRegT(rN), mkU32(0)) ); 15091 15092 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 15093 /* Looks like the nearest insn we can branch to is the one after 15094 next. That makes sense, as there's no point in being able to 15095 encode a conditional branch to the next instruction. */ 15096 UInt dst = (guest_R15_curr_instr_notENC + 4 + imm32) | 1; 15097 stmt(IRStmt_Exit( mkexpr(kond), 15098 Ijk_Boring, 15099 IRConst_U32(toUInt(dst)) )); 15100 DIP("cb%s r%u, 0x%x\n", bOP ? "nz" : "z", rN, dst - 1); 15101 goto decode_success; 15102 } 15103 15104 default: 15105 break; /* examine the next shortest prefix */ 15106 15107 } 15108 15109 15110 /* ================ 16-bit 15:9 cases ================ */ 15111 15112 switch (INSN0(15,9)) { 15113 15114 case BITS7(1,0,1,1,0,1,0): { 15115 /* ---------------- PUSH ---------------- */ 15116 /* This is a bit like STMxx, but way simpler. Complications we 15117 don't have to deal with: 15118 * SP being one of the transferred registers 15119 * direction (increment vs decrement) 15120 * before-vs-after-ness 15121 */ 15122 Int i, nRegs; 15123 UInt bitR = INSN0(8,8); 15124 UInt regList = INSN0(7,0); 15125 if (bitR) regList |= (1 << 14); 15126 15127 if (regList != 0) { 15128 /* Since we can't generate a guaranteed non-trapping IR 15129 sequence, (1) jump over the insn if it is gated false, and 15130 (2) back out the ITSTATE update. */ 15131 mk_skip_over_T16_if_cond_is_false(condT); 15132 condT = IRTemp_INVALID; 15133 put_ITSTATE(old_itstate); 15134 // now uncond 15135 15136 nRegs = 0; 15137 for (i = 0; i < 16; i++) { 15138 if ((regList & (1 << i)) != 0) 15139 nRegs++; 15140 } 15141 vassert(nRegs >= 1 && nRegs <= 8); 15142 15143 /* Move SP down first of all, so we're "covered". And don't 15144 mess with its alignment. */ 15145 IRTemp newSP = newTemp(Ity_I32); 15146 assign(newSP, binop(Iop_Sub32, getIRegT(13), mkU32(4 * nRegs))); 15147 putIRegT(13, mkexpr(newSP), IRTemp_INVALID); 15148 15149 /* Generate a transfer base address as a forced-aligned 15150 version of the final SP value. */ 15151 IRTemp base = newTemp(Ity_I32); 15152 assign(base, binop(Iop_And32, mkexpr(newSP), mkU32(~3))); 15153 15154 /* Now the transfers */ 15155 nRegs = 0; 15156 for (i = 0; i < 16; i++) { 15157 if ((regList & (1 << i)) != 0) { 15158 storeLE( binop(Iop_Add32, mkexpr(base), mkU32(4 * nRegs)), 15159 getIRegT(i) ); 15160 nRegs++; 15161 } 15162 } 15163 15164 /* Reinstate the ITSTATE update. */ 15165 put_ITSTATE(new_itstate); 15166 15167 DIP("push {%s0x%04x}\n", bitR ? "lr," : "", regList & 0xFF); 15168 goto decode_success; 15169 } 15170 break; 15171 } 15172 15173 case BITS7(1,0,1,1,1,1,0): { 15174 /* ---------------- POP ---------------- */ 15175 Int i, nRegs; 15176 UInt bitR = INSN0(8,8); 15177 UInt regList = INSN0(7,0); 15178 15179 if (regList != 0 || bitR) { 15180 /* Since we can't generate a guaranteed non-trapping IR 15181 sequence, (1) jump over the insn if it is gated false, and 15182 (2) back out the ITSTATE update. */ 15183 mk_skip_over_T16_if_cond_is_false(condT); 15184 condT = IRTemp_INVALID; 15185 put_ITSTATE(old_itstate); 15186 // now uncond 15187 15188 nRegs = 0; 15189 for (i = 0; i < 8; i++) { 15190 if ((regList & (1 << i)) != 0) 15191 nRegs++; 15192 } 15193 vassert(nRegs >= 0 && nRegs <= 7); 15194 vassert(bitR == 0 || bitR == 1); 15195 15196 IRTemp oldSP = newTemp(Ity_I32); 15197 assign(oldSP, getIRegT(13)); 15198 15199 /* Generate a transfer base address as a forced-aligned 15200 version of the original SP value. */ 15201 IRTemp base = newTemp(Ity_I32); 15202 assign(base, binop(Iop_And32, mkexpr(oldSP), mkU32(~3))); 15203 15204 /* Compute a new value for SP, but don't install it yet, so 15205 that we're "covered" until all the transfers are done. 15206 And don't mess with its alignment. */ 15207 IRTemp newSP = newTemp(Ity_I32); 15208 assign(newSP, binop(Iop_Add32, mkexpr(oldSP), 15209 mkU32(4 * (nRegs + bitR)))); 15210 15211 /* Now the transfers, not including PC */ 15212 nRegs = 0; 15213 for (i = 0; i < 8; i++) { 15214 if ((regList & (1 << i)) != 0) { 15215 putIRegT(i, loadLE( Ity_I32, 15216 binop(Iop_Add32, mkexpr(base), 15217 mkU32(4 * nRegs))), 15218 IRTemp_INVALID ); 15219 nRegs++; 15220 } 15221 } 15222 15223 IRTemp newPC = IRTemp_INVALID; 15224 if (bitR) { 15225 newPC = newTemp(Ity_I32); 15226 assign( newPC, loadLE( Ity_I32, 15227 binop(Iop_Add32, mkexpr(base), 15228 mkU32(4 * nRegs)))); 15229 } 15230 15231 /* Now we can safely install the new SP value */ 15232 putIRegT(13, mkexpr(newSP), IRTemp_INVALID); 15233 15234 /* Reinstate the ITSTATE update. */ 15235 put_ITSTATE(new_itstate); 15236 15237 /* now, do we also have to do a branch? If so, it turns out 15238 that the new PC value is encoded exactly as we need it to 15239 be -- with CPSR.T in the bottom bit. So we can simply use 15240 it as is, no need to mess with it. Note, therefore, this 15241 is an interworking return. */ 15242 if (bitR) { 15243 irsb->next = mkexpr(newPC); 15244 irsb->jumpkind = Ijk_Ret; 15245 dres.whatNext = Dis_StopHere; 15246 } 15247 15248 DIP("pop {%s0x%04x}\n", bitR ? "pc," : "", regList & 0xFF); 15249 goto decode_success; 15250 } 15251 break; 15252 } 15253 15254 case BITS7(0,0,0,1,1,1,0): /* ADDS */ 15255 case BITS7(0,0,0,1,1,1,1): { /* SUBS */ 15256 /* ---------------- ADDS Rd, Rn, #uimm3 ---------------- */ 15257 /* ---------------- SUBS Rd, Rn, #uimm3 ---------------- */ 15258 UInt uimm3 = INSN0(8,6); 15259 UInt rN = INSN0(5,3); 15260 UInt rD = INSN0(2,0); 15261 UInt isSub = INSN0(9,9); 15262 IRTemp argL = newTemp(Ity_I32); 15263 IRTemp argR = newTemp(Ity_I32); 15264 assign( argL, getIRegT(rN) ); 15265 assign( argR, mkU32(uimm3) ); 15266 putIRegT(rD, binop(isSub ? Iop_Sub32 : Iop_Add32, 15267 mkexpr(argL), mkexpr(argR)), 15268 condT); 15269 setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD, 15270 argL, argR, cond_AND_notInIT_T ); 15271 DIP("%s r%u, r%u, #%u\n", isSub ? "subs" : "adds", rD, rN, uimm3); 15272 goto decode_success; 15273 } 15274 15275 case BITS7(0,0,0,1,1,0,0): /* ADDS */ 15276 case BITS7(0,0,0,1,1,0,1): { /* SUBS */ 15277 /* ---------------- ADDS Rd, Rn, Rm ---------------- */ 15278 /* ---------------- SUBS Rd, Rn, Rm ---------------- */ 15279 UInt rM = INSN0(8,6); 15280 UInt rN = INSN0(5,3); 15281 UInt rD = INSN0(2,0); 15282 UInt isSub = INSN0(9,9); 15283 IRTemp argL = newTemp(Ity_I32); 15284 IRTemp argR = newTemp(Ity_I32); 15285 assign( argL, getIRegT(rN) ); 15286 assign( argR, getIRegT(rM) ); 15287 putIRegT( rD, binop(isSub ? Iop_Sub32 : Iop_Add32, 15288 mkexpr(argL), mkexpr(argR)), 15289 condT ); 15290 setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD, 15291 argL, argR, cond_AND_notInIT_T ); 15292 DIP("%s r%u, r%u, r%u\n", isSub ? "subs" : "adds", rD, rN, rM); 15293 goto decode_success; 15294 } 15295 15296 case BITS7(0,1,0,1,0,0,0): /* STR */ 15297 case BITS7(0,1,0,1,1,0,0): { /* LDR */ 15298 /* ------------- LDR Rd, [Rn, Rm] ------------- */ 15299 /* ------------- STR Rd, [Rn, Rm] ------------- */ 15300 /* LDR/STR Rd, [Rn + Rm] */ 15301 UInt rD = INSN0(2,0); 15302 UInt rN = INSN0(5,3); 15303 UInt rM = INSN0(8,6); 15304 UInt isLD = INSN0(11,11); 15305 15306 mk_skip_over_T16_if_cond_is_false(condT); 15307 condT = IRTemp_INVALID; 15308 // now uncond 15309 15310 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM)); 15311 put_ITSTATE(old_itstate); // backout 15312 if (isLD) { 15313 putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID); 15314 } else { 15315 storeLE(ea, getIRegT(rD)); 15316 } 15317 put_ITSTATE(new_itstate); // restore 15318 15319 DIP("%s r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM); 15320 goto decode_success; 15321 } 15322 15323 case BITS7(0,1,0,1,0,0,1): 15324 case BITS7(0,1,0,1,1,0,1): { 15325 /* ------------- LDRH Rd, [Rn, Rm] ------------- */ 15326 /* ------------- STRH Rd, [Rn, Rm] ------------- */ 15327 /* LDRH/STRH Rd, [Rn + Rm] */ 15328 UInt rD = INSN0(2,0); 15329 UInt rN = INSN0(5,3); 15330 UInt rM = INSN0(8,6); 15331 UInt isLD = INSN0(11,11); 15332 15333 mk_skip_over_T16_if_cond_is_false(condT); 15334 condT = IRTemp_INVALID; 15335 // now uncond 15336 15337 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM)); 15338 put_ITSTATE(old_itstate); // backout 15339 if (isLD) { 15340 putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)), 15341 IRTemp_INVALID); 15342 } else { 15343 storeLE( ea, unop(Iop_32to16, getIRegT(rD)) ); 15344 } 15345 put_ITSTATE(new_itstate); // restore 15346 15347 DIP("%sh r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM); 15348 goto decode_success; 15349 } 15350 15351 case BITS7(0,1,0,1,1,1,1): { 15352 /* ------------- LDRSH Rd, [Rn, Rm] ------------- */ 15353 /* LDRSH Rd, [Rn + Rm] */ 15354 UInt rD = INSN0(2,0); 15355 UInt rN = INSN0(5,3); 15356 UInt rM = INSN0(8,6); 15357 15358 mk_skip_over_T16_if_cond_is_false(condT); 15359 condT = IRTemp_INVALID; 15360 // now uncond 15361 15362 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM)); 15363 put_ITSTATE(old_itstate); // backout 15364 putIRegT(rD, unop(Iop_16Sto32, loadLE(Ity_I16, ea)), 15365 IRTemp_INVALID); 15366 put_ITSTATE(new_itstate); // restore 15367 15368 DIP("ldrsh r%u, [r%u, r%u]\n", rD, rN, rM); 15369 goto decode_success; 15370 } 15371 15372 case BITS7(0,1,0,1,0,1,1): { 15373 /* ------------- LDRSB Rd, [Rn, Rm] ------------- */ 15374 /* LDRSB Rd, [Rn + Rm] */ 15375 UInt rD = INSN0(2,0); 15376 UInt rN = INSN0(5,3); 15377 UInt rM = INSN0(8,6); 15378 15379 mk_skip_over_T16_if_cond_is_false(condT); 15380 condT = IRTemp_INVALID; 15381 // now uncond 15382 15383 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM)); 15384 put_ITSTATE(old_itstate); // backout 15385 putIRegT(rD, unop(Iop_8Sto32, loadLE(Ity_I8, ea)), 15386 IRTemp_INVALID); 15387 put_ITSTATE(new_itstate); // restore 15388 15389 DIP("ldrsb r%u, [r%u, r%u]\n", rD, rN, rM); 15390 goto decode_success; 15391 } 15392 15393 case BITS7(0,1,0,1,0,1,0): 15394 case BITS7(0,1,0,1,1,1,0): { 15395 /* ------------- LDRB Rd, [Rn, Rm] ------------- */ 15396 /* ------------- STRB Rd, [Rn, Rm] ------------- */ 15397 /* LDRB/STRB Rd, [Rn + Rm] */ 15398 UInt rD = INSN0(2,0); 15399 UInt rN = INSN0(5,3); 15400 UInt rM = INSN0(8,6); 15401 UInt isLD = INSN0(11,11); 15402 15403 mk_skip_over_T16_if_cond_is_false(condT); 15404 condT = IRTemp_INVALID; 15405 // now uncond 15406 15407 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM)); 15408 put_ITSTATE(old_itstate); // backout 15409 if (isLD) { 15410 putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)), 15411 IRTemp_INVALID); 15412 } else { 15413 storeLE( ea, unop(Iop_32to8, getIRegT(rD)) ); 15414 } 15415 put_ITSTATE(new_itstate); // restore 15416 15417 DIP("%sb r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM); 15418 goto decode_success; 15419 } 15420 15421 default: 15422 break; /* examine the next shortest prefix */ 15423 15424 } 15425 15426 15427 /* ================ 16-bit 15:11 cases ================ */ 15428 15429 switch (INSN0(15,11)) { 15430 15431 case BITS5(0,0,1,1,0): 15432 case BITS5(0,0,1,1,1): { 15433 /* ---------------- ADDS Rn, #uimm8 ---------------- */ 15434 /* ---------------- SUBS Rn, #uimm8 ---------------- */ 15435 UInt isSub = INSN0(11,11); 15436 UInt rN = INSN0(10,8); 15437 UInt uimm8 = INSN0(7,0); 15438 IRTemp argL = newTemp(Ity_I32); 15439 IRTemp argR = newTemp(Ity_I32); 15440 assign( argL, getIRegT(rN) ); 15441 assign( argR, mkU32(uimm8) ); 15442 putIRegT( rN, binop(isSub ? Iop_Sub32 : Iop_Add32, 15443 mkexpr(argL), mkexpr(argR)), condT ); 15444 setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD, 15445 argL, argR, cond_AND_notInIT_T ); 15446 DIP("%s r%u, #%u\n", isSub ? "subs" : "adds", rN, uimm8); 15447 goto decode_success; 15448 } 15449 15450 case BITS5(1,0,1,0,0): { 15451 /* ---------------- ADD rD, PC, #imm8 * 4 ---------------- */ 15452 /* a.k.a. ADR */ 15453 /* rD = align4(PC) + imm8 * 4 */ 15454 UInt rD = INSN0(10,8); 15455 UInt imm8 = INSN0(7,0); 15456 putIRegT(rD, binop(Iop_Add32, 15457 binop(Iop_And32, getIRegT(15), mkU32(~3U)), 15458 mkU32(imm8 * 4)), 15459 condT); 15460 DIP("add r%u, pc, #%u\n", rD, imm8 * 4); 15461 goto decode_success; 15462 } 15463 15464 case BITS5(1,0,1,0,1): { 15465 /* ---------------- ADD rD, SP, #imm8 * 4 ---------------- */ 15466 UInt rD = INSN0(10,8); 15467 UInt imm8 = INSN0(7,0); 15468 putIRegT(rD, binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4)), 15469 condT); 15470 DIP("add r%u, r13, #%u\n", rD, imm8 * 4); 15471 goto decode_success; 15472 } 15473 15474 case BITS5(0,0,1,0,1): { 15475 /* ---------------- CMP Rn, #uimm8 ---------------- */ 15476 UInt rN = INSN0(10,8); 15477 UInt uimm8 = INSN0(7,0); 15478 IRTemp argL = newTemp(Ity_I32); 15479 IRTemp argR = newTemp(Ity_I32); 15480 assign( argL, getIRegT(rN) ); 15481 assign( argR, mkU32(uimm8) ); 15482 /* Update flags regardless of whether in an IT block or not. */ 15483 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT ); 15484 DIP("cmp r%u, #%u\n", rN, uimm8); 15485 goto decode_success; 15486 } 15487 15488 case BITS5(0,0,1,0,0): { 15489 /* -------------- (T1) MOVS Rn, #uimm8 -------------- */ 15490 UInt rD = INSN0(10,8); 15491 UInt uimm8 = INSN0(7,0); 15492 IRTemp oldV = newTemp(Ity_I32); 15493 IRTemp oldC = newTemp(Ity_I32); 15494 IRTemp res = newTemp(Ity_I32); 15495 assign( oldV, mk_armg_calculate_flag_v() ); 15496 assign( oldC, mk_armg_calculate_flag_c() ); 15497 assign( res, mkU32(uimm8) ); 15498 putIRegT(rD, mkexpr(res), condT); 15499 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 15500 cond_AND_notInIT_T ); 15501 DIP("movs r%u, #%u\n", rD, uimm8); 15502 goto decode_success; 15503 } 15504 15505 case BITS5(0,1,0,0,1): { 15506 /* ------------- LDR Rd, [PC, #imm8 * 4] ------------- */ 15507 /* LDR Rd, [align4(PC) + imm8 * 4] */ 15508 UInt rD = INSN0(10,8); 15509 UInt imm8 = INSN0(7,0); 15510 IRTemp ea = newTemp(Ity_I32); 15511 15512 mk_skip_over_T16_if_cond_is_false(condT); 15513 condT = IRTemp_INVALID; 15514 // now uncond 15515 15516 assign(ea, binop(Iop_Add32, 15517 binop(Iop_And32, getIRegT(15), mkU32(~3U)), 15518 mkU32(imm8 * 4))); 15519 put_ITSTATE(old_itstate); // backout 15520 putIRegT(rD, loadLE(Ity_I32, mkexpr(ea)), 15521 IRTemp_INVALID); 15522 put_ITSTATE(new_itstate); // restore 15523 15524 DIP("ldr r%u, [pc, #%u]\n", rD, imm8 * 4); 15525 goto decode_success; 15526 } 15527 15528 case BITS5(0,1,1,0,0): /* STR */ 15529 case BITS5(0,1,1,0,1): { /* LDR */ 15530 /* ------------- LDR Rd, [Rn, #imm5 * 4] ------------- */ 15531 /* ------------- STR Rd, [Rn, #imm5 * 4] ------------- */ 15532 /* LDR/STR Rd, [Rn + imm5 * 4] */ 15533 UInt rD = INSN0(2,0); 15534 UInt rN = INSN0(5,3); 15535 UInt imm5 = INSN0(10,6); 15536 UInt isLD = INSN0(11,11); 15537 15538 mk_skip_over_T16_if_cond_is_false(condT); 15539 condT = IRTemp_INVALID; 15540 // now uncond 15541 15542 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 4)); 15543 put_ITSTATE(old_itstate); // backout 15544 if (isLD) { 15545 putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID); 15546 } else { 15547 storeLE( ea, getIRegT(rD) ); 15548 } 15549 put_ITSTATE(new_itstate); // restore 15550 15551 DIP("%s r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 4); 15552 goto decode_success; 15553 } 15554 15555 case BITS5(1,0,0,0,0): /* STRH */ 15556 case BITS5(1,0,0,0,1): { /* LDRH */ 15557 /* ------------- LDRH Rd, [Rn, #imm5 * 2] ------------- */ 15558 /* ------------- STRH Rd, [Rn, #imm5 * 2] ------------- */ 15559 /* LDRH/STRH Rd, [Rn + imm5 * 2] */ 15560 UInt rD = INSN0(2,0); 15561 UInt rN = INSN0(5,3); 15562 UInt imm5 = INSN0(10,6); 15563 UInt isLD = INSN0(11,11); 15564 15565 mk_skip_over_T16_if_cond_is_false(condT); 15566 condT = IRTemp_INVALID; 15567 // now uncond 15568 15569 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 2)); 15570 put_ITSTATE(old_itstate); // backout 15571 if (isLD) { 15572 putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)), 15573 IRTemp_INVALID); 15574 } else { 15575 storeLE( ea, unop(Iop_32to16, getIRegT(rD)) ); 15576 } 15577 put_ITSTATE(new_itstate); // restore 15578 15579 DIP("%sh r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 2); 15580 goto decode_success; 15581 } 15582 15583 case BITS5(0,1,1,1,0): /* STRB */ 15584 case BITS5(0,1,1,1,1): { /* LDRB */ 15585 /* ------------- LDRB Rd, [Rn, #imm5] ------------- */ 15586 /* ------------- STRB Rd, [Rn, #imm5] ------------- */ 15587 /* LDRB/STRB Rd, [Rn + imm5] */ 15588 UInt rD = INSN0(2,0); 15589 UInt rN = INSN0(5,3); 15590 UInt imm5 = INSN0(10,6); 15591 UInt isLD = INSN0(11,11); 15592 15593 mk_skip_over_T16_if_cond_is_false(condT); 15594 condT = IRTemp_INVALID; 15595 // now uncond 15596 15597 IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5)); 15598 put_ITSTATE(old_itstate); // backout 15599 if (isLD) { 15600 putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)), 15601 IRTemp_INVALID); 15602 } else { 15603 storeLE( ea, unop(Iop_32to8, getIRegT(rD)) ); 15604 } 15605 put_ITSTATE(new_itstate); // restore 15606 15607 DIP("%sb r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5); 15608 goto decode_success; 15609 } 15610 15611 case BITS5(1,0,0,1,0): /* STR */ 15612 case BITS5(1,0,0,1,1): { /* LDR */ 15613 /* ------------- LDR Rd, [SP, #imm8 * 4] ------------- */ 15614 /* ------------- STR Rd, [SP, #imm8 * 4] ------------- */ 15615 /* LDR/STR Rd, [SP + imm8 * 4] */ 15616 UInt rD = INSN0(10,8); 15617 UInt imm8 = INSN0(7,0); 15618 UInt isLD = INSN0(11,11); 15619 15620 mk_skip_over_T16_if_cond_is_false(condT); 15621 condT = IRTemp_INVALID; 15622 // now uncond 15623 15624 IRExpr* ea = binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4)); 15625 put_ITSTATE(old_itstate); // backout 15626 if (isLD) { 15627 putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID); 15628 } else { 15629 storeLE(ea, getIRegT(rD)); 15630 } 15631 put_ITSTATE(new_itstate); // restore 15632 15633 DIP("%s r%u, [sp, #%u]\n", isLD ? "ldr" : "str", rD, imm8 * 4); 15634 goto decode_success; 15635 } 15636 15637 case BITS5(1,1,0,0,1): { 15638 /* ------------- LDMIA Rn!, {reglist} ------------- */ 15639 Int i, nRegs = 0; 15640 UInt rN = INSN0(10,8); 15641 UInt list = INSN0(7,0); 15642 /* Empty lists aren't allowed. */ 15643 if (list != 0) { 15644 mk_skip_over_T16_if_cond_is_false(condT); 15645 condT = IRTemp_INVALID; 15646 put_ITSTATE(old_itstate); 15647 // now uncond 15648 15649 IRTemp oldRn = newTemp(Ity_I32); 15650 IRTemp base = newTemp(Ity_I32); 15651 assign(oldRn, getIRegT(rN)); 15652 assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U))); 15653 for (i = 0; i < 8; i++) { 15654 if (0 == (list & (1 << i))) 15655 continue; 15656 nRegs++; 15657 putIRegT( 15658 i, loadLE(Ity_I32, 15659 binop(Iop_Add32, mkexpr(base), 15660 mkU32(nRegs * 4 - 4))), 15661 IRTemp_INVALID 15662 ); 15663 } 15664 /* Only do the writeback for rN if it isn't in the list of 15665 registers to be transferred. */ 15666 if (0 == (list & (1 << rN))) { 15667 putIRegT(rN, 15668 binop(Iop_Add32, mkexpr(oldRn), 15669 mkU32(nRegs * 4)), 15670 IRTemp_INVALID 15671 ); 15672 } 15673 15674 /* Reinstate the ITSTATE update. */ 15675 put_ITSTATE(new_itstate); 15676 15677 DIP("ldmia r%u!, {0x%04x}\n", rN, list); 15678 goto decode_success; 15679 } 15680 break; 15681 } 15682 15683 case BITS5(1,1,0,0,0): { 15684 /* ------------- STMIA Rn!, {reglist} ------------- */ 15685 Int i, nRegs = 0; 15686 UInt rN = INSN0(10,8); 15687 UInt list = INSN0(7,0); 15688 /* Empty lists aren't allowed. Also, if rN is in the list then 15689 it must be the lowest numbered register in the list. */ 15690 Bool valid = list != 0; 15691 if (valid && 0 != (list & (1 << rN))) { 15692 for (i = 0; i < rN; i++) { 15693 if (0 != (list & (1 << i))) 15694 valid = False; 15695 } 15696 } 15697 if (valid) { 15698 mk_skip_over_T16_if_cond_is_false(condT); 15699 condT = IRTemp_INVALID; 15700 put_ITSTATE(old_itstate); 15701 // now uncond 15702 15703 IRTemp oldRn = newTemp(Ity_I32); 15704 IRTemp base = newTemp(Ity_I32); 15705 assign(oldRn, getIRegT(rN)); 15706 assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U))); 15707 for (i = 0; i < 8; i++) { 15708 if (0 == (list & (1 << i))) 15709 continue; 15710 nRegs++; 15711 storeLE( binop(Iop_Add32, mkexpr(base), mkU32(nRegs * 4 - 4)), 15712 getIRegT(i) ); 15713 } 15714 /* Always do the writeback. */ 15715 putIRegT(rN, 15716 binop(Iop_Add32, mkexpr(oldRn), 15717 mkU32(nRegs * 4)), 15718 IRTemp_INVALID); 15719 15720 /* Reinstate the ITSTATE update. */ 15721 put_ITSTATE(new_itstate); 15722 15723 DIP("stmia r%u!, {0x%04x}\n", rN, list); 15724 goto decode_success; 15725 } 15726 break; 15727 } 15728 15729 case BITS5(0,0,0,0,0): /* LSLS */ 15730 case BITS5(0,0,0,0,1): /* LSRS */ 15731 case BITS5(0,0,0,1,0): { /* ASRS */ 15732 /* ---------------- LSLS Rd, Rm, #imm5 ---------------- */ 15733 /* ---------------- LSRS Rd, Rm, #imm5 ---------------- */ 15734 /* ---------------- ASRS Rd, Rm, #imm5 ---------------- */ 15735 UInt rD = INSN0(2,0); 15736 UInt rM = INSN0(5,3); 15737 UInt imm5 = INSN0(10,6); 15738 IRTemp res = newTemp(Ity_I32); 15739 IRTemp resC = newTemp(Ity_I32); 15740 IRTemp rMt = newTemp(Ity_I32); 15741 IRTemp oldV = newTemp(Ity_I32); 15742 HChar* wot = "???"; 15743 assign(rMt, getIRegT(rM)); 15744 assign(oldV, mk_armg_calculate_flag_v()); 15745 /* Looks like INSN0(12,11) are the standard 'how' encoding. 15746 Could compactify if the ROR case later appears. */ 15747 switch (INSN0(15,11)) { 15748 case BITS5(0,0,0,0,0): 15749 compute_result_and_C_after_LSL_by_imm5( 15750 dis_buf, &res, &resC, rMt, imm5, rM 15751 ); 15752 wot = "lsl"; 15753 break; 15754 case BITS5(0,0,0,0,1): 15755 compute_result_and_C_after_LSR_by_imm5( 15756 dis_buf, &res, &resC, rMt, imm5, rM 15757 ); 15758 wot = "lsr"; 15759 break; 15760 case BITS5(0,0,0,1,0): 15761 compute_result_and_C_after_ASR_by_imm5( 15762 dis_buf, &res, &resC, rMt, imm5, rM 15763 ); 15764 wot = "asr"; 15765 break; 15766 default: 15767 /*NOTREACHED*/vassert(0); 15768 } 15769 // not safe to read guest state after this point 15770 putIRegT(rD, mkexpr(res), condT); 15771 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV, 15772 cond_AND_notInIT_T ); 15773 /* ignore buf and roll our own output */ 15774 DIP("%ss r%u, r%u, #%u\n", wot, rD, rM, imm5); 15775 goto decode_success; 15776 } 15777 15778 case BITS5(1,1,1,0,0): { 15779 /* ---------------- B #simm11 ---------------- */ 15780 Int simm11 = INSN0(10,0); 15781 simm11 = (simm11 << 21) >> 20; 15782 UInt dst = simm11 + guest_R15_curr_instr_notENC + 4; 15783 /* Only allowed outside or last-in IT block; SIGILL if not so. */ 15784 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 15785 // and skip this insn if not selected; being cleverer is too 15786 // difficult 15787 mk_skip_over_T16_if_cond_is_false(condT); 15788 condT = IRTemp_INVALID; 15789 // now uncond 15790 irsb->next = mkU32( dst | 1 /*CPSR.T*/ ); 15791 irsb->jumpkind = Ijk_Boring; 15792 dres.whatNext = Dis_StopHere; 15793 DIP("b 0x%x\n", dst); 15794 goto decode_success; 15795 } 15796 15797 default: 15798 break; /* examine the next shortest prefix */ 15799 15800 } 15801 15802 15803 /* ================ 16-bit 15:12 cases ================ */ 15804 15805 switch (INSN0(15,12)) { 15806 15807 case BITS4(1,1,0,1): { 15808 /* ---------------- Bcond #simm8 ---------------- */ 15809 UInt cond = INSN0(11,8); 15810 Int simm8 = INSN0(7,0); 15811 simm8 = (simm8 << 24) >> 23; 15812 UInt dst = simm8 + guest_R15_curr_instr_notENC + 4; 15813 if (cond != ARMCondAL && cond != ARMCondNV) { 15814 /* Not allowed in an IT block; SIGILL if so. */ 15815 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate); 15816 15817 IRTemp kondT = newTemp(Ity_I32); 15818 assign( kondT, mk_armg_calculate_condition(cond) ); 15819 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)), 15820 Ijk_Boring, 15821 IRConst_U32(dst | 1/*CPSR.T*/) )); 15822 irsb->next = mkU32( (guest_R15_curr_instr_notENC + 2) 15823 | 1 /*CPSR.T*/ ); 15824 irsb->jumpkind = Ijk_Boring; 15825 dres.whatNext = Dis_StopHere; 15826 DIP("b%s 0x%x\n", nCC(cond), dst); 15827 goto decode_success; 15828 } 15829 break; 15830 } 15831 15832 default: 15833 break; /* hmm, nothing matched */ 15834 15835 } 15836 15837 /* ================ 16-bit misc cases ================ */ 15838 15839 /* ------ NOP ------ */ 15840 if (INSN0(15,0) == 0xBF00) { 15841 DIP("nop"); 15842 goto decode_success; 15843 } 15844 15845 /* ----------------------------------------------------------- */ 15846 /* -- -- */ 15847 /* -- Thumb 32-bit integer instructions -- */ 15848 /* -- -- */ 15849 /* ----------------------------------------------------------- */ 15850 15851 # define INSN1(_bMax,_bMin) SLICE_UInt(((UInt)insn1), (_bMax), (_bMin)) 15852 15853 /* second 16 bits of the instruction, if any */ 15854 UShort insn1 = getUShortLittleEndianly( guest_instr+2 ); 15855 15856 anOp = Iop_INVALID; /* paranoia */ 15857 anOpNm = NULL; /* paranoia */ 15858 15859 /* Change result defaults to suit 32-bit insns. */ 15860 vassert(dres.whatNext == Dis_Continue); 15861 vassert(dres.len == 2); 15862 vassert(dres.continueAt == 0); 15863 dres.len = 4; 15864 15865 /* ---------------- BL/BLX simm26 ---------------- */ 15866 if (BITS5(1,1,1,1,0) == INSN0(15,11) && BITS2(1,1) == INSN1(15,14)) { 15867 UInt isBL = INSN1(12,12); 15868 UInt bS = INSN0(10,10); 15869 UInt bJ1 = INSN1(13,13); 15870 UInt bJ2 = INSN1(11,11); 15871 UInt bI1 = 1 ^ (bJ1 ^ bS); 15872 UInt bI2 = 1 ^ (bJ2 ^ bS); 15873 Int simm25 15874 = (bS << (1 + 1 + 10 + 11 + 1)) 15875 | (bI1 << (1 + 10 + 11 + 1)) 15876 | (bI2 << (10 + 11 + 1)) 15877 | (INSN0(9,0) << (11 + 1)) 15878 | (INSN1(10,0) << 1); 15879 simm25 = (simm25 << 7) >> 7; 15880 15881 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 15882 UInt dst = simm25 + guest_R15_curr_instr_notENC + 4; 15883 15884 /* One further validity case to check: in the case of BLX 15885 (not-BL), that insn1[0] must be zero. */ 15886 Bool valid = True; 15887 if (isBL == 0 && INSN1(0,0) == 1) valid = False; 15888 if (valid) { 15889 /* Only allowed outside or last-in IT block; SIGILL if not so. */ 15890 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 15891 // and skip this insn if not selected; being cleverer is too 15892 // difficult 15893 mk_skip_over_T32_if_cond_is_false(condT); 15894 condT = IRTemp_INVALID; 15895 // now uncond 15896 15897 /* We're returning to Thumb code, hence "| 1" */ 15898 putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 4) | 1 ), 15899 IRTemp_INVALID); 15900 if (isBL) { 15901 /* BL: unconditional T -> T call */ 15902 /* we're calling Thumb code, hence "| 1" */ 15903 irsb->next = mkU32( dst | 1 ); 15904 DIP("bl 0x%x (stay in Thumb mode)\n", dst); 15905 } else { 15906 /* BLX: unconditional T -> A call */ 15907 /* we're calling ARM code, hence "& 3" to align to a 15908 valid ARM insn address */ 15909 irsb->next = mkU32( dst & ~3 ); 15910 DIP("blx 0x%x (switch to ARM mode)\n", dst & ~3); 15911 } 15912 irsb->jumpkind = Ijk_Call; 15913 dres.whatNext = Dis_StopHere; 15914 goto decode_success; 15915 } 15916 } 15917 15918 /* ---------------- {LD,ST}M{IA,DB} ---------------- */ 15919 if (0x3a2 == INSN0(15,6) // {LD,ST}MIA 15920 || 0x3a4 == INSN0(15,6)) { // {LD,ST}MDB 15921 UInt bW = INSN0(5,5); /* writeback Rn ? */ 15922 UInt bL = INSN0(4,4); 15923 UInt rN = INSN0(3,0); 15924 UInt bP = INSN1(15,15); /* reglist entry for r15 */ 15925 UInt bM = INSN1(14,14); /* reglist entry for r14 */ 15926 UInt rLmost = INSN1(12,0); /* reglist entry for r0 .. 12 */ 15927 UInt rL13 = INSN1(13,13); /* must be zero */ 15928 UInt regList = 0; 15929 Bool valid = True; 15930 15931 UInt bINC = 1; 15932 UInt bBEFORE = 0; 15933 if (INSN0(15,6) == 0x3a4) { 15934 bINC = 0; 15935 bBEFORE = 1; 15936 } 15937 15938 /* detect statically invalid cases, and construct the final 15939 reglist */ 15940 if (rL13 == 1) 15941 valid = False; 15942 15943 if (bL == 1) { 15944 regList = (bP << 15) | (bM << 14) | rLmost; 15945 if (rN == 15) valid = False; 15946 if (popcount32(regList) < 2) valid = False; 15947 if (bP == 1 && bM == 1) valid = False; 15948 if (bW == 1 && (regList & (1<<rN))) valid = False; 15949 } else { 15950 regList = (bM << 14) | rLmost; 15951 if (bP == 1) valid = False; 15952 if (rN == 15) valid = False; 15953 if (popcount32(regList) < 2) valid = False; 15954 if (bW == 1 && (regList & (1<<rN))) valid = False; 15955 if (regList & (1<<rN)) { 15956 UInt i; 15957 /* if Rn is in the list, then it must be the 15958 lowest numbered entry */ 15959 for (i = 0; i < rN; i++) { 15960 if (regList & (1<<i)) 15961 valid = False; 15962 } 15963 } 15964 } 15965 15966 if (valid) { 15967 if (bL == 1 && bP == 1) { 15968 // We'll be writing the PC. Hence: 15969 /* Only allowed outside or last-in IT block; SIGILL if not so. */ 15970 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 15971 } 15972 15973 /* Go uncond: */ 15974 mk_skip_over_T32_if_cond_is_false(condT); 15975 condT = IRTemp_INVALID; 15976 // now uncond 15977 15978 /* Generate the IR. This might generate a write to R15, */ 15979 mk_ldm_stm(False/*!arm*/, rN, bINC, bBEFORE, bW, bL, regList); 15980 15981 if (bL == 1 && (regList & (1<<15))) { 15982 // If we wrote to R15, we have an interworking return to 15983 // deal with. 15984 irsb->next = llGetIReg(15); 15985 irsb->jumpkind = Ijk_Ret; 15986 dres.whatNext = Dis_StopHere; 15987 } 15988 15989 DIP("%sm%c%c r%u%s, {0x%04x}\n", 15990 bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a', 15991 rN, bW ? "!" : "", regList); 15992 15993 goto decode_success; 15994 } 15995 } 15996 15997 /* -------------- (T3) ADD{S}.W Rd, Rn, #constT -------------- */ 15998 if (INSN0(15,11) == BITS5(1,1,1,1,0) 15999 && INSN0(9,5) == BITS5(0,1,0,0,0) 16000 && INSN1(15,15) == 0) { 16001 UInt bS = INSN0(4,4); 16002 UInt rN = INSN0(3,0); 16003 UInt rD = INSN1(11,8); 16004 Bool valid = !isBadRegT(rN) && !isBadRegT(rD); 16005 /* but allow "add.w reg, sp, #constT" */ 16006 if (!valid && rN == 13) 16007 valid = True; 16008 if (valid) { 16009 IRTemp argL = newTemp(Ity_I32); 16010 IRTemp argR = newTemp(Ity_I32); 16011 IRTemp res = newTemp(Ity_I32); 16012 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1); 16013 assign(argL, getIRegT(rN)); 16014 assign(argR, mkU32(imm32)); 16015 assign(res, binop(Iop_Add32, mkexpr(argL), mkexpr(argR))); 16016 putIRegT(rD, mkexpr(res), condT); 16017 if (bS == 1) 16018 setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT ); 16019 DIP("add%s.w r%u, r%u, #%u\n", 16020 bS == 1 ? "s" : "", rD, rN, imm32); 16021 goto decode_success; 16022 } 16023 } 16024 16025 /* ---------------- (T4) ADDW Rd, Rn, #imm12 -------------- */ 16026 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16027 && INSN0(9,4) == BITS6(1,0,0,0,0,0) 16028 && INSN1(15,15) == 0) { 16029 UInt rN = INSN0(3,0); 16030 UInt rD = INSN1(11,8); 16031 Bool valid = !isBadRegT(rN) && !isBadRegT(rD); 16032 /* but allow "addw reg, sp, #imm12" */ 16033 if (!valid && rN == 13) 16034 valid = True; 16035 if (valid) { 16036 IRTemp argL = newTemp(Ity_I32); 16037 IRTemp argR = newTemp(Ity_I32); 16038 IRTemp res = newTemp(Ity_I32); 16039 UInt imm1 = INSN0(10,10); 16040 UInt imm3 = INSN1(14,12); 16041 UInt imm8 = INSN1(7,0); 16042 UInt imm12 = (imm1 << 11) | (imm3 << 8) | imm8; 16043 assign(argL, getIRegT(rN)); 16044 assign(argR, mkU32(imm12)); 16045 assign(res, binop(Iop_Add32, mkexpr(argL), mkexpr(argR))); 16046 putIRegT(rD, mkexpr(res), condT); 16047 DIP("addw r%u, r%u, #%u\n", rD, rN, imm12); 16048 goto decode_success; 16049 } 16050 } 16051 16052 /* ---------------- (T2) CMP.W Rn, #constT ---------------- */ 16053 /* ---------------- (T2) CMN.W Rn, #constT ---------------- */ 16054 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16055 && ( INSN0(9,4) == BITS6(0,1,1,0,1,1) // CMP 16056 || INSN0(9,4) == BITS6(0,1,0,0,0,1)) // CMN 16057 && INSN1(15,15) == 0 16058 && INSN1(11,8) == BITS4(1,1,1,1)) { 16059 UInt rN = INSN0(3,0); 16060 if (rN != 15) { 16061 IRTemp argL = newTemp(Ity_I32); 16062 IRTemp argR = newTemp(Ity_I32); 16063 Bool isCMN = INSN0(9,4) == BITS6(0,1,0,0,0,1); 16064 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1); 16065 assign(argL, getIRegT(rN)); 16066 assign(argR, mkU32(imm32)); 16067 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB, 16068 argL, argR, condT ); 16069 DIP("%s.w r%u, #%u\n", isCMN ? "cmn" : "cmp", rN, imm32); 16070 goto decode_success; 16071 } 16072 } 16073 16074 /* -------------- (T1) TST.W Rn, #constT -------------- */ 16075 /* -------------- (T1) TEQ.W Rn, #constT -------------- */ 16076 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16077 && ( INSN0(9,4) == BITS6(0,0,0,0,0,1) // TST 16078 || INSN0(9,4) == BITS6(0,0,1,0,0,1)) // TEQ 16079 && INSN1(15,15) == 0 16080 && INSN1(11,8) == BITS4(1,1,1,1)) { 16081 UInt rN = INSN0(3,0); 16082 if (!isBadRegT(rN)) { // yes, really, it's inconsistent with CMP.W 16083 Bool isTST = INSN0(9,4) == BITS6(0,0,0,0,0,1); 16084 IRTemp argL = newTemp(Ity_I32); 16085 IRTemp argR = newTemp(Ity_I32); 16086 IRTemp res = newTemp(Ity_I32); 16087 IRTemp oldV = newTemp(Ity_I32); 16088 IRTemp oldC = newTemp(Ity_I32); 16089 Bool updC = False; 16090 UInt imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1); 16091 assign(argL, getIRegT(rN)); 16092 assign(argR, mkU32(imm32)); 16093 assign(res, binop(isTST ? Iop_And32 : Iop_Xor32, 16094 mkexpr(argL), mkexpr(argR))); 16095 assign( oldV, mk_armg_calculate_flag_v() ); 16096 assign( oldC, updC 16097 ? mkU32((imm32 >> 31) & 1) 16098 : mk_armg_calculate_flag_c() ); 16099 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT ); 16100 DIP("%s.w r%u, #%u\n", isTST ? "tst" : "teq", rN, imm32); 16101 goto decode_success; 16102 } 16103 } 16104 16105 /* -------------- (T3) SUB{S}.W Rd, Rn, #constT -------------- */ 16106 /* -------------- (T3) RSB{S}.W Rd, Rn, #constT -------------- */ 16107 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16108 && (INSN0(9,5) == BITS5(0,1,1,0,1) // SUB 16109 || INSN0(9,5) == BITS5(0,1,1,1,0)) // RSB 16110 && INSN1(15,15) == 0) { 16111 Bool isRSB = INSN0(9,5) == BITS5(0,1,1,1,0); 16112 UInt bS = INSN0(4,4); 16113 UInt rN = INSN0(3,0); 16114 UInt rD = INSN1(11,8); 16115 Bool valid = !isBadRegT(rN) && !isBadRegT(rD); 16116 /* but allow "sub.w sp, sp, #constT" */ 16117 if (!valid && !isRSB && rN == 13 && rD == 13) 16118 valid = True; 16119 if (valid) { 16120 IRTemp argL = newTemp(Ity_I32); 16121 IRTemp argR = newTemp(Ity_I32); 16122 IRTemp res = newTemp(Ity_I32); 16123 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1); 16124 assign(argL, getIRegT(rN)); 16125 assign(argR, mkU32(imm32)); 16126 assign(res, isRSB 16127 ? binop(Iop_Sub32, mkexpr(argR), mkexpr(argL)) 16128 : binop(Iop_Sub32, mkexpr(argL), mkexpr(argR))); 16129 putIRegT(rD, mkexpr(res), condT); 16130 if (bS == 1) { 16131 if (isRSB) 16132 setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT ); 16133 else 16134 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT ); 16135 } 16136 DIP("%s%s.w r%u, r%u, #%u\n", 16137 isRSB ? "rsb" : "sub", bS == 1 ? "s" : "", rD, rN, imm32); 16138 goto decode_success; 16139 } 16140 } 16141 16142 /* -------------- (T4) SUBW Rd, Rn, #imm12 ------------------- */ 16143 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16144 && INSN0(9,4) == BITS6(1,0,1,0,1,0) 16145 && INSN1(15,15) == 0) { 16146 UInt rN = INSN0(3,0); 16147 UInt rD = INSN1(11,8); 16148 Bool valid = !isBadRegT(rN) && !isBadRegT(rD); 16149 if (!valid && rN == 13 && rD == 13) 16150 valid = True; 16151 if (valid) { 16152 IRTemp argL = newTemp(Ity_I32); 16153 IRTemp argR = newTemp(Ity_I32); 16154 IRTemp res = newTemp(Ity_I32); 16155 UInt imm12 = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0); 16156 assign(argL, getIRegT(rN)); 16157 assign(argR, mkU32(imm12)); 16158 assign(res, binop(Iop_Sub32, mkexpr(argL), mkexpr(argR))); 16159 putIRegT(rD, mkexpr(res), condT); 16160 DIP("subw r%u, r%u, #%u\n", rD, rN, imm12); 16161 goto decode_success; 16162 } 16163 } 16164 16165 /* -------------- (T2) SUB{S}.W Rd, SP, #constT ------------------- */ 16166 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16167 && INSN0(9,5) == BITS5(0,1,1,0,1) 16168 && INSN0(3,0) == BITS4(1,1,0,1) 16169 && INSN1(15,15) == 0) { 16170 UInt rN = 13; // SP 16171 UInt rD = INSN1(11,8); 16172 UInt bS = INSN0(4,4); 16173 Bool valid = !isBadRegT(rD); 16174 if (valid) { 16175 IRTemp argL = newTemp(Ity_I32); 16176 IRTemp argR = newTemp(Ity_I32); 16177 IRTemp res = newTemp(Ity_I32); 16178 UInt imm12 = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0); 16179 assign(argL, getIRegT(rN)); 16180 assign(argR, mkU32(imm12)); 16181 assign(res, binop(Iop_Sub32, mkexpr(argL), mkexpr(argR))); 16182 putIRegT(rD, mkexpr(res), condT); 16183 if (bS == 1) { 16184 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT ); 16185 } 16186 DIP("sub%s.w r%u, sp, #%u\n", 16187 bS == 1 ? "s" : "", rD, imm12); 16188 goto decode_success; 16189 } 16190 } 16191 16192 /* -------------- (T1) ADC{S}.W Rd, Rn, #constT -------------- */ 16193 /* -------------- (T1) SBC{S}.W Rd, Rn, #constT -------------- */ 16194 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16195 && ( INSN0(9,5) == BITS5(0,1,0,1,0) // ADC 16196 || INSN0(9,5) == BITS5(0,1,0,1,1)) // SBC 16197 && INSN1(15,15) == 0) { 16198 /* ADC: Rd = Rn + constT + oldC */ 16199 /* SBC: Rd = Rn - constT - (oldC ^ 1) */ 16200 UInt bS = INSN0(4,4); 16201 UInt rN = INSN0(3,0); 16202 UInt rD = INSN1(11,8); 16203 if (!isBadRegT(rN) && !isBadRegT(rD)) { 16204 IRTemp argL = newTemp(Ity_I32); 16205 IRTemp argR = newTemp(Ity_I32); 16206 IRTemp res = newTemp(Ity_I32); 16207 IRTemp oldC = newTemp(Ity_I32); 16208 UInt imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1); 16209 assign(argL, getIRegT(rN)); 16210 assign(argR, mkU32(imm32)); 16211 assign(oldC, mk_armg_calculate_flag_c() ); 16212 HChar* nm = "???"; 16213 switch (INSN0(9,5)) { 16214 case BITS5(0,1,0,1,0): // ADC 16215 nm = "adc"; 16216 assign(res, 16217 binop(Iop_Add32, 16218 binop(Iop_Add32, mkexpr(argL), mkexpr(argR)), 16219 mkexpr(oldC) )); 16220 putIRegT(rD, mkexpr(res), condT); 16221 if (bS) 16222 setFlags_D1_D2_ND( ARMG_CC_OP_ADC, 16223 argL, argR, oldC, condT ); 16224 break; 16225 case BITS5(0,1,0,1,1): // SBC 16226 nm = "sbc"; 16227 assign(res, 16228 binop(Iop_Sub32, 16229 binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)), 16230 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) )); 16231 putIRegT(rD, mkexpr(res), condT); 16232 if (bS) 16233 setFlags_D1_D2_ND( ARMG_CC_OP_SBB, 16234 argL, argR, oldC, condT ); 16235 break; 16236 default: 16237 vassert(0); 16238 } 16239 DIP("%s%s.w r%u, r%u, #%u\n", 16240 nm, bS == 1 ? "s" : "", rD, rN, imm32); 16241 goto decode_success; 16242 } 16243 } 16244 16245 /* -------------- (T1) ORR{S}.W Rd, Rn, #constT -------------- */ 16246 /* -------------- (T1) AND{S}.W Rd, Rn, #constT -------------- */ 16247 /* -------------- (T1) BIC{S}.W Rd, Rn, #constT -------------- */ 16248 /* -------------- (T1) EOR{S}.W Rd, Rn, #constT -------------- */ 16249 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16250 && ( INSN0(9,5) == BITS5(0,0,0,1,0) // ORR 16251 || INSN0(9,5) == BITS5(0,0,0,0,0) // AND 16252 || INSN0(9,5) == BITS5(0,0,0,0,1) // BIC 16253 || INSN0(9,5) == BITS5(0,0,1,0,0) // EOR 16254 || INSN0(9,5) == BITS5(0,0,0,1,1)) // ORN 16255 && INSN1(15,15) == 0) { 16256 UInt bS = INSN0(4,4); 16257 UInt rN = INSN0(3,0); 16258 UInt rD = INSN1(11,8); 16259 if (!isBadRegT(rN) && !isBadRegT(rD)) { 16260 Bool notArgR = False; 16261 IROp op = Iop_INVALID; 16262 HChar* nm = "???"; 16263 switch (INSN0(9,5)) { 16264 case BITS5(0,0,0,1,0): op = Iop_Or32; nm = "orr"; break; 16265 case BITS5(0,0,0,0,0): op = Iop_And32; nm = "and"; break; 16266 case BITS5(0,0,0,0,1): op = Iop_And32; nm = "bic"; 16267 notArgR = True; break; 16268 case BITS5(0,0,1,0,0): op = Iop_Xor32; nm = "eor"; break; 16269 case BITS5(0,0,0,1,1): op = Iop_Or32; nm = "orn"; 16270 notArgR = True; break; 16271 default: vassert(0); 16272 } 16273 IRTemp argL = newTemp(Ity_I32); 16274 IRTemp argR = newTemp(Ity_I32); 16275 IRTemp res = newTemp(Ity_I32); 16276 Bool updC = False; 16277 UInt imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1); 16278 assign(argL, getIRegT(rN)); 16279 assign(argR, mkU32(notArgR ? ~imm32 : imm32)); 16280 assign(res, binop(op, mkexpr(argL), mkexpr(argR))); 16281 putIRegT(rD, mkexpr(res), condT); 16282 if (bS) { 16283 IRTemp oldV = newTemp(Ity_I32); 16284 IRTemp oldC = newTemp(Ity_I32); 16285 assign( oldV, mk_armg_calculate_flag_v() ); 16286 assign( oldC, updC 16287 ? mkU32((imm32 >> 31) & 1) 16288 : mk_armg_calculate_flag_c() ); 16289 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 16290 condT ); 16291 } 16292 DIP("%s%s.w r%u, r%u, #%u\n", 16293 nm, bS == 1 ? "s" : "", rD, rN, imm32); 16294 goto decode_success; 16295 } 16296 } 16297 16298 /* ---------- (T3) ADD{S}.W Rd, Rn, Rm, {shift} ---------- */ 16299 /* ---------- (T3) SUB{S}.W Rd, Rn, Rm, {shift} ---------- */ 16300 /* ---------- (T3) RSB{S}.W Rd, Rn, Rm, {shift} ---------- */ 16301 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1) 16302 && ( INSN0(8,5) == BITS4(1,0,0,0) // add subopc 16303 || INSN0(8,5) == BITS4(1,1,0,1) // sub subopc 16304 || INSN0(8,5) == BITS4(1,1,1,0)) // rsb subopc 16305 && INSN1(15,15) == 0) { 16306 UInt rN = INSN0(3,0); 16307 UInt rD = INSN1(11,8); 16308 UInt rM = INSN1(3,0); 16309 UInt bS = INSN0(4,4); 16310 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 16311 UInt how = INSN1(5,4); 16312 16313 Bool valid = !isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM); 16314 /* but allow "add.w reg, sp, reg w/ no shift */ 16315 if (!valid && INSN0(8,5) == BITS4(1,0,0,0) // add 16316 && rN == 13 && imm5 == 0 && how == 0) { 16317 valid = True; 16318 } 16319 /* also allow "sub.w sp, sp, reg w/ no shift */ 16320 if (!valid && INSN0(8,5) == BITS4(1,1,0,1) // add 16321 && rD == 13 && rN == 13 && imm5 == 0 && how == 0) { 16322 valid = True; 16323 } 16324 if (valid) { 16325 Bool swap = False; 16326 IROp op = Iop_INVALID; 16327 HChar* nm = "???"; 16328 switch (INSN0(8,5)) { 16329 case BITS4(1,0,0,0): op = Iop_Add32; nm = "add"; break; 16330 case BITS4(1,1,0,1): op = Iop_Sub32; nm = "sub"; break; 16331 case BITS4(1,1,1,0): op = Iop_Sub32; nm = "rsb"; 16332 swap = True; break; 16333 default: vassert(0); 16334 } 16335 16336 IRTemp argL = newTemp(Ity_I32); 16337 assign(argL, getIRegT(rN)); 16338 16339 IRTemp rMt = newTemp(Ity_I32); 16340 assign(rMt, getIRegT(rM)); 16341 16342 IRTemp argR = newTemp(Ity_I32); 16343 compute_result_and_C_after_shift_by_imm5( 16344 dis_buf, &argR, NULL, rMt, how, imm5, rM 16345 ); 16346 16347 IRTemp res = newTemp(Ity_I32); 16348 assign(res, swap 16349 ? binop(op, mkexpr(argR), mkexpr(argL)) 16350 : binop(op, mkexpr(argL), mkexpr(argR))); 16351 16352 putIRegT(rD, mkexpr(res), condT); 16353 if (bS) { 16354 switch (op) { 16355 case Iop_Add32: 16356 setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT ); 16357 break; 16358 case Iop_Sub32: 16359 if (swap) 16360 setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT ); 16361 else 16362 setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT ); 16363 break; 16364 default: 16365 vassert(0); 16366 } 16367 } 16368 16369 DIP("%s%s.w r%u, r%u, %s\n", 16370 nm, bS ? "s" : "", rD, rN, dis_buf); 16371 goto decode_success; 16372 } 16373 } 16374 16375 /* ---------- (T3) ADC{S}.W Rd, Rn, Rm, {shift} ---------- */ 16376 /* ---------- (T2) SBC{S}.W Rd, Rn, Rm, {shift} ---------- */ 16377 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1) 16378 && ( INSN0(8,5) == BITS4(1,0,1,0) // adc subopc 16379 || INSN0(8,5) == BITS4(1,0,1,1)) // sbc subopc 16380 && INSN1(15,15) == 0) { 16381 /* ADC: Rd = Rn + shifter_operand + oldC */ 16382 /* SBC: Rd = Rn - shifter_operand - (oldC ^ 1) */ 16383 UInt rN = INSN0(3,0); 16384 UInt rD = INSN1(11,8); 16385 UInt rM = INSN1(3,0); 16386 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 16387 UInt bS = INSN0(4,4); 16388 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 16389 UInt how = INSN1(5,4); 16390 16391 IRTemp argL = newTemp(Ity_I32); 16392 assign(argL, getIRegT(rN)); 16393 16394 IRTemp rMt = newTemp(Ity_I32); 16395 assign(rMt, getIRegT(rM)); 16396 16397 IRTemp oldC = newTemp(Ity_I32); 16398 assign(oldC, mk_armg_calculate_flag_c()); 16399 16400 IRTemp argR = newTemp(Ity_I32); 16401 compute_result_and_C_after_shift_by_imm5( 16402 dis_buf, &argR, NULL, rMt, how, imm5, rM 16403 ); 16404 16405 HChar* nm = "???"; 16406 IRTemp res = newTemp(Ity_I32); 16407 switch (INSN0(8,5)) { 16408 case BITS4(1,0,1,0): // ADC 16409 nm = "adc"; 16410 assign(res, 16411 binop(Iop_Add32, 16412 binop(Iop_Add32, mkexpr(argL), mkexpr(argR)), 16413 mkexpr(oldC) )); 16414 putIRegT(rD, mkexpr(res), condT); 16415 if (bS) 16416 setFlags_D1_D2_ND( ARMG_CC_OP_ADC, 16417 argL, argR, oldC, condT ); 16418 break; 16419 case BITS4(1,0,1,1): // SBC 16420 nm = "sbc"; 16421 assign(res, 16422 binop(Iop_Sub32, 16423 binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)), 16424 binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) )); 16425 putIRegT(rD, mkexpr(res), condT); 16426 if (bS) 16427 setFlags_D1_D2_ND( ARMG_CC_OP_SBB, 16428 argL, argR, oldC, condT ); 16429 break; 16430 default: 16431 vassert(0); 16432 } 16433 16434 DIP("%s%s.w r%u, r%u, %s\n", 16435 nm, bS ? "s" : "", rD, rN, dis_buf); 16436 goto decode_success; 16437 } 16438 } 16439 16440 /* ---------- (T3) AND{S}.W Rd, Rn, Rm, {shift} ---------- */ 16441 /* ---------- (T3) ORR{S}.W Rd, Rn, Rm, {shift} ---------- */ 16442 /* ---------- (T3) EOR{S}.W Rd, Rn, Rm, {shift} ---------- */ 16443 /* ---------- (T3) BIC{S}.W Rd, Rn, Rm, {shift} ---------- */ 16444 /* ---------- (T1) ORN{S}.W Rd, Rn, Rm, {shift} ---------- */ 16445 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1) 16446 && ( INSN0(8,5) == BITS4(0,0,0,0) // and subopc 16447 || INSN0(8,5) == BITS4(0,0,1,0) // orr subopc 16448 || INSN0(8,5) == BITS4(0,1,0,0) // eor subopc 16449 || INSN0(8,5) == BITS4(0,0,0,1) // bic subopc 16450 || INSN0(8,5) == BITS4(0,0,1,1)) // orn subopc 16451 && INSN1(15,15) == 0) { 16452 UInt rN = INSN0(3,0); 16453 UInt rD = INSN1(11,8); 16454 UInt rM = INSN1(3,0); 16455 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 16456 Bool notArgR = False; 16457 IROp op = Iop_INVALID; 16458 HChar* nm = "???"; 16459 switch (INSN0(8,5)) { 16460 case BITS4(0,0,0,0): op = Iop_And32; nm = "and"; break; 16461 case BITS4(0,0,1,0): op = Iop_Or32; nm = "orr"; break; 16462 case BITS4(0,1,0,0): op = Iop_Xor32; nm = "eor"; break; 16463 case BITS4(0,0,0,1): op = Iop_And32; nm = "bic"; 16464 notArgR = True; break; 16465 case BITS4(0,0,1,1): op = Iop_Or32; nm = "orn"; 16466 notArgR = True; break; 16467 default: vassert(0); 16468 } 16469 UInt bS = INSN0(4,4); 16470 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 16471 UInt how = INSN1(5,4); 16472 16473 IRTemp rNt = newTemp(Ity_I32); 16474 assign(rNt, getIRegT(rN)); 16475 16476 IRTemp rMt = newTemp(Ity_I32); 16477 assign(rMt, getIRegT(rM)); 16478 16479 IRTemp argR = newTemp(Ity_I32); 16480 IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID; 16481 16482 compute_result_and_C_after_shift_by_imm5( 16483 dis_buf, &argR, bS ? &oldC : NULL, rMt, how, imm5, rM 16484 ); 16485 16486 IRTemp res = newTemp(Ity_I32); 16487 if (notArgR) { 16488 vassert(op == Iop_And32 || op == Iop_Or32); 16489 assign(res, binop(op, mkexpr(rNt), 16490 unop(Iop_Not32, mkexpr(argR)))); 16491 } else { 16492 assign(res, binop(op, mkexpr(rNt), mkexpr(argR))); 16493 } 16494 16495 putIRegT(rD, mkexpr(res), condT); 16496 if (bS) { 16497 IRTemp oldV = newTemp(Ity_I32); 16498 assign( oldV, mk_armg_calculate_flag_v() ); 16499 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 16500 condT ); 16501 } 16502 16503 DIP("%s%s.w r%u, r%u, %s\n", 16504 nm, bS ? "s" : "", rD, rN, dis_buf); 16505 goto decode_success; 16506 } 16507 } 16508 16509 /* -------------- (T?) LSL{S}.W Rd, Rn, Rm -------------- */ 16510 /* -------------- (T?) LSR{S}.W Rd, Rn, Rm -------------- */ 16511 /* -------------- (T?) ASR{S}.W Rd, Rn, Rm -------------- */ 16512 /* -------------- (T?) ROR{S}.W Rd, Rn, Rm -------------- */ 16513 if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,0,0) 16514 && INSN1(15,12) == BITS4(1,1,1,1) 16515 && INSN1(7,4) == BITS4(0,0,0,0)) { 16516 UInt how = INSN0(6,5); // standard encoding 16517 UInt rN = INSN0(3,0); 16518 UInt rD = INSN1(11,8); 16519 UInt rM = INSN1(3,0); 16520 UInt bS = INSN0(4,4); 16521 Bool valid = !isBadRegT(rN) && !isBadRegT(rM) && !isBadRegT(rD); 16522 if (how == 3) valid = False; //ATC 16523 if (valid) { 16524 IRTemp rNt = newTemp(Ity_I32); 16525 IRTemp rMt = newTemp(Ity_I32); 16526 IRTemp res = newTemp(Ity_I32); 16527 IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID; 16528 IRTemp oldV = bS ? newTemp(Ity_I32) : IRTemp_INVALID; 16529 HChar* nms[4] = { "lsl", "lsr", "asr", "ror" }; 16530 HChar* nm = nms[how]; 16531 assign(rNt, getIRegT(rN)); 16532 assign(rMt, getIRegT(rM)); 16533 compute_result_and_C_after_shift_by_reg( 16534 dis_buf, &res, bS ? &oldC : NULL, 16535 rNt, how, rMt, rN, rM 16536 ); 16537 if (bS) 16538 assign(oldV, mk_armg_calculate_flag_v()); 16539 putIRegT(rD, mkexpr(res), condT); 16540 if (bS) { 16541 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 16542 condT ); 16543 } 16544 DIP("%s%s.w r%u, r%u, r%u\n", 16545 nm, bS ? "s" : "", rD, rN, rM); 16546 goto decode_success; 16547 } 16548 } 16549 16550 /* ------------ (T?) MOV{S}.W Rd, Rn, {shift} ------------ */ 16551 /* ------------ (T?) MVN{S}.W Rd, Rn, {shift} ------------ */ 16552 if ((INSN0(15,0) & 0xFFCF) == 0xEA4F 16553 && INSN1(15,15) == 0) { 16554 UInt rD = INSN1(11,8); 16555 UInt rN = INSN1(3,0); 16556 if (!isBadRegT(rD) && !isBadRegT(rN)) { 16557 UInt bS = INSN0(4,4); 16558 UInt isMVN = INSN0(5,5); 16559 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 16560 UInt how = INSN1(5,4); 16561 16562 IRTemp rNt = newTemp(Ity_I32); 16563 assign(rNt, getIRegT(rN)); 16564 16565 IRTemp oldRn = newTemp(Ity_I32); 16566 IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID; 16567 compute_result_and_C_after_shift_by_imm5( 16568 dis_buf, &oldRn, bS ? &oldC : NULL, rNt, how, imm5, rN 16569 ); 16570 16571 IRTemp res = newTemp(Ity_I32); 16572 assign(res, isMVN ? unop(Iop_Not32, mkexpr(oldRn)) 16573 : mkexpr(oldRn)); 16574 16575 putIRegT(rD, mkexpr(res), condT); 16576 if (bS) { 16577 IRTemp oldV = newTemp(Ity_I32); 16578 assign( oldV, mk_armg_calculate_flag_v() ); 16579 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT); 16580 } 16581 DIP("%s%s.w r%u, %s\n", 16582 isMVN ? "mvn" : "mov", bS ? "s" : "", rD, dis_buf); 16583 goto decode_success; 16584 } 16585 } 16586 16587 /* -------------- (T?) TST.W Rn, Rm, {shift} -------------- */ 16588 /* -------------- (T?) TEQ.W Rn, Rm, {shift} -------------- */ 16589 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1) 16590 && ( INSN0(8,4) == BITS5(0,0,0,0,1) // TST 16591 || INSN0(8,4) == BITS5(0,1,0,0,1)) // TEQ 16592 && INSN1(15,15) == 0 16593 && INSN1(11,8) == BITS4(1,1,1,1)) { 16594 UInt rN = INSN0(3,0); 16595 UInt rM = INSN1(3,0); 16596 if (!isBadRegT(rN) && !isBadRegT(rM)) { 16597 Bool isTST = INSN0(8,4) == BITS5(0,0,0,0,1); 16598 16599 UInt how = INSN1(5,4); 16600 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 16601 16602 IRTemp argL = newTemp(Ity_I32); 16603 assign(argL, getIRegT(rN)); 16604 16605 IRTemp rMt = newTemp(Ity_I32); 16606 assign(rMt, getIRegT(rM)); 16607 16608 IRTemp argR = newTemp(Ity_I32); 16609 IRTemp oldC = newTemp(Ity_I32); 16610 compute_result_and_C_after_shift_by_imm5( 16611 dis_buf, &argR, &oldC, rMt, how, imm5, rM 16612 ); 16613 16614 IRTemp oldV = newTemp(Ity_I32); 16615 assign( oldV, mk_armg_calculate_flag_v() ); 16616 16617 IRTemp res = newTemp(Ity_I32); 16618 assign(res, binop(isTST ? Iop_And32 : Iop_Xor32, 16619 mkexpr(argL), mkexpr(argR))); 16620 16621 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 16622 condT ); 16623 DIP("%s.w r%u, %s\n", isTST ? "tst" : "teq", rN, dis_buf); 16624 goto decode_success; 16625 } 16626 } 16627 16628 /* -------------- (T3) CMP.W Rn, Rm, {shift} -------------- */ 16629 /* -------------- (T2) CMN.W Rn, Rm, {shift} -------------- */ 16630 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1) 16631 && ( INSN0(8,4) == BITS5(1,1,0,1,1) // CMP 16632 || INSN0(8,4) == BITS5(1,0,0,0,1)) // CMN 16633 && INSN1(15,15) == 0 16634 && INSN1(11,8) == BITS4(1,1,1,1)) { 16635 UInt rN = INSN0(3,0); 16636 UInt rM = INSN1(3,0); 16637 if (!isBadRegT(rN) && !isBadRegT(rM)) { 16638 Bool isCMN = INSN0(8,4) == BITS5(1,0,0,0,1); 16639 UInt how = INSN1(5,4); 16640 UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6); 16641 16642 IRTemp argL = newTemp(Ity_I32); 16643 assign(argL, getIRegT(rN)); 16644 16645 IRTemp rMt = newTemp(Ity_I32); 16646 assign(rMt, getIRegT(rM)); 16647 16648 IRTemp argR = newTemp(Ity_I32); 16649 compute_result_and_C_after_shift_by_imm5( 16650 dis_buf, &argR, NULL, rMt, how, imm5, rM 16651 ); 16652 16653 setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB, 16654 argL, argR, condT ); 16655 16656 DIP("%s.w r%u, %s\n", isCMN ? "cmn" : "cmp", rN, dis_buf); 16657 goto decode_success; 16658 } 16659 } 16660 16661 /* -------------- (T2) MOV{S}.W Rd, #constT -------------- */ 16662 /* -------------- (T2) MVN{S}.W Rd, #constT -------------- */ 16663 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16664 && ( INSN0(9,5) == BITS5(0,0,0,1,0) // MOV 16665 || INSN0(9,5) == BITS5(0,0,0,1,1)) // MVN 16666 && INSN0(3,0) == BITS4(1,1,1,1) 16667 && INSN1(15,15) == 0) { 16668 UInt rD = INSN1(11,8); 16669 if (!isBadRegT(rD)) { 16670 Bool updC = False; 16671 UInt bS = INSN0(4,4); 16672 Bool isMVN = INSN0(5,5) == 1; 16673 UInt imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1); 16674 IRTemp res = newTemp(Ity_I32); 16675 assign(res, mkU32(isMVN ? ~imm32 : imm32)); 16676 putIRegT(rD, mkexpr(res), condT); 16677 if (bS) { 16678 IRTemp oldV = newTemp(Ity_I32); 16679 IRTemp oldC = newTemp(Ity_I32); 16680 assign( oldV, mk_armg_calculate_flag_v() ); 16681 assign( oldC, updC 16682 ? mkU32((imm32 >> 31) & 1) 16683 : mk_armg_calculate_flag_c() ); 16684 setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, 16685 condT ); 16686 } 16687 DIP("%s%s.w r%u, #%u\n", 16688 isMVN ? "mvn" : "mov", bS ? "s" : "", rD, imm32); 16689 goto decode_success; 16690 } 16691 } 16692 16693 /* -------------- (T3) MOVW Rd, #imm16 -------------- */ 16694 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16695 && INSN0(9,4) == BITS6(1,0,0,1,0,0) 16696 && INSN1(15,15) == 0) { 16697 UInt rD = INSN1(11,8); 16698 if (!isBadRegT(rD)) { 16699 UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11) 16700 | (INSN1(14,12) << 8) | INSN1(7,0); 16701 putIRegT(rD, mkU32(imm16), condT); 16702 DIP("movw r%u, #%u\n", rD, imm16); 16703 goto decode_success; 16704 } 16705 } 16706 16707 /* ---------------- MOVT Rd, #imm16 ---------------- */ 16708 if (INSN0(15,11) == BITS5(1,1,1,1,0) 16709 && INSN0(9,4) == BITS6(1,0,1,1,0,0) 16710 && INSN1(15,15) == 0) { 16711 UInt rD = INSN1(11,8); 16712 if (!isBadRegT(rD)) { 16713 UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11) 16714 | (INSN1(14,12) << 8) | INSN1(7,0); 16715 IRTemp res = newTemp(Ity_I32); 16716 assign(res, 16717 binop(Iop_Or32, 16718 binop(Iop_And32, getIRegT(rD), mkU32(0xFFFF)), 16719 mkU32(imm16 << 16))); 16720 putIRegT(rD, mkexpr(res), condT); 16721 DIP("movt r%u, #%u\n", rD, imm16); 16722 goto decode_success; 16723 } 16724 } 16725 16726 /* ---------------- LD/ST reg+/-#imm8 ---------------- */ 16727 /* Loads and stores of the form: 16728 op Rt, [Rn, #-imm8] or 16729 op Rt, [Rn], #+/-imm8 or 16730 op Rt, [Rn, #+/-imm8]! 16731 where op is one of 16732 ldrb ldrh ldr ldrsb ldrsh 16733 strb strh str 16734 */ 16735 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) && INSN1(11,11) == 1) { 16736 Bool valid = True; 16737 Bool syned = False; 16738 Bool isST = False; 16739 IRType ty = Ity_I8; 16740 HChar* nm = "???"; 16741 16742 switch (INSN0(8,4)) { 16743 case BITS5(0,0,0,0,0): // strb 16744 nm = "strb"; isST = True; break; 16745 case BITS5(0,0,0,0,1): // ldrb 16746 nm = "ldrb"; break; 16747 case BITS5(1,0,0,0,1): // ldrsb 16748 nm = "ldrsb"; syned = True; break; 16749 case BITS5(0,0,0,1,0): // strh 16750 nm = "strh"; ty = Ity_I16; isST = True; break; 16751 case BITS5(0,0,0,1,1): // ldrh 16752 nm = "ldrh"; ty = Ity_I16; break; 16753 case BITS5(1,0,0,1,1): // ldrsh 16754 nm = "ldrsh"; ty = Ity_I16; syned = True; break; 16755 case BITS5(0,0,1,0,0): // str 16756 nm = "str"; ty = Ity_I32; isST = True; break; 16757 case BITS5(0,0,1,0,1): 16758 nm = "ldr"; ty = Ity_I32; break; // ldr 16759 default: 16760 valid = False; break; 16761 } 16762 16763 UInt rN = INSN0(3,0); 16764 UInt rT = INSN1(15,12); 16765 UInt bP = INSN1(10,10); 16766 UInt bU = INSN1(9,9); 16767 UInt bW = INSN1(8,8); 16768 UInt imm8 = INSN1(7,0); 16769 Bool loadsPC = False; 16770 16771 if (valid) { 16772 if (bP == 1 && bU == 1 && bW == 0) 16773 valid = False; 16774 if (bP == 0 && bW == 0) 16775 valid = False; 16776 if (rN == 15) 16777 valid = False; 16778 if (bW == 1 && rN == rT) 16779 valid = False; 16780 if (ty == Ity_I8 || ty == Ity_I16) { 16781 if (isBadRegT(rT)) 16782 valid = False; 16783 } else { 16784 /* ty == Ity_I32 */ 16785 if (isST && rT == 15) 16786 valid = False; 16787 if (!isST && rT == 15) 16788 loadsPC = True; 16789 } 16790 } 16791 16792 if (valid) { 16793 // if it's a branch, it can't happen in the middle of an IT block 16794 if (loadsPC) 16795 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 16796 // go uncond 16797 mk_skip_over_T32_if_cond_is_false(condT); 16798 condT = IRTemp_INVALID; 16799 // now uncond 16800 16801 IRTemp preAddr = newTemp(Ity_I32); 16802 assign(preAddr, getIRegT(rN)); 16803 16804 IRTemp postAddr = newTemp(Ity_I32); 16805 assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32, 16806 mkexpr(preAddr), mkU32(imm8))); 16807 16808 IRTemp transAddr = bP == 1 ? postAddr : preAddr; 16809 16810 if (isST) { 16811 16812 /* Store. If necessary, update the base register before 16813 the store itself, so that the common idiom of "str rX, 16814 [sp, #-4]!" (store rX at sp-4, then do new sp = sp-4, 16815 a.k.a "push rX") doesn't cause Memcheck to complain 16816 that the access is below the stack pointer. Also, not 16817 updating sp before the store confuses Valgrind's 16818 dynamic stack-extending logic. So do it before the 16819 store. Hence we need to snarf the store data before 16820 doing the basereg update. */ 16821 16822 /* get hold of the data to be stored */ 16823 IRTemp oldRt = newTemp(Ity_I32); 16824 assign(oldRt, getIRegT(rT)); 16825 16826 /* Update Rn if necessary. */ 16827 if (bW == 1) { 16828 vassert(rN != rT); // assured by validity check above 16829 putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID); 16830 } 16831 16832 /* generate the transfer */ 16833 switch (ty) { 16834 case Ity_I8: 16835 storeLE(mkexpr(transAddr), 16836 unop(Iop_32to8, mkexpr(oldRt))); 16837 break; 16838 case Ity_I16: 16839 storeLE(mkexpr(transAddr), 16840 unop(Iop_32to16, mkexpr(oldRt))); 16841 break; 16842 case Ity_I32: 16843 storeLE(mkexpr(transAddr), mkexpr(oldRt)); 16844 break; 16845 default: 16846 vassert(0); 16847 } 16848 16849 } else { 16850 16851 /* Load. */ 16852 16853 /* generate the transfer */ 16854 IRTemp newRt = newTemp(Ity_I32); 16855 IROp widen = Iop_INVALID; 16856 switch (ty) { 16857 case Ity_I8: 16858 widen = syned ? Iop_8Sto32 : Iop_8Uto32; break; 16859 case Ity_I16: 16860 widen = syned ? Iop_16Sto32 : Iop_16Uto32; break; 16861 case Ity_I32: 16862 break; 16863 default: 16864 vassert(0); 16865 } 16866 if (widen == Iop_INVALID) { 16867 assign(newRt, loadLE(ty, mkexpr(transAddr))); 16868 } else { 16869 assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr)))); 16870 } 16871 if (loadsPC) { 16872 vassert(rT == 15); 16873 llPutIReg(rT, mkexpr(newRt)); 16874 } else { 16875 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID); 16876 } 16877 16878 if (loadsPC) { 16879 /* Presumably this is an interworking branch. */ 16880 irsb->next = mkexpr(newRt); 16881 irsb->jumpkind = Ijk_Boring; /* or _Ret ? */ 16882 dres.whatNext = Dis_StopHere; 16883 } 16884 16885 /* Update Rn if necessary. */ 16886 if (bW == 1) { 16887 vassert(rN != rT); // assured by validity check above 16888 putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID); 16889 } 16890 } 16891 16892 if (bP == 1 && bW == 0) { 16893 DIP("%s.w r%u, [r%u, #%c%u]\n", 16894 nm, rT, rN, bU ? '+' : '-', imm8); 16895 } 16896 else if (bP == 1 && bW == 1) { 16897 DIP("%s.w r%u, [r%u, #%c%u]!\n", 16898 nm, rT, rN, bU ? '+' : '-', imm8); 16899 } 16900 else { 16901 vassert(bP == 0 && bW == 1); 16902 DIP("%s.w r%u, [r%u], #%c%u\n", 16903 nm, rT, rN, bU ? '+' : '-', imm8); 16904 } 16905 16906 goto decode_success; 16907 } 16908 } 16909 16910 /* ------------- LD/ST reg+(reg<<imm2) ------------- */ 16911 /* Loads and stores of the form: 16912 op Rt, [Rn, Rm, LSL #imm8] 16913 where op is one of 16914 ldrb ldrh ldr ldrsb ldrsh 16915 strb strh str 16916 */ 16917 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) 16918 && INSN1(11,6) == BITS6(0,0,0,0,0,0)) { 16919 Bool valid = True; 16920 Bool syned = False; 16921 Bool isST = False; 16922 IRType ty = Ity_I8; 16923 HChar* nm = "???"; 16924 16925 switch (INSN0(8,4)) { 16926 case BITS5(0,0,0,0,0): // strb 16927 nm = "strb"; isST = True; break; 16928 case BITS5(0,0,0,0,1): // ldrb 16929 nm = "ldrb"; break; 16930 case BITS5(1,0,0,0,1): // ldrsb 16931 nm = "ldrsb"; syned = True; break; 16932 case BITS5(0,0,0,1,0): // strh 16933 nm = "strh"; ty = Ity_I16; isST = True; break; 16934 case BITS5(0,0,0,1,1): // ldrh 16935 nm = "ldrh"; ty = Ity_I16; break; 16936 case BITS5(1,0,0,1,1): // ldrsh 16937 nm = "ldrsh"; ty = Ity_I16; syned = True; break; 16938 case BITS5(0,0,1,0,0): // str 16939 nm = "str"; ty = Ity_I32; isST = True; break; 16940 case BITS5(0,0,1,0,1): 16941 nm = "ldr"; ty = Ity_I32; break; // ldr 16942 default: 16943 valid = False; break; 16944 } 16945 16946 UInt rN = INSN0(3,0); 16947 UInt rM = INSN1(3,0); 16948 UInt rT = INSN1(15,12); 16949 UInt imm2 = INSN1(5,4); 16950 Bool loadsPC = False; 16951 16952 if (ty == Ity_I8 || ty == Ity_I16) { 16953 /* all 8- and 16-bit load and store cases have the 16954 same exclusion set. */ 16955 if (rN == 15 || isBadRegT(rT) || isBadRegT(rM)) 16956 valid = False; 16957 } else { 16958 vassert(ty == Ity_I32); 16959 if (rN == 15 || isBadRegT(rM)) 16960 valid = False; 16961 if (isST && rT == 15) 16962 valid = False; 16963 /* If it is a load and rT is 15, that's only allowable if we 16964 not in an IT block, or are the last in it. Need to insert 16965 a dynamic check for that. */ 16966 if (!isST && rT == 15) 16967 loadsPC = True; 16968 } 16969 16970 if (valid) { 16971 // if it's a branch, it can't happen in the middle of an IT block 16972 if (loadsPC) 16973 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 16974 // go uncond 16975 mk_skip_over_T32_if_cond_is_false(condT); 16976 condT = IRTemp_INVALID; 16977 // now uncond 16978 16979 IRTemp transAddr = newTemp(Ity_I32); 16980 assign(transAddr, 16981 binop( Iop_Add32, 16982 getIRegT(rN), 16983 binop(Iop_Shl32, getIRegT(rM), mkU8(imm2)) )); 16984 16985 if (isST) { 16986 IRTemp oldRt = newTemp(Ity_I32); 16987 assign(oldRt, getIRegT(rT)); 16988 switch (ty) { 16989 case Ity_I8: 16990 storeLE(mkexpr(transAddr), 16991 unop(Iop_32to8, mkexpr(oldRt))); 16992 break; 16993 case Ity_I16: 16994 storeLE(mkexpr(transAddr), 16995 unop(Iop_32to16, mkexpr(oldRt))); 16996 break; 16997 case Ity_I32: 16998 storeLE(mkexpr(transAddr), mkexpr(oldRt)); 16999 break; 17000 default: 17001 vassert(0); 17002 } 17003 } else { 17004 IRTemp newRt = newTemp(Ity_I32); 17005 IROp widen = Iop_INVALID; 17006 switch (ty) { 17007 case Ity_I8: 17008 widen = syned ? Iop_8Sto32 : Iop_8Uto32; break; 17009 case Ity_I16: 17010 widen = syned ? Iop_16Sto32 : Iop_16Uto32; break; 17011 case Ity_I32: 17012 break; 17013 default: 17014 vassert(0); 17015 } 17016 if (widen == Iop_INVALID) { 17017 assign(newRt, loadLE(ty, mkexpr(transAddr))); 17018 } else { 17019 assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr)))); 17020 } 17021 17022 /* If we're loading the PC, putIRegT will assert. So go 17023 direct via llPutIReg. In all other cases use putIRegT 17024 as it is safer (although could simply use llPutIReg for 17025 _all_ cases here.) */ 17026 if (loadsPC) { 17027 vassert(rT == 15); 17028 llPutIReg(rT, mkexpr(newRt)); 17029 } else { 17030 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID); 17031 } 17032 17033 if (loadsPC) { 17034 /* Presumably this is an interworking branch. */ 17035 irsb->next = mkexpr(newRt); 17036 irsb->jumpkind = Ijk_Boring; /* or _Ret ? */ 17037 dres.whatNext = Dis_StopHere; 17038 } 17039 } 17040 17041 DIP("%s.w r%u, [r%u, r%u, LSL #%u]\n", 17042 nm, rT, rN, rM, imm2); 17043 17044 goto decode_success; 17045 } 17046 } 17047 17048 /* --------------- LD/ST reg+imm12 --------------- */ 17049 /* Loads and stores of the form: 17050 op Rt, [Rn, +#imm12] 17051 where op is one of 17052 ldrb ldrh ldr ldrsb ldrsh 17053 strb strh str 17054 */ 17055 if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)) { 17056 Bool valid = True; 17057 Bool syned = False; 17058 Bool isST = False; 17059 IRType ty = Ity_I8; 17060 HChar* nm = "???"; 17061 17062 switch (INSN0(8,4)) { 17063 case BITS5(0,1,0,0,0): // strb 17064 nm = "strb"; isST = True; break; 17065 case BITS5(0,1,0,0,1): // ldrb 17066 nm = "ldrb"; break; 17067 case BITS5(1,1,0,0,1): // ldrsb 17068 nm = "ldrsb"; syned = True; break; 17069 case BITS5(0,1,0,1,0): // strh 17070 nm = "strh"; ty = Ity_I16; isST = True; break; 17071 case BITS5(0,1,0,1,1): // ldrh 17072 nm = "ldrh"; ty = Ity_I16; break; 17073 case BITS5(1,1,0,1,1): // ldrsh 17074 nm = "ldrsh"; ty = Ity_I16; syned = True; break; 17075 case BITS5(0,1,1,0,0): // str 17076 nm = "str"; ty = Ity_I32; isST = True; break; 17077 case BITS5(0,1,1,0,1): 17078 nm = "ldr"; ty = Ity_I32; break; // ldr 17079 default: 17080 valid = False; break; 17081 } 17082 17083 UInt rN = INSN0(3,0); 17084 UInt rT = INSN1(15,12); 17085 UInt imm12 = INSN1(11,0); 17086 Bool loadsPC = False; 17087 17088 if (ty == Ity_I8 || ty == Ity_I16) { 17089 /* all 8- and 16-bit load and store cases have the 17090 same exclusion set. */ 17091 if (rN == 15 || isBadRegT(rT)) 17092 valid = False; 17093 } else { 17094 vassert(ty == Ity_I32); 17095 if (isST) { 17096 if (rN == 15 || rT == 15) 17097 valid = False; 17098 } else { 17099 /* For a 32-bit load, rT == 15 is only allowable if we not 17100 in an IT block, or are the last in it. Need to insert 17101 a dynamic check for that. Also, in this particular 17102 case, rN == 15 is allowable. In this case however, the 17103 value obtained for rN is (apparently) 17104 "word-align(address of current insn + 4)". */ 17105 if (rT == 15) 17106 loadsPC = True; 17107 } 17108 } 17109 17110 if (valid) { 17111 // if it's a branch, it can't happen in the middle of an IT block 17112 if (loadsPC) 17113 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 17114 // go uncond 17115 mk_skip_over_T32_if_cond_is_false(condT); 17116 condT = IRTemp_INVALID; 17117 // now uncond 17118 17119 IRTemp rNt = newTemp(Ity_I32); 17120 if (rN == 15) { 17121 vassert(ty == Ity_I32 && !isST); 17122 assign(rNt, binop(Iop_And32, getIRegT(rN), mkU32(~3))); 17123 } else { 17124 assign(rNt, getIRegT(rN)); 17125 } 17126 17127 IRTemp transAddr = newTemp(Ity_I32); 17128 assign(transAddr, 17129 binop( Iop_Add32, mkexpr(rNt), mkU32(imm12) )); 17130 17131 if (isST) { 17132 IRTemp oldRt = newTemp(Ity_I32); 17133 assign(oldRt, getIRegT(rT)); 17134 switch (ty) { 17135 case Ity_I8: 17136 storeLE(mkexpr(transAddr), 17137 unop(Iop_32to8, mkexpr(oldRt))); 17138 break; 17139 case Ity_I16: 17140 storeLE(mkexpr(transAddr), 17141 unop(Iop_32to16, mkexpr(oldRt))); 17142 break; 17143 case Ity_I32: 17144 storeLE(mkexpr(transAddr), mkexpr(oldRt)); 17145 break; 17146 default: 17147 vassert(0); 17148 } 17149 } else { 17150 IRTemp newRt = newTemp(Ity_I32); 17151 IROp widen = Iop_INVALID; 17152 switch (ty) { 17153 case Ity_I8: 17154 widen = syned ? Iop_8Sto32 : Iop_8Uto32; break; 17155 case Ity_I16: 17156 widen = syned ? Iop_16Sto32 : Iop_16Uto32; break; 17157 case Ity_I32: 17158 break; 17159 default: 17160 vassert(0); 17161 } 17162 if (widen == Iop_INVALID) { 17163 assign(newRt, loadLE(ty, mkexpr(transAddr))); 17164 } else { 17165 assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr)))); 17166 } 17167 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID); 17168 17169 if (loadsPC) { 17170 /* Presumably this is an interworking branch. */ 17171 irsb->next = mkexpr(newRt); 17172 irsb->jumpkind = Ijk_Boring; /* or _Ret ? */ 17173 dres.whatNext = Dis_StopHere; 17174 } 17175 } 17176 17177 DIP("%s.w r%u, [r%u, +#%u]\n", nm, rT, rN, imm12); 17178 17179 goto decode_success; 17180 } 17181 } 17182 17183 /* -------------- LDRD/STRD reg+/-#imm8 -------------- */ 17184 /* Doubleword loads and stores of the form: 17185 ldrd/strd Rt, Rt2, [Rn, #-imm8] or 17186 ldrd/strd Rt, Rt2, [Rn], #+/-imm8 or 17187 ldrd/strd Rt, Rt2, [Rn, #+/-imm8]! 17188 */ 17189 if (INSN0(15,9) == BITS7(1,1,1,0,1,0,0) && INSN0(6,6) == 1) { 17190 UInt bP = INSN0(8,8); 17191 UInt bU = INSN0(7,7); 17192 UInt bW = INSN0(5,5); 17193 UInt bL = INSN0(4,4); // 1: load 0: store 17194 UInt rN = INSN0(3,0); 17195 UInt rT = INSN1(15,12); 17196 UInt rT2 = INSN1(11,8); 17197 UInt imm8 = INSN1(7,0); 17198 17199 Bool valid = True; 17200 if (bP == 0 && bW == 0) valid = False; 17201 if (bW == 1 && (rN == rT || rN == rT2)) valid = False; 17202 if (isBadRegT(rT) || isBadRegT(rT2)) valid = False; 17203 if (rN == 15) valid = False; 17204 if (bL == 1 && rT == rT2) valid = False; 17205 17206 if (valid) { 17207 // go uncond 17208 mk_skip_over_T32_if_cond_is_false(condT); 17209 condT = IRTemp_INVALID; 17210 // now uncond 17211 17212 IRTemp preAddr = newTemp(Ity_I32); 17213 assign(preAddr, getIRegT(rN)); 17214 17215 IRTemp postAddr = newTemp(Ity_I32); 17216 assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32, 17217 mkexpr(preAddr), mkU32(imm8 << 2))); 17218 17219 IRTemp transAddr = bP == 1 ? postAddr : preAddr; 17220 17221 if (bL == 0) { 17222 IRTemp oldRt = newTemp(Ity_I32); 17223 IRTemp oldRt2 = newTemp(Ity_I32); 17224 assign(oldRt, getIRegT(rT)); 17225 assign(oldRt2, getIRegT(rT2)); 17226 storeLE(mkexpr(transAddr), 17227 mkexpr(oldRt)); 17228 storeLE(binop(Iop_Add32, mkexpr(transAddr), mkU32(4)), 17229 mkexpr(oldRt2)); 17230 } else { 17231 IRTemp newRt = newTemp(Ity_I32); 17232 IRTemp newRt2 = newTemp(Ity_I32); 17233 assign(newRt, 17234 loadLE(Ity_I32, 17235 mkexpr(transAddr))); 17236 assign(newRt2, 17237 loadLE(Ity_I32, 17238 binop(Iop_Add32, mkexpr(transAddr), mkU32(4)))); 17239 putIRegT(rT, mkexpr(newRt), IRTemp_INVALID); 17240 putIRegT(rT2, mkexpr(newRt2), IRTemp_INVALID); 17241 } 17242 17243 if (bW == 1) { 17244 putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID); 17245 } 17246 17247 HChar* nm = bL ? "ldrd" : "strd"; 17248 17249 if (bP == 1 && bW == 0) { 17250 DIP("%s.w r%u, r%u, [r%u, #%c%u]\n", 17251 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2); 17252 } 17253 else if (bP == 1 && bW == 1) { 17254 DIP("%s.w r%u, r%u, [r%u, #%c%u]!\n", 17255 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2); 17256 } 17257 else { 17258 vassert(bP == 0 && bW == 1); 17259 DIP("%s.w r%u, r%u, [r%u], #%c%u\n", 17260 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2); 17261 } 17262 17263 goto decode_success; 17264 } 17265 } 17266 17267 /* -------------- (T3) Bcond.W label -------------- */ 17268 /* This variant carries its own condition, so can't be part of an 17269 IT block ... */ 17270 if (INSN0(15,11) == BITS5(1,1,1,1,0) 17271 && INSN1(15,14) == BITS2(1,0) 17272 && INSN1(12,12) == 0) { 17273 UInt cond = INSN0(9,6); 17274 if (cond != ARMCondAL && cond != ARMCondNV) { 17275 Int simm21 17276 = (INSN0(10,10) << (1 + 1 + 6 + 11 + 1)) 17277 | (INSN1(11,11) << (1 + 6 + 11 + 1)) 17278 | (INSN1(13,13) << (6 + 11 + 1)) 17279 | (INSN0(5,0) << (11 + 1)) 17280 | (INSN1(10,0) << 1); 17281 simm21 = (simm21 << 11) >> 11; 17282 17283 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 17284 UInt dst = simm21 + guest_R15_curr_instr_notENC + 4; 17285 17286 /* Not allowed in an IT block; SIGILL if so. */ 17287 gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate); 17288 17289 IRTemp kondT = newTemp(Ity_I32); 17290 assign( kondT, mk_armg_calculate_condition(cond) ); 17291 stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)), 17292 Ijk_Boring, 17293 IRConst_U32(dst | 1/*CPSR.T*/) )); 17294 irsb->next = mkU32( (guest_R15_curr_instr_notENC + 4) 17295 | 1 /*CPSR.T*/ ); 17296 irsb->jumpkind = Ijk_Boring; 17297 dres.whatNext = Dis_StopHere; 17298 DIP("b%s.w 0x%x\n", nCC(cond), dst); 17299 goto decode_success; 17300 } 17301 } 17302 17303 /* ---------------- (T4) B.W label ---------------- */ 17304 /* ... whereas this variant doesn't carry its own condition, so it 17305 has to be either unconditional or the conditional by virtue of 17306 being the last in an IT block. The upside is that there's 4 17307 more bits available for the jump offset, so it has a 16-times 17308 greater branch range than the T3 variant. */ 17309 if (INSN0(15,11) == BITS5(1,1,1,1,0) 17310 && INSN1(15,14) == BITS2(1,0) 17311 && INSN1(12,12) == 1) { 17312 if (1) { 17313 UInt bS = INSN0(10,10); 17314 UInt bJ1 = INSN1(13,13); 17315 UInt bJ2 = INSN1(11,11); 17316 UInt bI1 = 1 ^ (bJ1 ^ bS); 17317 UInt bI2 = 1 ^ (bJ2 ^ bS); 17318 Int simm25 17319 = (bS << (1 + 1 + 10 + 11 + 1)) 17320 | (bI1 << (1 + 10 + 11 + 1)) 17321 | (bI2 << (10 + 11 + 1)) 17322 | (INSN0(9,0) << (11 + 1)) 17323 | (INSN1(10,0) << 1); 17324 simm25 = (simm25 << 7) >> 7; 17325 17326 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 17327 UInt dst = simm25 + guest_R15_curr_instr_notENC + 4; 17328 17329 /* If in an IT block, must be the last insn. */ 17330 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 17331 17332 // go uncond 17333 mk_skip_over_T32_if_cond_is_false(condT); 17334 condT = IRTemp_INVALID; 17335 // now uncond 17336 17337 // branch to dst 17338 irsb->next = mkU32( dst | 1 /*CPSR.T*/ ); 17339 irsb->jumpkind = Ijk_Boring; 17340 dres.whatNext = Dis_StopHere; 17341 DIP("b.w 0x%x\n", dst); 17342 goto decode_success; 17343 } 17344 } 17345 17346 /* ------------------ TBB, TBH ------------------ */ 17347 if (INSN0(15,4) == 0xE8D && INSN1(15,5) == 0x780) { 17348 UInt rN = INSN0(3,0); 17349 UInt rM = INSN1(3,0); 17350 UInt bH = INSN1(4,4); 17351 if (bH/*ATC*/ || (rN != 13 && !isBadRegT(rM))) { 17352 /* Must be last or not-in IT block */ 17353 gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate); 17354 /* Go uncond */ 17355 mk_skip_over_T32_if_cond_is_false(condT); 17356 condT = IRTemp_INVALID; 17357 17358 IRExpr* ea 17359 = binop(Iop_Add32, 17360 getIRegT(rN), 17361 bH ? binop(Iop_Shl32, getIRegT(rM), mkU8(1)) 17362 : getIRegT(rM)); 17363 17364 IRTemp delta = newTemp(Ity_I32); 17365 if (bH) { 17366 assign(delta, unop(Iop_16Uto32, loadLE(Ity_I16, ea))); 17367 } else { 17368 assign(delta, unop(Iop_8Uto32, loadLE(Ity_I8, ea))); 17369 } 17370 17371 irsb->next 17372 = binop(Iop_Or32, 17373 binop(Iop_Add32, 17374 getIRegT(15), 17375 binop(Iop_Shl32, mkexpr(delta), mkU8(1)) 17376 ), 17377 mkU32(1) 17378 ); 17379 irsb->jumpkind = Ijk_Boring; 17380 dres.whatNext = Dis_StopHere; 17381 DIP("tb%c [r%u, r%u%s]\n", 17382 bH ? 'h' : 'b', rN, rM, bH ? ", LSL #1" : ""); 17383 goto decode_success; 17384 } 17385 } 17386 17387 /* ------------------ UBFX ------------------ */ 17388 /* ------------------ SBFX ------------------ */ 17389 /* There's also ARM versions of same, but it doesn't seem worth the 17390 hassle to common up the handling (it's only a couple of C 17391 statements). */ 17392 if ((INSN0(15,4) == 0xF3C // UBFX 17393 || INSN0(15,4) == 0xF34) // SBFX 17394 && INSN1(15,15) == 0 && INSN1(5,5) == 0) { 17395 UInt rN = INSN0(3,0); 17396 UInt rD = INSN1(11,8); 17397 UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6); 17398 UInt wm1 = INSN1(4,0); 17399 UInt msb = lsb + wm1; 17400 if (!isBadRegT(rD) && !isBadRegT(rN) && msb <= 31) { 17401 Bool isU = INSN0(15,4) == 0xF3C; 17402 IRTemp src = newTemp(Ity_I32); 17403 IRTemp tmp = newTemp(Ity_I32); 17404 IRTemp res = newTemp(Ity_I32); 17405 UInt mask = ((1 << wm1) - 1) + (1 << wm1); 17406 vassert(msb >= 0 && msb <= 31); 17407 vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive 17408 17409 assign(src, getIRegT(rN)); 17410 assign(tmp, binop(Iop_And32, 17411 binop(Iop_Shr32, mkexpr(src), mkU8(lsb)), 17412 mkU32(mask))); 17413 assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32, 17414 binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)), 17415 mkU8(31-wm1))); 17416 17417 putIRegT(rD, mkexpr(res), condT); 17418 17419 DIP("%s r%u, r%u, #%u, #%u\n", 17420 isU ? "ubfx" : "sbfx", rD, rN, lsb, wm1 + 1); 17421 goto decode_success; 17422 } 17423 } 17424 17425 /* ------------------ UXTB ------------------ */ 17426 /* ------------------ UXTH ------------------ */ 17427 /* ------------------ SXTB ------------------ */ 17428 /* ------------------ SXTH ------------------ */ 17429 /* ----------------- UXTB16 ----------------- */ 17430 /* ----------------- SXTB16 ----------------- */ 17431 /* FIXME: this is an exact duplicate of the ARM version. They 17432 should be commoned up. */ 17433 if ((INSN0(15,0) == 0xFA5F // UXTB 17434 || INSN0(15,0) == 0xFA1F // UXTH 17435 || INSN0(15,0) == 0xFA4F // SXTB 17436 || INSN0(15,0) == 0xFA0F // SXTH 17437 || INSN0(15,0) == 0xFA3F // UXTB16 17438 || INSN0(15,0) == 0xFA2F) // SXTB16 17439 && INSN1(15,12) == BITS4(1,1,1,1) 17440 && INSN1(7,6) == BITS2(1,0)) { 17441 UInt rD = INSN1(11,8); 17442 UInt rM = INSN1(3,0); 17443 UInt rot = INSN1(5,4); 17444 if (!isBadRegT(rD) && !isBadRegT(rM)) { 17445 HChar* nm = "???"; 17446 IRTemp srcT = newTemp(Ity_I32); 17447 IRTemp rotT = newTemp(Ity_I32); 17448 IRTemp dstT = newTemp(Ity_I32); 17449 assign(srcT, getIRegT(rM)); 17450 assign(rotT, genROR32(srcT, 8 * rot)); 17451 switch (INSN0(15,0)) { 17452 case 0xFA5F: // UXTB 17453 nm = "uxtb"; 17454 assign(dstT, unop(Iop_8Uto32, 17455 unop(Iop_32to8, mkexpr(rotT)))); 17456 break; 17457 case 0xFA1F: // UXTH 17458 nm = "uxth"; 17459 assign(dstT, unop(Iop_16Uto32, 17460 unop(Iop_32to16, mkexpr(rotT)))); 17461 break; 17462 case 0xFA4F: // SXTB 17463 nm = "sxtb"; 17464 assign(dstT, unop(Iop_8Sto32, 17465 unop(Iop_32to8, mkexpr(rotT)))); 17466 break; 17467 case 0xFA0F: // SXTH 17468 nm = "sxth"; 17469 assign(dstT, unop(Iop_16Sto32, 17470 unop(Iop_32to16, mkexpr(rotT)))); 17471 break; 17472 case 0xFA3F: // UXTB16 17473 nm = "uxtb16"; 17474 assign(dstT, binop(Iop_And32, mkexpr(rotT), 17475 mkU32(0x00FF00FF))); 17476 break; 17477 case 0xFA2F: { // SXTB16 17478 nm = "sxtb16"; 17479 IRTemp lo32 = newTemp(Ity_I32); 17480 IRTemp hi32 = newTemp(Ity_I32); 17481 assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF))); 17482 assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16))); 17483 assign( 17484 dstT, 17485 binop(Iop_Or32, 17486 binop(Iop_And32, 17487 unop(Iop_8Sto32, 17488 unop(Iop_32to8, mkexpr(lo32))), 17489 mkU32(0xFFFF)), 17490 binop(Iop_Shl32, 17491 unop(Iop_8Sto32, 17492 unop(Iop_32to8, mkexpr(hi32))), 17493 mkU8(16)) 17494 )); 17495 break; 17496 } 17497 default: 17498 vassert(0); 17499 } 17500 putIRegT(rD, mkexpr(dstT), condT); 17501 DIP("%s r%u, r%u, ror #%u\n", nm, rD, rM, 8 * rot); 17502 goto decode_success; 17503 } 17504 } 17505 17506 /* -------------- MUL.W Rd, Rn, Rm -------------- */ 17507 if (INSN0(15,4) == 0xFB0 17508 && (INSN1(15,0) & 0xF0F0) == 0xF000) { 17509 UInt rN = INSN0(3,0); 17510 UInt rD = INSN1(11,8); 17511 UInt rM = INSN1(3,0); 17512 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 17513 IRTemp res = newTemp(Ity_I32); 17514 assign(res, binop(Iop_Mul32, getIRegT(rN), getIRegT(rM))); 17515 putIRegT(rD, mkexpr(res), condT); 17516 DIP("mul.w r%u, r%u, r%u\n", rD, rN, rM); 17517 goto decode_success; 17518 } 17519 } 17520 17521 /* ------------------ {U,S}MULL ------------------ */ 17522 if ((INSN0(15,4) == 0xFB8 || INSN0(15,4) == 0xFBA) 17523 && INSN1(7,4) == BITS4(0,0,0,0)) { 17524 UInt isU = INSN0(5,5); 17525 UInt rN = INSN0(3,0); 17526 UInt rDlo = INSN1(15,12); 17527 UInt rDhi = INSN1(11,8); 17528 UInt rM = INSN1(3,0); 17529 if (!isBadRegT(rDhi) && !isBadRegT(rDlo) 17530 && !isBadRegT(rN) && !isBadRegT(rM) && rDlo != rDhi) { 17531 IRTemp res = newTemp(Ity_I64); 17532 assign(res, binop(isU ? Iop_MullU32 : Iop_MullS32, 17533 getIRegT(rN), getIRegT(rM))); 17534 putIRegT( rDhi, unop(Iop_64HIto32, mkexpr(res)), condT ); 17535 putIRegT( rDlo, unop(Iop_64to32, mkexpr(res)), condT ); 17536 DIP("%cmull r%u, r%u, r%u, r%u\n", 17537 isU ? 'u' : 's', rDlo, rDhi, rN, rM); 17538 goto decode_success; 17539 } 17540 } 17541 17542 /* ------------------ ML{A,S} ------------------ */ 17543 if (INSN0(15,4) == 0xFB0 17544 && ( INSN1(7,4) == BITS4(0,0,0,0) // MLA 17545 || INSN1(7,4) == BITS4(0,0,0,1))) { // MLS 17546 UInt rN = INSN0(3,0); 17547 UInt rA = INSN1(15,12); 17548 UInt rD = INSN1(11,8); 17549 UInt rM = INSN1(3,0); 17550 if (!isBadRegT(rD) && !isBadRegT(rN) 17551 && !isBadRegT(rM) && !isBadRegT(rA)) { 17552 Bool isMLA = INSN1(7,4) == BITS4(0,0,0,0); 17553 IRTemp res = newTemp(Ity_I32); 17554 assign(res, 17555 binop(isMLA ? Iop_Add32 : Iop_Sub32, 17556 getIRegT(rA), 17557 binop(Iop_Mul32, getIRegT(rN), getIRegT(rM)))); 17558 putIRegT(rD, mkexpr(res), condT); 17559 DIP("%s r%u, r%u, r%u, r%u\n", 17560 isMLA ? "mla" : "mls", rD, rN, rM, rA); 17561 goto decode_success; 17562 } 17563 } 17564 17565 /* ------------------ (T3) ADR ------------------ */ 17566 if ((INSN0(15,0) == 0xF20F || INSN0(15,0) == 0xF60F) 17567 && INSN1(15,15) == 0) { 17568 /* rD = align4(PC) + imm32 */ 17569 UInt rD = INSN1(11,8); 17570 if (!isBadRegT(rD)) { 17571 UInt imm32 = (INSN0(10,10) << 11) 17572 | (INSN1(14,12) << 8) | INSN1(7,0); 17573 putIRegT(rD, binop(Iop_Add32, 17574 binop(Iop_And32, getIRegT(15), mkU32(~3U)), 17575 mkU32(imm32)), 17576 condT); 17577 DIP("add r%u, pc, #%u\n", rD, imm32); 17578 goto decode_success; 17579 } 17580 } 17581 17582 /* ----------------- (T1) UMLAL ----------------- */ 17583 /* ----------------- (T1) SMLAL ----------------- */ 17584 if ((INSN0(15,4) == 0xFBE // UMLAL 17585 || INSN0(15,4) == 0xFBC) // SMLAL 17586 && INSN1(7,4) == BITS4(0,0,0,0)) { 17587 UInt rN = INSN0(3,0); 17588 UInt rDlo = INSN1(15,12); 17589 UInt rDhi = INSN1(11,8); 17590 UInt rM = INSN1(3,0); 17591 if (!isBadRegT(rDlo) && !isBadRegT(rDhi) && !isBadRegT(rN) 17592 && !isBadRegT(rM) && rDhi != rDlo) { 17593 Bool isS = INSN0(15,4) == 0xFBC; 17594 IRTemp argL = newTemp(Ity_I32); 17595 IRTemp argR = newTemp(Ity_I32); 17596 IRTemp old = newTemp(Ity_I64); 17597 IRTemp res = newTemp(Ity_I64); 17598 IRTemp resHi = newTemp(Ity_I32); 17599 IRTemp resLo = newTemp(Ity_I32); 17600 IROp mulOp = isS ? Iop_MullS32 : Iop_MullU32; 17601 assign( argL, getIRegT(rM)); 17602 assign( argR, getIRegT(rN)); 17603 assign( old, binop(Iop_32HLto64, getIRegT(rDhi), getIRegT(rDlo)) ); 17604 assign( res, binop(Iop_Add64, 17605 mkexpr(old), 17606 binop(mulOp, mkexpr(argL), mkexpr(argR))) ); 17607 assign( resHi, unop(Iop_64HIto32, mkexpr(res)) ); 17608 assign( resLo, unop(Iop_64to32, mkexpr(res)) ); 17609 putIRegT( rDhi, mkexpr(resHi), condT ); 17610 putIRegT( rDlo, mkexpr(resLo), condT ); 17611 DIP("%cmlal r%u, r%u, r%u, r%u\n", 17612 isS ? 's' : 'u', rDlo, rDhi, rN, rM); 17613 goto decode_success; 17614 } 17615 } 17616 17617 /* ------------------ (T2) ADR ------------------ */ 17618 if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF) 17619 && INSN1(15,15) == 0) { 17620 /* rD = align4(PC) - imm32 */ 17621 UInt rD = INSN1(11,8); 17622 if (!isBadRegT(rD)) { 17623 UInt imm32 = (INSN0(10,10) << 11) 17624 | (INSN1(14,12) << 8) | INSN1(7,0); 17625 putIRegT(rD, binop(Iop_Sub32, 17626 binop(Iop_And32, getIRegT(15), mkU32(~3U)), 17627 mkU32(imm32)), 17628 condT); 17629 DIP("sub r%u, pc, #%u\n", rD, imm32); 17630 goto decode_success; 17631 } 17632 } 17633 17634 /* ------------------- (T1) BFI ------------------- */ 17635 /* ------------------- (T1) BFC ------------------- */ 17636 if (INSN0(15,4) == 0xF36 && INSN1(15,15) == 0 && INSN1(5,5) == 0) { 17637 UInt rD = INSN1(11,8); 17638 UInt rN = INSN0(3,0); 17639 UInt msb = INSN1(4,0); 17640 UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6); 17641 if (isBadRegT(rD) || rN == 13 || msb < lsb) { 17642 /* undecodable; fall through */ 17643 } else { 17644 IRTemp src = newTemp(Ity_I32); 17645 IRTemp olddst = newTemp(Ity_I32); 17646 IRTemp newdst = newTemp(Ity_I32); 17647 UInt mask = 1 << (msb - lsb); 17648 mask = (mask - 1) + mask; 17649 vassert(mask != 0); // guaranteed by "msb < lsb" check above 17650 mask <<= lsb; 17651 17652 assign(src, rN == 15 ? mkU32(0) : getIRegT(rN)); 17653 assign(olddst, getIRegT(rD)); 17654 assign(newdst, 17655 binop(Iop_Or32, 17656 binop(Iop_And32, 17657 binop(Iop_Shl32, mkexpr(src), mkU8(lsb)), 17658 mkU32(mask)), 17659 binop(Iop_And32, 17660 mkexpr(olddst), 17661 mkU32(~mask))) 17662 ); 17663 17664 putIRegT(rD, mkexpr(newdst), condT); 17665 17666 if (rN == 15) { 17667 DIP("bfc r%u, #%u, #%u\n", 17668 rD, lsb, msb-lsb+1); 17669 } else { 17670 DIP("bfi r%u, r%u, #%u, #%u\n", 17671 rD, rN, lsb, msb-lsb+1); 17672 } 17673 goto decode_success; 17674 } 17675 } 17676 17677 /* ------------------- (T1) SXTAH ------------------- */ 17678 /* ------------------- (T1) UXTAH ------------------- */ 17679 if ((INSN0(15,4) == 0xFA1 // UXTAH 17680 || INSN0(15,4) == 0xFA0) // SXTAH 17681 && INSN1(15,12) == BITS4(1,1,1,1) 17682 && INSN1(7,6) == BITS2(1,0)) { 17683 Bool isU = INSN0(15,4) == 0xFA1; 17684 UInt rN = INSN0(3,0); 17685 UInt rD = INSN1(11,8); 17686 UInt rM = INSN1(3,0); 17687 UInt rot = INSN1(5,4); 17688 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 17689 IRTemp srcL = newTemp(Ity_I32); 17690 IRTemp srcR = newTemp(Ity_I32); 17691 IRTemp res = newTemp(Ity_I32); 17692 assign(srcR, getIRegT(rM)); 17693 assign(srcL, getIRegT(rN)); 17694 assign(res, binop(Iop_Add32, 17695 mkexpr(srcL), 17696 unop(isU ? Iop_16Uto32 : Iop_16Sto32, 17697 unop(Iop_32to16, 17698 genROR32(srcR, 8 * rot))))); 17699 putIRegT(rD, mkexpr(res), condT); 17700 DIP("%cxtah r%u, r%u, r%u, ror #%u\n", 17701 isU ? 'u' : 's', rD, rN, rM, rot); 17702 goto decode_success; 17703 } 17704 } 17705 17706 /* ------------------- (T1) SXTAB ------------------- */ 17707 /* ------------------- (T1) UXTAB ------------------- */ 17708 if ((INSN0(15,4) == 0xFA5 // UXTAB 17709 || INSN0(15,4) == 0xFA4) // SXTAB 17710 && INSN1(15,12) == BITS4(1,1,1,1) 17711 && INSN1(7,6) == BITS2(1,0)) { 17712 Bool isU = INSN0(15,4) == 0xFA5; 17713 UInt rN = INSN0(3,0); 17714 UInt rD = INSN1(11,8); 17715 UInt rM = INSN1(3,0); 17716 UInt rot = INSN1(5,4); 17717 if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) { 17718 IRTemp srcL = newTemp(Ity_I32); 17719 IRTemp srcR = newTemp(Ity_I32); 17720 IRTemp res = newTemp(Ity_I32); 17721 assign(srcR, getIRegT(rM)); 17722 assign(srcL, getIRegT(rN)); 17723 assign(res, binop(Iop_Add32, 17724 mkexpr(srcL), 17725 unop(isU ? Iop_8Uto32 : Iop_8Sto32, 17726 unop(Iop_32to8, 17727 genROR32(srcR, 8 * rot))))); 17728 putIRegT(rD, mkexpr(res), condT); 17729 DIP("%cxtab r%u, r%u, r%u, ror #%u\n", 17730 isU ? 'u' : 's', rD, rN, rM, rot); 17731 goto decode_success; 17732 } 17733 } 17734 17735 /* ------------------- (T1) CLZ ------------------- */ 17736 if (INSN0(15,4) == 0xFAB 17737 && INSN1(15,12) == BITS4(1,1,1,1) 17738 && INSN1(7,4) == BITS4(1,0,0,0)) { 17739 UInt rM1 = INSN0(3,0); 17740 UInt rD = INSN1(11,8); 17741 UInt rM2 = INSN1(3,0); 17742 if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) { 17743 IRTemp arg = newTemp(Ity_I32); 17744 IRTemp res = newTemp(Ity_I32); 17745 assign(arg, getIRegT(rM1)); 17746 assign(res, IRExpr_Mux0X( 17747 unop(Iop_1Uto8,binop(Iop_CmpEQ32, 17748 mkexpr(arg), 17749 mkU32(0))), 17750 unop(Iop_Clz32, mkexpr(arg)), 17751 mkU32(32) 17752 )); 17753 putIRegT(rD, mkexpr(res), condT); 17754 DIP("clz r%u, r%u\n", rD, rM1); 17755 goto decode_success; 17756 } 17757 } 17758 17759 /* ------------------- (T1) RBIT ------------------- */ 17760 if (INSN0(15,4) == 0xFA9 17761 && INSN1(15,12) == BITS4(1,1,1,1) 17762 && INSN1(7,4) == BITS4(1,0,1,0)) { 17763 UInt rM1 = INSN0(3,0); 17764 UInt rD = INSN1(11,8); 17765 UInt rM2 = INSN1(3,0); 17766 if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) { 17767 IRTemp arg = newTemp(Ity_I32); 17768 assign(arg, getIRegT(rM1)); 17769 IRTemp res = gen_BITREV(arg); 17770 putIRegT(rD, mkexpr(res), condT); 17771 DIP("rbit r%u, r%u\n", rD, rM1); 17772 goto decode_success; 17773 } 17774 } 17775 17776 /* ------------------- (T2) REV ------------------- */ 17777 /* ------------------- (T2) REV16 ------------------- */ 17778 if (INSN0(15,4) == 0xFA9 17779 && INSN1(15,12) == BITS4(1,1,1,1) 17780 && ( INSN1(7,4) == BITS4(1,0,0,0) // REV 17781 || INSN1(7,4) == BITS4(1,0,0,1))) { // REV16 17782 UInt rM1 = INSN0(3,0); 17783 UInt rD = INSN1(11,8); 17784 UInt rM2 = INSN1(3,0); 17785 Bool isREV = INSN1(7,4) == BITS4(1,0,0,0); 17786 if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) { 17787 IRTemp arg = newTemp(Ity_I32); 17788 assign(arg, getIRegT(rM1)); 17789 IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg); 17790 putIRegT(rD, mkexpr(res), condT); 17791 DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM1); 17792 goto decode_success; 17793 } 17794 } 17795 17796 /* -------------- (T1) MSR apsr, reg -------------- */ 17797 if (INSN0(15,4) == 0xF38 17798 && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) { 17799 UInt rN = INSN0(3,0); 17800 UInt write_ge = INSN1(10,10); 17801 UInt write_nzcvq = INSN1(11,11); 17802 if (!isBadRegT(rN) && (write_nzcvq || write_ge)) { 17803 IRTemp rNt = newTemp(Ity_I32); 17804 assign(rNt, getIRegT(rN)); 17805 desynthesise_APSR( write_nzcvq, write_ge, rNt, condT ); 17806 DIP("msr cpsr_%s%s, r%u\n", 17807 write_nzcvq ? "f" : "", write_ge ? "g" : "", rN); 17808 goto decode_success; 17809 } 17810 } 17811 17812 /* -------------- (T1) MRS reg, apsr -------------- */ 17813 if (INSN0(15,0) == 0xF3EF 17814 && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(7,0) == 0x00) { 17815 UInt rD = INSN1(11,8); 17816 if (!isBadRegT(rD)) { 17817 IRTemp apsr = synthesise_APSR(); 17818 putIRegT( rD, mkexpr(apsr), condT ); 17819 DIP("mrs r%u, cpsr\n", rD); 17820 goto decode_success; 17821 } 17822 } 17823 17824 /* ----------------- (T1) LDREX ----------------- */ 17825 if (INSN0(15,4) == 0xE85 && INSN1(11,8) == BITS4(1,1,1,1)) { 17826 UInt rN = INSN0(3,0); 17827 UInt rT = INSN1(15,12); 17828 UInt imm8 = INSN1(7,0); 17829 if (!isBadRegT(rT) && rN != 15) { 17830 IRTemp res; 17831 // go uncond 17832 mk_skip_over_T32_if_cond_is_false( condT ); 17833 // now uncond 17834 res = newTemp(Ity_I32); 17835 stmt( IRStmt_LLSC(Iend_LE, 17836 res, 17837 binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)), 17838 NULL/*this is a load*/ )); 17839 putIRegT(rT, mkexpr(res), IRTemp_INVALID); 17840 DIP("ldrex r%u, [r%u, #+%u]\n", rT, rN, imm8 * 4); 17841 goto decode_success; 17842 } 17843 } 17844 17845 /* ----------------- (T1) STREX ----------------- */ 17846 if (INSN0(15,4) == 0xE84) { 17847 UInt rN = INSN0(3,0); 17848 UInt rT = INSN1(15,12); 17849 UInt rD = INSN1(11,8); 17850 UInt imm8 = INSN1(7,0); 17851 if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15 17852 && rD != rN && rD != rT) { 17853 IRTemp resSC1, resSC32; 17854 17855 // go uncond 17856 mk_skip_over_T32_if_cond_is_false( condT ); 17857 // now uncond 17858 17859 /* Ok, now we're unconditional. Do the store. */ 17860 resSC1 = newTemp(Ity_I1); 17861 stmt( IRStmt_LLSC(Iend_LE, 17862 resSC1, 17863 binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)), 17864 getIRegT(rT)) ); 17865 17866 /* Set rD to 1 on failure, 0 on success. Currently we have 17867 resSC1 == 0 on failure, 1 on success. */ 17868 resSC32 = newTemp(Ity_I32); 17869 assign(resSC32, 17870 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1)))); 17871 17872 putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID); 17873 DIP("strex r%u, r%u, [r%u, #+%u]\n", rD, rT, rN, imm8 * 4); 17874 goto decode_success; 17875 } 17876 } 17877 17878 /* -------------- read CP15 TPIDRURO register ------------- */ 17879 /* mrc p15, 0, r0, c13, c0, 3 up to 17880 mrc p15, 0, r14, c13, c0, 3 17881 */ 17882 /* I don't know whether this is really v7-only. But anyway, we 17883 have to support it since arm-linux uses TPIDRURO as a thread 17884 state register. */ 17885 if (INSN0(15,0) == 0xEE1D && INSN1(11,0) == 0xF70) { 17886 UInt rD = INSN1(15,12); 17887 if (rD <= 14) { 17888 /* skip r15, that's too stupid to handle */ 17889 putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), 17890 condT); 17891 DIP("mrc p15,0, r%u, c13, c0, 3\n", rD); 17892 goto decode_success; 17893 } 17894 } 17895 17896 /* -------------- v7 barrier insns -------------- */ 17897 if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) { 17898 /* XXX this isn't really right, is it? The generated IR does 17899 them unconditionally. I guess it doesn't matter since it 17900 doesn't do any harm to do them even when the guarding 17901 condition is false -- it's just a performance loss. */ 17902 switch (INSN1(7,0)) { 17903 case 0x4F: /* DSB sy */ 17904 case 0x4E: /* DSB st */ 17905 case 0x4B: /* DSB ish */ 17906 case 0x4A: /* DSB ishst */ 17907 case 0x47: /* DSB nsh */ 17908 case 0x46: /* DSB nshst */ 17909 case 0x43: /* DSB osh */ 17910 case 0x42: /* DSB oshst */ 17911 stmt( IRStmt_MBE(Imbe_Fence) ); 17912 DIP("DSB\n"); 17913 goto decode_success; 17914 case 0x5F: /* DMB sy */ 17915 case 0x5E: /* DMB st */ 17916 case 0x5B: /* DMB ish */ 17917 case 0x5A: /* DMB ishst */ 17918 case 0x57: /* DMB nsh */ 17919 case 0x56: /* DMB nshst */ 17920 case 0x53: /* DMB osh */ 17921 case 0x52: /* DMB oshst */ 17922 stmt( IRStmt_MBE(Imbe_Fence) ); 17923 DIP("DMB\n"); 17924 goto decode_success; 17925 case 0x6F: /* ISB */ 17926 stmt( IRStmt_MBE(Imbe_Fence) ); 17927 DIP("ISB\n"); 17928 goto decode_success; 17929 default: 17930 break; 17931 } 17932 } 17933 17934 /* -------------- read CP15 TPIDRURO register ------------- */ 17935 /* mrc p15, 0, r0, c13, c0, 3 up to 17936 mrc p15, 0, r14, c13, c0, 3 17937 */ 17938 /* I don't know whether this is really v7-only. But anyway, we 17939 have to support it since arm-linux uses TPIDRURO as a thread 17940 state register. */ 17941 17942 if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) { 17943 UInt rD = INSN1(15,12); 17944 if (!isBadRegT(rD)) { 17945 putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), IRTemp_INVALID); 17946 DIP("mrc p15,0, r%u, c13, c0, 3\n", rD); 17947 goto decode_success; 17948 } 17949 /* fall through */ 17950 } 17951 17952 /* ------------------- NOP ------------------ */ 17953 if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) { 17954 DIP("nop\n"); 17955 goto decode_success; 17956 } 17957 17958 /* ----------------------------------------------------------- */ 17959 /* -- VFP (CP 10, CP 11) instructions (in Thumb mode) -- */ 17960 /* ----------------------------------------------------------- */ 17961 17962 if (INSN0(15,12) == BITS4(1,1,1,0)) { 17963 UInt insn28 = (INSN0(11,0) << 16) | INSN1(15,0); 17964 Bool ok_vfp = decode_CP10_CP11_instruction ( 17965 &dres, insn28, condT, ARMCondAL/*bogus*/, 17966 True/*isT*/ 17967 ); 17968 if (ok_vfp) 17969 goto decode_success; 17970 } 17971 17972 /* ----------------------------------------------------------- */ 17973 /* -- NEON instructions (in Thumb mode) -- */ 17974 /* ----------------------------------------------------------- */ 17975 17976 if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) { 17977 UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0); 17978 Bool ok_neon = decode_NEON_instruction( 17979 &dres, insn32, condT, True/*isT*/ 17980 ); 17981 if (ok_neon) 17982 goto decode_success; 17983 } 17984 17985 /* ----------------------------------------------------------- */ 17986 /* -- v6 media instructions (in Thumb mode) -- */ 17987 /* ----------------------------------------------------------- */ 17988 17989 { UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0); 17990 Bool ok_v6m = decode_V6MEDIA_instruction( 17991 &dres, insn32, condT, ARMCondAL/*bogus*/, 17992 True/*isT*/ 17993 ); 17994 if (ok_v6m) 17995 goto decode_success; 17996 } 17997 17998 /* ----------------------------------------------------------- */ 17999 /* -- Undecodable -- */ 18000 /* ----------------------------------------------------------- */ 18001 18002 goto decode_failure; 18003 /*NOTREACHED*/ 18004 18005 decode_failure: 18006 /* All decode failures end up here. */ 18007 vex_printf("disInstr(thumb): unhandled instruction: " 18008 "0x%04x 0x%04x\n", (UInt)insn0, (UInt)insn1); 18009 18010 /* Back up ITSTATE to the initial value for this instruction. 18011 If we don't do that, any subsequent restart of the instruction 18012 will restart with the wrong value. */ 18013 put_ITSTATE(old_itstate); 18014 /* Tell the dispatcher that this insn cannot be decoded, and so has 18015 not been executed, and (is currently) the next to be executed. 18016 R15 should be up-to-date since it made so at the start of each 18017 insn, but nevertheless be paranoid and update it again right 18018 now. */ 18019 vassert(0 == (guest_R15_curr_instr_notENC & 1)); 18020 llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) ); 18021 irsb->next = mkU32(guest_R15_curr_instr_notENC | 1 /* CPSR.T */); 18022 irsb->jumpkind = Ijk_NoDecode; 18023 dres.whatNext = Dis_StopHere; 18024 dres.len = 0; 18025 return dres; 18026 18027 decode_success: 18028 /* All decode successes end up here. */ 18029 DIP("\n"); 18030 18031 vassert(dres.len == 2 || dres.len == 4 || dres.len == 20); 18032 18033 #if 0 18034 // XXX is this necessary on Thumb? 18035 /* Now then. Do we have an implicit jump to r15 to deal with? */ 18036 if (r15written) { 18037 /* If we get jump to deal with, we assume that there's been no 18038 other competing branch stuff previously generated for this 18039 insn. That's reasonable, in the sense that the ARM insn set 18040 appears to declare as "Unpredictable" any instruction which 18041 generates more than one possible new value for r15. Hence 18042 just assert. The decoders themselves should check against 18043 all such instructions which are thusly Unpredictable, and 18044 decline to decode them. Hence we should never get here if we 18045 have competing new values for r15, and hence it is safe to 18046 assert here. */ 18047 vassert(dres.whatNext == Dis_Continue); 18048 vassert(irsb->next == NULL); 18049 vassert(irsb->jumpkind = Ijk_Boring); 18050 /* If r15 is unconditionally written, terminate the block by 18051 jumping to it. If it's conditionally written, still 18052 terminate the block (a shame, but we can't do side exits to 18053 arbitrary destinations), but first jump to the next 18054 instruction if the condition doesn't hold. */ 18055 /* We can't use getIRegT(15) to get the destination, since that 18056 will produce r15+4, which isn't what we want. Must use 18057 llGetIReg(15) instead. */ 18058 if (r15guard == IRTemp_INVALID) { 18059 /* unconditional */ 18060 } else { 18061 /* conditional */ 18062 stmt( IRStmt_Exit( 18063 unop(Iop_32to1, 18064 binop(Iop_Xor32, 18065 mkexpr(r15guard), mkU32(1))), 18066 r15kind, 18067 IRConst_U32(guest_R15_curr_instr_notENC + 4) 18068 )); 18069 } 18070 irsb->next = llGetIReg(15); 18071 irsb->jumpkind = r15kind; 18072 dres.whatNext = Dis_StopHere; 18073 } 18074 #endif 18075 18076 return dres; 18077 18078 # undef INSN0 18079 # undef INSN1 18080 } 18081 18082 #undef DIP 18083 #undef DIS 18084 18085 18086 /*------------------------------------------------------------*/ 18087 /*--- Top-level fn ---*/ 18088 /*------------------------------------------------------------*/ 18089 18090 /* Disassemble a single instruction into IR. The instruction 18091 is located in host memory at &guest_code[delta]. */ 18092 18093 DisResult disInstr_ARM ( IRSB* irsb_IN, 18094 Bool put_IP, 18095 Bool (*resteerOkFn) ( void*, Addr64 ), 18096 Bool resteerCisOk, 18097 void* callback_opaque, 18098 UChar* guest_code_IN, 18099 Long delta_ENCODED, 18100 Addr64 guest_IP_ENCODED, 18101 VexArch guest_arch, 18102 VexArchInfo* archinfo, 18103 VexAbiInfo* abiinfo, 18104 Bool host_bigendian_IN ) 18105 { 18106 DisResult dres; 18107 Bool isThumb = (Bool)(guest_IP_ENCODED & 1); 18108 18109 /* Set globals (see top of this file) */ 18110 vassert(guest_arch == VexArchARM); 18111 18112 irsb = irsb_IN; 18113 host_is_bigendian = host_bigendian_IN; 18114 __curr_is_Thumb = isThumb; 18115 18116 if (isThumb) { 18117 guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED - 1; 18118 } else { 18119 guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED; 18120 } 18121 18122 if (isThumb) { 18123 dres = disInstr_THUMB_WRK ( put_IP, resteerOkFn, 18124 resteerCisOk, callback_opaque, 18125 &guest_code_IN[delta_ENCODED - 1], 18126 archinfo, abiinfo ); 18127 } else { 18128 dres = disInstr_ARM_WRK ( put_IP, resteerOkFn, 18129 resteerCisOk, callback_opaque, 18130 &guest_code_IN[delta_ENCODED], 18131 archinfo, abiinfo ); 18132 } 18133 18134 return dres; 18135 } 18136 18137 /* Test program for the conversion of IRCmpF64Result values to VFP 18138 nzcv values. See handling of FCMPD et al above. */ 18139 /* 18140 UInt foo ( UInt x ) 18141 { 18142 UInt ix = ((x >> 5) & 3) | (x & 1); 18143 UInt termL = (((((ix ^ 1) << 30) - 1) >> 29) + 1); 18144 UInt termR = (ix & (ix >> 1) & 1); 18145 return termL - termR; 18146 } 18147 18148 void try ( char* s, UInt ir, UInt req ) 18149 { 18150 UInt act = foo(ir); 18151 printf("%s 0x%02x -> req %d%d%d%d act %d%d%d%d (0x%x)\n", 18152 s, ir, (req >> 3) & 1, (req >> 2) & 1, 18153 (req >> 1) & 1, (req >> 0) & 1, 18154 (act >> 3) & 1, (act >> 2) & 1, 18155 (act >> 1) & 1, (act >> 0) & 1, act); 18156 18157 } 18158 18159 int main ( void ) 18160 { 18161 printf("\n"); 18162 try("UN", 0x45, 0b0011); 18163 try("LT", 0x01, 0b1000); 18164 try("GT", 0x00, 0b0010); 18165 try("EQ", 0x40, 0b0110); 18166 printf("\n"); 18167 return 0; 18168 } 18169 */ 18170 18171 /*--------------------------------------------------------------------*/ 18172 /*--- end guest_arm_toIR.c ---*/ 18173 /*--------------------------------------------------------------------*/ 18174