1 2 /*--------------------------------------------------------------------*/ 3 /*--- begin guest_ppc_toIR.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2004-2015 OpenWorks LLP 11 info (at) open-works.net 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 02110-1301, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 30 Neither the names of the U.S. Department of Energy nor the 31 University of California nor the names of its contributors may be 32 used to endorse or promote products derived from this software 33 without prior written permission. 34 */ 35 36 /* TODO 18/Nov/05: 37 38 Spot rld... cases which are simply left/right shifts and emit 39 Shl64/Shr64 accordingly. 40 41 Altivec 42 - datastream insns 43 - lvxl,stvxl: load/store with 'least recently used' hint 44 - vexptefp, vlogefp 45 46 LIMITATIONS: 47 48 Various, including: 49 50 - Some invalid forms of lswi and lswx are accepted when they should 51 not be. 52 53 - Floating Point: 54 - All exceptions disabled in FPSCR 55 - condition codes not set in FPSCR 56 57 - Altivec floating point: 58 - vmaddfp, vnmsubfp 59 Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the 60 system default of Non-Java mode, we get some small errors 61 (lowest bit only). 62 This is because Non-Java mode brutally hacks denormalised results 63 to zero, whereas we keep maximum accuracy. However, using 64 Non-Java mode would give us more inaccuracy, as our intermediate 65 results would then be zeroed, too. 66 67 - AbiHints for the stack red zone are only emitted for 68 unconditional calls and returns (bl, blr). They should also be 69 emitted for conditional calls and returns, but we don't have a 70 way to express that right now. Ah well. 71 72 - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c) 73 ignores the rounding mode, and generates code that assumes 74 round-to-nearest. This means V will compute incorrect results 75 for uses of these IROps when the rounding mode (first) arg is 76 not mkU32(Irrm_NEAREST). 77 */ 78 79 /* "Special" instructions. 80 81 This instruction decoder can decode four special instructions 82 which mean nothing natively (are no-ops as far as regs/mem are 83 concerned) but have meaning for supporting Valgrind. A special 84 instruction is flagged by a 16-byte preamble: 85 86 32-bit mode: 5400183E 5400683E 5400E83E 5400983E 87 (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31; 88 rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31) 89 90 64-bit mode: 78001800 78006800 7800E802 78009802 91 (rotldi 0,0,3; rotldi 0,0,13; 92 rotldi 0,0,61; rotldi 0,0,51) 93 94 Following that, one of the following 3 are allowed 95 (standard interpretation in parentheses): 96 97 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 ) 98 7C421378 (or 2,2,2) %R3 = guest_NRADDR 99 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 Big endian 100 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R12 Little endian 101 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2 102 7CA52B78 (or 5,5,5) IR injection 103 104 Any other bytes following the 16-byte preamble are illegal and 105 constitute a failure in instruction decoding. This all assumes 106 that the preamble will never occur except in specific code 107 fragments designed for Valgrind to catch. 108 */ 109 110 /* Little Endian notes */ 111 /* 112 * Vector operations in little Endian mode behave in non-obvious ways at times. 113 * Below is an attempt at explaining this. 114 * 115 * LE/BE vector example 116 * With a vector of unsigned ints declared as follows: 117 * vector unsigned int vec_inA = 118 { 0x11111111, 0x22222222, 0x33333333, 0x44444444 }; 119 * The '0x11111111' word is word zero in both LE and BE format. But the 120 * loaded vector register will have word zero on the far left in BE mode and 121 * on the far right in LE mode. The lvx and stvx instructions work naturally 122 * for whatever endianness is in effect. For example, in LE mode, the stvx 123 * stores word zero (far right word) of the vector at the lowest memory 124 * address of the EA; in BE mode, stvx still stores word zero at the lowest 125 * memory address, but with word zero interpreted as the one at the far left 126 * of the register. 127 * 128 * The lxvd2x and stxvd2x instructions are not so well suited for LE mode. 129 * When the compiler generates an lxvd2x instruction to load the 130 * above-declared vector of unsigned integers, it loads the vector as two 131 * double words, but they are in BE word-wise format. To put the vector in 132 * the right order for LE, the compiler also generates an xxswapd after the 133 * load, which puts it in proper LE format. Similarly, the stxvd2x 134 * instruction has a BE bias, storing the vector in BE word-wise format. But 135 * the compiler also generates an xxswapd prior to the store, thus ensuring 136 * the vector is stored in memory in the correct LE order. 137 * 138 * Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts 139 * of a double words and words within a vector. Because of the reverse order 140 * of numbering for LE as described above, the high part refers to word 1 in 141 * LE format. When input data is saved to a guest state vector register 142 * (e.g., via Iop_64HLtoV128), it is first saved to memory and then the 143 * register is loaded via PPCInstr_AvLdSt, which does an lvx instruction. 144 * The saving of the data to memory must be done in proper LE order. For the 145 * inverse operation of extracting data from a vector register (e.g., 146 * Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting 147 * in stvx), and then integer registers are loaded from the memory location 148 * from where the vector register was saved. Again, this must be done in 149 * proper LE order. So for these various vector Iops, we have LE-specific 150 * code in host_ppc_isel.c 151 * 152 * Another unique behavior of vectors in LE mode is with the vector scalar 153 * (VSX) operations that operate on "double word 0" of the source register, 154 * storing the result in "double word 0" of the output vector register. For 155 * these operations, "double word 0" is interpreted as "high half of the 156 * register" (i.e, the part on the left side). 157 * 158 */ 159 /* Translates PPC32/64 code to IR. */ 160 161 /* References 162 163 #define PPC32 164 "PowerPC Microprocessor Family: 165 The Programming Environments Manual for 32-Bit Microprocessors" 166 02/21/2000 167 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2 168 169 #define PPC64 170 "PowerPC Microprocessor Family: 171 Programming Environments Manual for 64-Bit Microprocessors" 172 06/10/2003 173 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797 174 175 #define AV 176 "PowerPC Microprocessor Family: 177 AltiVec(TM) Technology Programming Environments Manual" 178 07/10/2003 179 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D 180 */ 181 182 #include "libvex_basictypes.h" 183 #include "libvex_ir.h" 184 #include "libvex.h" 185 #include "libvex_emnote.h" 186 #include "libvex_guest_ppc32.h" 187 #include "libvex_guest_ppc64.h" 188 189 #include "main_util.h" 190 #include "main_globals.h" 191 #include "guest_generic_bb_to_IR.h" 192 #include "guest_ppc_defs.h" 193 194 /*------------------------------------------------------------*/ 195 /*--- Globals ---*/ 196 /*------------------------------------------------------------*/ 197 198 /* These are set at the start of the translation of an insn, right 199 down in disInstr_PPC, so that we don't have to pass them around 200 endlessly. They are all constant during the translation of any 201 given insn. */ 202 203 /* We need to know this to do sub-register accesses correctly. */ 204 static VexEndness host_endness; 205 206 /* Pointer to the guest code area. */ 207 static const UChar* guest_code; 208 209 /* The guest address corresponding to guest_code[0]. */ 210 static Addr64 guest_CIA_bbstart; 211 212 /* The guest address for the instruction currently being 213 translated. */ 214 static Addr64 guest_CIA_curr_instr; 215 216 /* The IRSB* into which we're generating code. */ 217 static IRSB* irsb; 218 219 /* Is our guest binary 32 or 64bit? Set at each call to 220 disInstr_PPC below. */ 221 static Bool mode64 = False; 222 223 // Given a pointer to a function as obtained by "& functionname" in C, 224 // produce a pointer to the actual entry point for the function. For 225 // most platforms it's the identity function. Unfortunately, on 226 // ppc64-linux it isn't (sigh) 227 static void* fnptr_to_fnentry( const VexAbiInfo* vbi, void* f ) 228 { 229 if (vbi->host_ppc_calls_use_fndescrs) { 230 /* f is a pointer to a 3-word function descriptor, of which the 231 first word is the entry address. */ 232 /* note, this is correct even with cross-jitting, since this is 233 purely a host issue, not a guest one. */ 234 HWord* fdescr = (HWord*)f; 235 return (void*)(fdescr[0]); 236 } else { 237 /* Simple; "& f" points directly at the code for f. */ 238 return f; 239 } 240 } 241 242 #define SIGN_BIT 0x8000000000000000ULL 243 #define SIGN_MASK 0x7fffffffffffffffULL 244 #define SIGN_BIT32 0x80000000 245 #define SIGN_MASK32 0x7fffffff 246 247 248 /*------------------------------------------------------------*/ 249 /*--- Debugging output ---*/ 250 /*------------------------------------------------------------*/ 251 252 #define DIP(format, args...) \ 253 if (vex_traceflags & VEX_TRACE_FE) \ 254 vex_printf(format, ## args) 255 256 #define DIS(buf, format, args...) \ 257 if (vex_traceflags & VEX_TRACE_FE) \ 258 vex_sprintf(buf, format, ## args) 259 260 261 /*------------------------------------------------------------*/ 262 /*--- Offsets of various parts of the ppc32/64 guest state ---*/ 263 /*------------------------------------------------------------*/ 264 265 #define offsetofPPCGuestState(_x) \ 266 (mode64 ? offsetof(VexGuestPPC64State, _x) : \ 267 offsetof(VexGuestPPC32State, _x)) 268 269 #define OFFB_CIA offsetofPPCGuestState(guest_CIA) 270 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL) 271 #define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO) 272 #define OFFB_LR offsetofPPCGuestState(guest_LR) 273 #define OFFB_CTR offsetofPPCGuestState(guest_CTR) 274 #define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO) 275 #define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV) 276 #define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA) 277 #define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC) 278 #define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND) 279 #define OFFB_DFPROUND offsetofPPCGuestState(guest_DFPROUND) 280 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE) 281 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR) 282 #define OFFB_EMNOTE offsetofPPCGuestState(guest_EMNOTE) 283 #define OFFB_CMSTART offsetofPPCGuestState(guest_CMSTART) 284 #define OFFB_CMLEN offsetofPPCGuestState(guest_CMLEN) 285 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) 286 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2) 287 #define OFFB_TFHAR offsetofPPCGuestState(guest_TFHAR) 288 #define OFFB_TEXASR offsetofPPCGuestState(guest_TEXASR) 289 #define OFFB_TEXASRU offsetofPPCGuestState(guest_TEXASRU) 290 #define OFFB_TFIAR offsetofPPCGuestState(guest_TFIAR) 291 #define OFFB_PPR offsetofPPCGuestState(guest_PPR) 292 #define OFFB_PSPB offsetofPPCGuestState(guest_PSPB) 293 294 295 /*------------------------------------------------------------*/ 296 /*--- Extract instruction fields --- */ 297 /*------------------------------------------------------------*/ 298 299 /* Extract field from insn, given idx (zero = lsb) and field length */ 300 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1)) 301 302 /* Extract primary opcode, instr[31:26] */ 303 static UChar ifieldOPC( UInt instr ) { 304 return toUChar( IFIELD( instr, 26, 6 ) ); 305 } 306 307 /* Extract 10-bit secondary opcode, instr[10:1] */ 308 static UInt ifieldOPClo10 ( UInt instr) { 309 return IFIELD( instr, 1, 10 ); 310 } 311 312 /* Extract 9-bit secondary opcode, instr[9:1] */ 313 static UInt ifieldOPClo9 ( UInt instr) { 314 return IFIELD( instr, 1, 9 ); 315 } 316 317 /* Extract 8-bit secondary opcode, instr[8:1] */ 318 static UInt ifieldOPClo8 ( UInt instr) { 319 return IFIELD( instr, 1, 8 ); 320 } 321 322 /* Extract 5-bit secondary opcode, instr[5:1] */ 323 static UInt ifieldOPClo5 ( UInt instr) { 324 return IFIELD( instr, 1, 5 ); 325 } 326 327 /* Extract RD (destination register) field, instr[25:21] */ 328 static UChar ifieldRegDS( UInt instr ) { 329 return toUChar( IFIELD( instr, 21, 5 ) ); 330 } 331 332 /* Extract XT (destination register) field, instr[0,25:21] */ 333 static UChar ifieldRegXT ( UInt instr ) 334 { 335 UChar upper_bit = toUChar (IFIELD (instr, 0, 1)); 336 UChar lower_bits = toUChar (IFIELD (instr, 21, 5)); 337 return (upper_bit << 5) | lower_bits; 338 } 339 340 /* Extract XS (store source register) field, instr[0,25:21] */ 341 static inline UChar ifieldRegXS ( UInt instr ) 342 { 343 return ifieldRegXT ( instr ); 344 } 345 346 /* Extract RA (1st source register) field, instr[20:16] */ 347 static UChar ifieldRegA ( UInt instr ) { 348 return toUChar( IFIELD( instr, 16, 5 ) ); 349 } 350 351 /* Extract XA (1st source register) field, instr[2,20:16] */ 352 static UChar ifieldRegXA ( UInt instr ) 353 { 354 UChar upper_bit = toUChar (IFIELD (instr, 2, 1)); 355 UChar lower_bits = toUChar (IFIELD (instr, 16, 5)); 356 return (upper_bit << 5) | lower_bits; 357 } 358 359 /* Extract RB (2nd source register) field, instr[15:11] */ 360 static UChar ifieldRegB ( UInt instr ) { 361 return toUChar( IFIELD( instr, 11, 5 ) ); 362 } 363 364 /* Extract XB (2nd source register) field, instr[1,15:11] */ 365 static UChar ifieldRegXB ( UInt instr ) 366 { 367 UChar upper_bit = toUChar (IFIELD (instr, 1, 1)); 368 UChar lower_bits = toUChar (IFIELD (instr, 11, 5)); 369 return (upper_bit << 5) | lower_bits; 370 } 371 372 /* Extract RC (3rd source register) field, instr[10:6] */ 373 static UChar ifieldRegC ( UInt instr ) { 374 return toUChar( IFIELD( instr, 6, 5 ) ); 375 } 376 377 /* Extract XC (3rd source register) field, instr[3,10:6] */ 378 static UChar ifieldRegXC ( UInt instr ) 379 { 380 UChar upper_bit = toUChar (IFIELD (instr, 3, 1)); 381 UChar lower_bits = toUChar (IFIELD (instr, 6, 5)); 382 return (upper_bit << 5) | lower_bits; 383 } 384 385 /* Extract bit 10, instr[10] */ 386 static UChar ifieldBIT10 ( UInt instr ) { 387 return toUChar( IFIELD( instr, 10, 1 ) ); 388 } 389 390 /* Extract 2nd lowest bit, instr[1] */ 391 static UChar ifieldBIT1 ( UInt instr ) { 392 return toUChar( IFIELD( instr, 1, 1 ) ); 393 } 394 395 /* Extract lowest bit, instr[0] */ 396 static UChar ifieldBIT0 ( UInt instr ) { 397 return toUChar( instr & 0x1 ); 398 } 399 400 /* Extract unsigned bottom half, instr[15:0] */ 401 static UInt ifieldUIMM16 ( UInt instr ) { 402 return instr & 0xFFFF; 403 } 404 405 /* Extract unsigned bottom 26 bits, instr[25:0] */ 406 static UInt ifieldUIMM26 ( UInt instr ) { 407 return instr & 0x3FFFFFF; 408 } 409 410 /* Extract DM field, instr[9:8] */ 411 static UChar ifieldDM ( UInt instr ) { 412 return toUChar( IFIELD( instr, 8, 2 ) ); 413 } 414 415 /* Extract SHW field, instr[9:8] */ 416 static inline UChar ifieldSHW ( UInt instr ) 417 { 418 return ifieldDM ( instr ); 419 } 420 421 /*------------------------------------------------------------*/ 422 /*--- Guest-state identifiers ---*/ 423 /*------------------------------------------------------------*/ 424 425 typedef enum { 426 PPC_GST_CIA, // Current Instruction Address 427 PPC_GST_LR, // Link Register 428 PPC_GST_CTR, // Count Register 429 PPC_GST_XER, // Overflow, carry flags, byte count 430 PPC_GST_CR, // Condition Register 431 PPC_GST_FPSCR, // Floating Point Status/Control Register 432 PPC_GST_VRSAVE, // Vector Save/Restore Register 433 PPC_GST_VSCR, // Vector Status and Control Register 434 PPC_GST_EMWARN, // Emulation warnings 435 PPC_GST_CMSTART,// For icbi: start of area to invalidate 436 PPC_GST_CMLEN, // For icbi: length of area to invalidate 437 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn 438 PPC_GST_SPRG3_RO, // SPRG3 439 PPC_GST_TFHAR, // Transactional Failure Handler Address Register 440 PPC_GST_TFIAR, // Transactional Failure Instruction Address Register 441 PPC_GST_TEXASR, // Transactional EXception And Summary Register 442 PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper 443 PPC_GST_PPR, // Program Priority register 444 PPC_GST_PPR32, // Upper 32-bits of Program Priority register 445 PPC_GST_PSPB, /* Problem State Priority Boost register, Note, the 446 * register is initialized to a non-zero value. Currently 447 * Valgrind is not supporting the register value to 448 * automatically decrement. Could be added later if 449 * needed. 450 */ 451 PPC_GST_MAX 452 } PPC_GST; 453 454 #define MASK_FPSCR_RN 0x3ULL // Binary floating point rounding mode 455 #define MASK_FPSCR_DRN 0x700000000ULL // Decimal floating point rounding mode 456 #define MASK_VSCR_VALID 0x00010001 457 458 459 /*------------------------------------------------------------*/ 460 /*--- FP Helpers ---*/ 461 /*------------------------------------------------------------*/ 462 463 /* Produce the 32-bit pattern corresponding to the supplied 464 float. */ 465 static UInt float_to_bits ( Float f ) 466 { 467 union { UInt i; Float f; } u; 468 vassert(4 == sizeof(UInt)); 469 vassert(4 == sizeof(Float)); 470 vassert(4 == sizeof(u)); 471 u.f = f; 472 return u.i; 473 } 474 475 476 /*------------------------------------------------------------*/ 477 /*--- Misc Helpers ---*/ 478 /*------------------------------------------------------------*/ 479 480 /* Generate mask with 1's from 'begin' through 'end', 481 wrapping if begin > end. 482 begin->end works from right to left, 0=lsb 483 */ 484 static UInt MASK32( UInt begin, UInt end ) 485 { 486 UInt m1, m2, mask; 487 vassert(begin < 32); 488 vassert(end < 32); 489 m1 = ((UInt)(-1)) << begin; 490 m2 = ((UInt)(-1)) << end << 1; 491 mask = m1 ^ m2; 492 if (begin > end) mask = ~mask; // wrap mask 493 return mask; 494 } 495 496 static ULong MASK64( UInt begin, UInt end ) 497 { 498 ULong m1, m2, mask; 499 vassert(begin < 64); 500 vassert(end < 64); 501 m1 = ((ULong)(-1)) << begin; 502 m2 = ((ULong)(-1)) << end << 1; 503 mask = m1 ^ m2; 504 if (begin > end) mask = ~mask; // wrap mask 505 return mask; 506 } 507 508 static Addr64 nextInsnAddr( void ) 509 { 510 return guest_CIA_curr_instr + 4; 511 } 512 513 514 /*------------------------------------------------------------*/ 515 /*--- Helper bits and pieces for deconstructing the ---*/ 516 /*--- ppc32/64 insn stream. ---*/ 517 /*------------------------------------------------------------*/ 518 519 /* Add a statement to the list held by "irsb". */ 520 static void stmt ( IRStmt* st ) 521 { 522 addStmtToIRSB( irsb, st ); 523 } 524 525 /* Generate a new temporary of the given type. */ 526 static IRTemp newTemp ( IRType ty ) 527 { 528 vassert(isPlausibleIRType(ty)); 529 return newIRTemp( irsb->tyenv, ty ); 530 } 531 532 /* Various simple conversions */ 533 534 static UChar extend_s_5to8 ( UChar x ) 535 { 536 return toUChar((((Int)x) << 27) >> 27); 537 } 538 539 static UInt extend_s_8to32( UChar x ) 540 { 541 return (UInt)((((Int)x) << 24) >> 24); 542 } 543 544 static UInt extend_s_16to32 ( UInt x ) 545 { 546 return (UInt)((((Int)x) << 16) >> 16); 547 } 548 549 static ULong extend_s_16to64 ( UInt x ) 550 { 551 return (ULong)((((Long)x) << 48) >> 48); 552 } 553 554 static ULong extend_s_26to64 ( UInt x ) 555 { 556 return (ULong)((((Long)x) << 38) >> 38); 557 } 558 559 static ULong extend_s_32to64 ( UInt x ) 560 { 561 return (ULong)((((Long)x) << 32) >> 32); 562 } 563 564 /* Do a proper-endian load of a 32-bit word, regardless of the endianness 565 of the underlying host. */ 566 static UInt getUIntPPCendianly ( const UChar* p ) 567 { 568 UInt w = 0; 569 if (host_endness == VexEndnessBE) { 570 w = (w << 8) | p[0]; 571 w = (w << 8) | p[1]; 572 w = (w << 8) | p[2]; 573 w = (w << 8) | p[3]; 574 } else { 575 w = (w << 8) | p[3]; 576 w = (w << 8) | p[2]; 577 w = (w << 8) | p[1]; 578 w = (w << 8) | p[0]; 579 } 580 return w; 581 } 582 583 584 /*------------------------------------------------------------*/ 585 /*--- Helpers for constructing IR. ---*/ 586 /*------------------------------------------------------------*/ 587 588 static void assign ( IRTemp dst, IRExpr* e ) 589 { 590 stmt( IRStmt_WrTmp(dst, e) ); 591 } 592 593 /* This generates a normal (non store-conditional) store. */ 594 static void store ( IRExpr* addr, IRExpr* data ) 595 { 596 IRType tyA = typeOfIRExpr(irsb->tyenv, addr); 597 vassert(tyA == Ity_I32 || tyA == Ity_I64); 598 599 if (host_endness == VexEndnessBE) 600 stmt( IRStmt_Store(Iend_BE, addr, data) ); 601 else 602 stmt( IRStmt_Store(Iend_LE, addr, data) ); 603 } 604 605 static IRExpr* unop ( IROp op, IRExpr* a ) 606 { 607 return IRExpr_Unop(op, a); 608 } 609 610 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 611 { 612 return IRExpr_Binop(op, a1, a2); 613 } 614 615 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 616 { 617 return IRExpr_Triop(op, a1, a2, a3); 618 } 619 620 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2, 621 IRExpr* a3, IRExpr* a4 ) 622 { 623 return IRExpr_Qop(op, a1, a2, a3, a4); 624 } 625 626 static IRExpr* mkexpr ( IRTemp tmp ) 627 { 628 return IRExpr_RdTmp(tmp); 629 } 630 631 static IRExpr* mkU8 ( UChar i ) 632 { 633 return IRExpr_Const(IRConst_U8(i)); 634 } 635 636 static IRExpr* mkU16 ( UInt i ) 637 { 638 return IRExpr_Const(IRConst_U16(i)); 639 } 640 641 static IRExpr* mkU32 ( UInt i ) 642 { 643 return IRExpr_Const(IRConst_U32(i)); 644 } 645 646 static IRExpr* mkU64 ( ULong i ) 647 { 648 return IRExpr_Const(IRConst_U64(i)); 649 } 650 651 static IRExpr* mkV128 ( UShort i ) 652 { 653 vassert(i == 0 || i == 0xffff); 654 return IRExpr_Const(IRConst_V128(i)); 655 } 656 657 /* This generates a normal (non load-linked) load. */ 658 static IRExpr* load ( IRType ty, IRExpr* addr ) 659 { 660 if (host_endness == VexEndnessBE) 661 return IRExpr_Load(Iend_BE, ty, addr); 662 else 663 return IRExpr_Load(Iend_LE, ty, addr); 664 } 665 666 static IRStmt* stmt_load ( IRTemp result, 667 IRExpr* addr, IRExpr* storedata ) 668 { 669 if (host_endness == VexEndnessBE) 670 return IRStmt_LLSC(Iend_BE, result, addr, storedata); 671 else 672 return IRStmt_LLSC(Iend_LE, result, addr, storedata); 673 } 674 675 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 ) 676 { 677 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 678 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 679 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1), 680 unop(Iop_1Uto32, arg2))); 681 } 682 683 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 ) 684 { 685 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 686 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 687 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1), 688 unop(Iop_1Uto32, arg2))); 689 } 690 691 /* expand V128_8Ux16 to 2x V128_16Ux8's */ 692 static void expand8Ux16( IRExpr* vIn, 693 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 694 { 695 IRTemp ones8x16 = newTemp(Ity_V128); 696 697 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 698 vassert(vEvn && *vEvn == IRTemp_INVALID); 699 vassert(vOdd && *vOdd == IRTemp_INVALID); 700 *vEvn = newTemp(Ity_V128); 701 *vOdd = newTemp(Ity_V128); 702 703 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 704 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) ); 705 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 706 binop(Iop_ShrV128, vIn, mkU8(8))) ); 707 } 708 709 /* expand V128_8Sx16 to 2x V128_16Sx8's */ 710 static void expand8Sx16( IRExpr* vIn, 711 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 712 { 713 IRTemp ones8x16 = newTemp(Ity_V128); 714 715 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 716 vassert(vEvn && *vEvn == IRTemp_INVALID); 717 vassert(vOdd && *vOdd == IRTemp_INVALID); 718 *vEvn = newTemp(Ity_V128); 719 *vOdd = newTemp(Ity_V128); 720 721 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 722 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) ); 723 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 724 binop(Iop_ShrV128, vIn, mkU8(8))) ); 725 } 726 727 /* expand V128_16Uto8 to 2x V128_32Ux4's */ 728 static void expand16Ux8( IRExpr* vIn, 729 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 730 { 731 IRTemp ones16x8 = newTemp(Ity_V128); 732 733 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 734 vassert(vEvn && *vEvn == IRTemp_INVALID); 735 vassert(vOdd && *vOdd == IRTemp_INVALID); 736 *vEvn = newTemp(Ity_V128); 737 *vOdd = newTemp(Ity_V128); 738 739 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 740 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) ); 741 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 742 binop(Iop_ShrV128, vIn, mkU8(16))) ); 743 } 744 745 /* expand V128_16Sto8 to 2x V128_32Sx4's */ 746 static void expand16Sx8( IRExpr* vIn, 747 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 748 { 749 IRTemp ones16x8 = newTemp(Ity_V128); 750 751 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 752 vassert(vEvn && *vEvn == IRTemp_INVALID); 753 vassert(vOdd && *vOdd == IRTemp_INVALID); 754 *vEvn = newTemp(Ity_V128); 755 *vOdd = newTemp(Ity_V128); 756 757 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 758 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) ); 759 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 760 binop(Iop_ShrV128, vIn, mkU8(16))) ); 761 } 762 763 /* break V128 to 4xF64's*/ 764 static void breakV128to4xF64( IRExpr* t128, 765 /*OUTs*/ 766 IRTemp* t3, IRTemp* t2, 767 IRTemp* t1, IRTemp* t0 ) 768 { 769 IRTemp hi64 = newTemp(Ity_I64); 770 IRTemp lo64 = newTemp(Ity_I64); 771 772 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 773 vassert(t0 && *t0 == IRTemp_INVALID); 774 vassert(t1 && *t1 == IRTemp_INVALID); 775 vassert(t2 && *t2 == IRTemp_INVALID); 776 vassert(t3 && *t3 == IRTemp_INVALID); 777 *t0 = newTemp(Ity_F64); 778 *t1 = newTemp(Ity_F64); 779 *t2 = newTemp(Ity_F64); 780 *t3 = newTemp(Ity_F64); 781 782 assign( hi64, unop(Iop_V128HIto64, t128) ); 783 assign( lo64, unop(Iop_V128to64, t128) ); 784 assign( *t3, 785 unop( Iop_F32toF64, 786 unop( Iop_ReinterpI32asF32, 787 unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) ); 788 assign( *t2, 789 unop( Iop_F32toF64, 790 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) ); 791 assign( *t1, 792 unop( Iop_F32toF64, 793 unop( Iop_ReinterpI32asF32, 794 unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) ); 795 assign( *t0, 796 unop( Iop_F32toF64, 797 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) ); 798 } 799 800 801 /* break V128 to 4xI32's, then sign-extend to I64's */ 802 static void breakV128to4x64S( IRExpr* t128, 803 /*OUTs*/ 804 IRTemp* t3, IRTemp* t2, 805 IRTemp* t1, IRTemp* t0 ) 806 { 807 IRTemp hi64 = newTemp(Ity_I64); 808 IRTemp lo64 = newTemp(Ity_I64); 809 810 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 811 vassert(t0 && *t0 == IRTemp_INVALID); 812 vassert(t1 && *t1 == IRTemp_INVALID); 813 vassert(t2 && *t2 == IRTemp_INVALID); 814 vassert(t3 && *t3 == IRTemp_INVALID); 815 *t0 = newTemp(Ity_I64); 816 *t1 = newTemp(Ity_I64); 817 *t2 = newTemp(Ity_I64); 818 *t3 = newTemp(Ity_I64); 819 820 assign( hi64, unop(Iop_V128HIto64, t128) ); 821 assign( lo64, unop(Iop_V128to64, t128) ); 822 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 823 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) ); 824 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 825 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) ); 826 } 827 828 /* break V128 to 4xI32's, then zero-extend to I64's */ 829 static void breakV128to4x64U ( IRExpr* t128, 830 /*OUTs*/ 831 IRTemp* t3, IRTemp* t2, 832 IRTemp* t1, IRTemp* t0 ) 833 { 834 IRTemp hi64 = newTemp(Ity_I64); 835 IRTemp lo64 = newTemp(Ity_I64); 836 837 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 838 vassert(t0 && *t0 == IRTemp_INVALID); 839 vassert(t1 && *t1 == IRTemp_INVALID); 840 vassert(t2 && *t2 == IRTemp_INVALID); 841 vassert(t3 && *t3 == IRTemp_INVALID); 842 *t0 = newTemp(Ity_I64); 843 *t1 = newTemp(Ity_I64); 844 *t2 = newTemp(Ity_I64); 845 *t3 = newTemp(Ity_I64); 846 847 assign( hi64, unop(Iop_V128HIto64, t128) ); 848 assign( lo64, unop(Iop_V128to64, t128) ); 849 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 850 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) ); 851 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 852 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) ); 853 } 854 855 static void breakV128to4x32( IRExpr* t128, 856 /*OUTs*/ 857 IRTemp* t3, IRTemp* t2, 858 IRTemp* t1, IRTemp* t0 ) 859 { 860 IRTemp hi64 = newTemp(Ity_I64); 861 IRTemp lo64 = newTemp(Ity_I64); 862 863 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 864 vassert(t0 && *t0 == IRTemp_INVALID); 865 vassert(t1 && *t1 == IRTemp_INVALID); 866 vassert(t2 && *t2 == IRTemp_INVALID); 867 vassert(t3 && *t3 == IRTemp_INVALID); 868 *t0 = newTemp(Ity_I32); 869 *t1 = newTemp(Ity_I32); 870 *t2 = newTemp(Ity_I32); 871 *t3 = newTemp(Ity_I32); 872 873 assign( hi64, unop(Iop_V128HIto64, t128) ); 874 assign( lo64, unop(Iop_V128to64, t128) ); 875 assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) ); 876 assign( *t2, unop(Iop_64to32, mkexpr(hi64)) ); 877 assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) ); 878 assign( *t0, unop(Iop_64to32, mkexpr(lo64)) ); 879 } 880 881 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2, 882 IRTemp t1, IRTemp t0 ) 883 { 884 return 885 binop( Iop_64HLtoV128, 886 binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)), 887 binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0)) 888 ); 889 } 890 891 892 /* Signed saturating narrow 64S to 32 */ 893 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 ) 894 { 895 IRTemp hi32 = newTemp(Ity_I32); 896 IRTemp lo32 = newTemp(Ity_I32); 897 898 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 899 900 assign( hi32, unop(Iop_64HIto32, t64)); 901 assign( lo32, unop(Iop_64to32, t64)); 902 903 return IRExpr_ITE( 904 /* if (hi32 == (lo32 >>s 31)) */ 905 binop(Iop_CmpEQ32, mkexpr(hi32), 906 binop( Iop_Sar32, mkexpr(lo32), mkU8(31))), 907 /* then: within signed-32 range: lo half good enough */ 908 mkexpr(lo32), 909 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */ 910 binop(Iop_Add32, mkU32(0x7FFFFFFF), 911 binop(Iop_Shr32, mkexpr(hi32), mkU8(31)))); 912 } 913 914 /* Unsigned saturating narrow 64S to 32 */ 915 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 ) 916 { 917 IRTemp hi32 = newTemp(Ity_I32); 918 IRTemp lo32 = newTemp(Ity_I32); 919 920 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 921 922 assign( hi32, unop(Iop_64HIto32, t64)); 923 assign( lo32, unop(Iop_64to32, t64)); 924 925 return IRExpr_ITE( 926 /* if (top 32 bits of t64 are 0) */ 927 binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)), 928 /* then: within unsigned-32 range: lo half good enough */ 929 mkexpr(lo32), 930 /* else: positive saturate -> 0xFFFFFFFF */ 931 mkU32(0xFFFFFFFF)); 932 } 933 934 /* Signed saturate narrow 64->32, combining to V128 */ 935 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2, 936 IRExpr* t1, IRExpr* t0 ) 937 { 938 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 939 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 940 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 941 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 942 return binop(Iop_64HLtoV128, 943 binop(Iop_32HLto64, 944 mkQNarrow64Sto32( t3 ), 945 mkQNarrow64Sto32( t2 )), 946 binop(Iop_32HLto64, 947 mkQNarrow64Sto32( t1 ), 948 mkQNarrow64Sto32( t0 ))); 949 } 950 951 /* Unsigned saturate narrow 64->32, combining to V128 */ 952 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2, 953 IRExpr* t1, IRExpr* t0 ) 954 { 955 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 956 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 957 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 958 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 959 return binop(Iop_64HLtoV128, 960 binop(Iop_32HLto64, 961 mkQNarrow64Uto32( t3 ), 962 mkQNarrow64Uto32( t2 )), 963 binop(Iop_32HLto64, 964 mkQNarrow64Uto32( t1 ), 965 mkQNarrow64Uto32( t0 ))); 966 } 967 968 /* Simulate irops Iop_MullOdd*, since we don't have them */ 969 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \ 970 binop(Iop_MullEven8Ux16, \ 971 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 972 binop(Iop_ShrV128, expr_vB, mkU8(8))) 973 974 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \ 975 binop(Iop_MullEven8Sx16, \ 976 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 977 binop(Iop_ShrV128, expr_vB, mkU8(8))) 978 979 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \ 980 binop(Iop_MullEven16Ux8, \ 981 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 982 binop(Iop_ShrV128, expr_vB, mkU8(16))) 983 984 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \ 985 binop(Iop_MullEven32Ux4, \ 986 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 987 binop(Iop_ShrV128, expr_vB, mkU8(32))) 988 989 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \ 990 binop(Iop_MullEven16Sx8, \ 991 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 992 binop(Iop_ShrV128, expr_vB, mkU8(16))) 993 994 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \ 995 binop(Iop_MullEven32Sx4, \ 996 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 997 binop(Iop_ShrV128, expr_vB, mkU8(32))) 998 999 1000 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src ) 1001 { 1002 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 1003 return unop(Iop_32Sto64, unop(Iop_64to32, src)); 1004 } 1005 1006 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src ) 1007 { 1008 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 1009 return unop(Iop_32Uto64, unop(Iop_64to32, src)); 1010 } 1011 1012 static IROp mkSzOp ( IRType ty, IROp op8 ) 1013 { 1014 Int adj; 1015 vassert(ty == Ity_I8 || ty == Ity_I16 || 1016 ty == Ity_I32 || ty == Ity_I64); 1017 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || 1018 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 || 1019 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 || 1020 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || 1021 op8 == Iop_Not8 ); 1022 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3)); 1023 return adj + op8; 1024 } 1025 1026 /* Make sure we get valid 32 and 64bit addresses */ 1027 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 1028 { 1029 vassert(ty == Ity_I32 || ty == Ity_I64); 1030 return ( ty == Ity_I64 ? 1031 (Addr64)addr : 1032 (Addr64)extend_s_32to64( toUInt(addr) ) ); 1033 } 1034 1035 /* sz, ULong -> IRExpr */ 1036 static IRExpr* mkSzImm ( IRType ty, ULong imm64 ) 1037 { 1038 vassert(ty == Ity_I32 || ty == Ity_I64); 1039 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64); 1040 } 1041 1042 /* sz, ULong -> IRConst */ 1043 static IRConst* mkSzConst ( IRType ty, ULong imm64 ) 1044 { 1045 vassert(ty == Ity_I32 || ty == Ity_I64); 1046 return ( ty == Ity_I64 ? 1047 IRConst_U64(imm64) : 1048 IRConst_U32((UInt)imm64) ); 1049 } 1050 1051 /* Sign extend imm16 -> IRExpr* */ 1052 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 ) 1053 { 1054 vassert(ty == Ity_I32 || ty == Ity_I64); 1055 return ( ty == Ity_I64 ? 1056 mkU64(extend_s_16to64(imm16)) : 1057 mkU32(extend_s_16to32(imm16)) ); 1058 } 1059 1060 /* Sign extend imm32 -> IRExpr* */ 1061 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 ) 1062 { 1063 vassert(ty == Ity_I32 || ty == Ity_I64); 1064 return ( ty == Ity_I64 ? 1065 mkU64(extend_s_32to64(imm32)) : 1066 mkU32(imm32) ); 1067 } 1068 1069 /* IR narrows I32/I64 -> I8/I16/I32 */ 1070 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src ) 1071 { 1072 vassert(ty == Ity_I32 || ty == Ity_I64); 1073 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 1074 } 1075 1076 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src ) 1077 { 1078 vassert(ty == Ity_I32 || ty == Ity_I64); 1079 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src); 1080 } 1081 1082 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src ) 1083 { 1084 vassert(ty == Ity_I32 || ty == Ity_I64); 1085 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 1086 } 1087 1088 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */ 1089 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined ) 1090 { 1091 IROp op; 1092 vassert(ty == Ity_I32 || ty == Ity_I64); 1093 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64; 1094 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64; 1095 return unop(op, src); 1096 } 1097 1098 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined ) 1099 { 1100 IROp op; 1101 vassert(ty == Ity_I32 || ty == Ity_I64); 1102 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64; 1103 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64; 1104 return unop(op, src); 1105 } 1106 1107 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined ) 1108 { 1109 vassert(ty == Ity_I32 || ty == Ity_I64); 1110 if (ty == Ity_I32) 1111 return src; 1112 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 1113 } 1114 1115 1116 static Int integerGuestRegOffset ( UInt archreg ) 1117 { 1118 vassert(archreg < 32); 1119 1120 // jrs: probably not necessary; only matters if we reference sub-parts 1121 // of the ppc registers, but that isn't the case 1122 // later: this might affect Altivec though? 1123 1124 switch (archreg) { 1125 case 0: return offsetofPPCGuestState(guest_GPR0); 1126 case 1: return offsetofPPCGuestState(guest_GPR1); 1127 case 2: return offsetofPPCGuestState(guest_GPR2); 1128 case 3: return offsetofPPCGuestState(guest_GPR3); 1129 case 4: return offsetofPPCGuestState(guest_GPR4); 1130 case 5: return offsetofPPCGuestState(guest_GPR5); 1131 case 6: return offsetofPPCGuestState(guest_GPR6); 1132 case 7: return offsetofPPCGuestState(guest_GPR7); 1133 case 8: return offsetofPPCGuestState(guest_GPR8); 1134 case 9: return offsetofPPCGuestState(guest_GPR9); 1135 case 10: return offsetofPPCGuestState(guest_GPR10); 1136 case 11: return offsetofPPCGuestState(guest_GPR11); 1137 case 12: return offsetofPPCGuestState(guest_GPR12); 1138 case 13: return offsetofPPCGuestState(guest_GPR13); 1139 case 14: return offsetofPPCGuestState(guest_GPR14); 1140 case 15: return offsetofPPCGuestState(guest_GPR15); 1141 case 16: return offsetofPPCGuestState(guest_GPR16); 1142 case 17: return offsetofPPCGuestState(guest_GPR17); 1143 case 18: return offsetofPPCGuestState(guest_GPR18); 1144 case 19: return offsetofPPCGuestState(guest_GPR19); 1145 case 20: return offsetofPPCGuestState(guest_GPR20); 1146 case 21: return offsetofPPCGuestState(guest_GPR21); 1147 case 22: return offsetofPPCGuestState(guest_GPR22); 1148 case 23: return offsetofPPCGuestState(guest_GPR23); 1149 case 24: return offsetofPPCGuestState(guest_GPR24); 1150 case 25: return offsetofPPCGuestState(guest_GPR25); 1151 case 26: return offsetofPPCGuestState(guest_GPR26); 1152 case 27: return offsetofPPCGuestState(guest_GPR27); 1153 case 28: return offsetofPPCGuestState(guest_GPR28); 1154 case 29: return offsetofPPCGuestState(guest_GPR29); 1155 case 30: return offsetofPPCGuestState(guest_GPR30); 1156 case 31: return offsetofPPCGuestState(guest_GPR31); 1157 default: break; 1158 } 1159 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/ 1160 } 1161 1162 static IRExpr* getIReg ( UInt archreg ) 1163 { 1164 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1165 vassert(archreg < 32); 1166 return IRExpr_Get( integerGuestRegOffset(archreg), ty ); 1167 } 1168 1169 /* Ditto, but write to a reg instead. */ 1170 static void putIReg ( UInt archreg, IRExpr* e ) 1171 { 1172 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1173 vassert(archreg < 32); 1174 vassert(typeOfIRExpr(irsb->tyenv, e) == ty ); 1175 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) ); 1176 } 1177 1178 1179 /* Floating point egisters are mapped to VSX registers[0..31]. */ 1180 static Int floatGuestRegOffset ( UInt archreg ) 1181 { 1182 vassert(archreg < 32); 1183 1184 if (host_endness == VexEndnessLE) { 1185 switch (archreg) { 1186 case 0: return offsetofPPCGuestState(guest_VSR0) + 8; 1187 case 1: return offsetofPPCGuestState(guest_VSR1) + 8; 1188 case 2: return offsetofPPCGuestState(guest_VSR2) + 8; 1189 case 3: return offsetofPPCGuestState(guest_VSR3) + 8; 1190 case 4: return offsetofPPCGuestState(guest_VSR4) + 8; 1191 case 5: return offsetofPPCGuestState(guest_VSR5) + 8; 1192 case 6: return offsetofPPCGuestState(guest_VSR6) + 8; 1193 case 7: return offsetofPPCGuestState(guest_VSR7) + 8; 1194 case 8: return offsetofPPCGuestState(guest_VSR8) + 8; 1195 case 9: return offsetofPPCGuestState(guest_VSR9) + 8; 1196 case 10: return offsetofPPCGuestState(guest_VSR10) + 8; 1197 case 11: return offsetofPPCGuestState(guest_VSR11) + 8; 1198 case 12: return offsetofPPCGuestState(guest_VSR12) + 8; 1199 case 13: return offsetofPPCGuestState(guest_VSR13) + 8; 1200 case 14: return offsetofPPCGuestState(guest_VSR14) + 8; 1201 case 15: return offsetofPPCGuestState(guest_VSR15) + 8; 1202 case 16: return offsetofPPCGuestState(guest_VSR16) + 8; 1203 case 17: return offsetofPPCGuestState(guest_VSR17) + 8; 1204 case 18: return offsetofPPCGuestState(guest_VSR18) + 8; 1205 case 19: return offsetofPPCGuestState(guest_VSR19) + 8; 1206 case 20: return offsetofPPCGuestState(guest_VSR20) + 8; 1207 case 21: return offsetofPPCGuestState(guest_VSR21) + 8; 1208 case 22: return offsetofPPCGuestState(guest_VSR22) + 8; 1209 case 23: return offsetofPPCGuestState(guest_VSR23) + 8; 1210 case 24: return offsetofPPCGuestState(guest_VSR24) + 8; 1211 case 25: return offsetofPPCGuestState(guest_VSR25) + 8; 1212 case 26: return offsetofPPCGuestState(guest_VSR26) + 8; 1213 case 27: return offsetofPPCGuestState(guest_VSR27) + 8; 1214 case 28: return offsetofPPCGuestState(guest_VSR28) + 8; 1215 case 29: return offsetofPPCGuestState(guest_VSR29) + 8; 1216 case 30: return offsetofPPCGuestState(guest_VSR30) + 8; 1217 case 31: return offsetofPPCGuestState(guest_VSR31) + 8; 1218 default: break; 1219 } 1220 } else { 1221 switch (archreg) { 1222 case 0: return offsetofPPCGuestState(guest_VSR0); 1223 case 1: return offsetofPPCGuestState(guest_VSR1); 1224 case 2: return offsetofPPCGuestState(guest_VSR2); 1225 case 3: return offsetofPPCGuestState(guest_VSR3); 1226 case 4: return offsetofPPCGuestState(guest_VSR4); 1227 case 5: return offsetofPPCGuestState(guest_VSR5); 1228 case 6: return offsetofPPCGuestState(guest_VSR6); 1229 case 7: return offsetofPPCGuestState(guest_VSR7); 1230 case 8: return offsetofPPCGuestState(guest_VSR8); 1231 case 9: return offsetofPPCGuestState(guest_VSR9); 1232 case 10: return offsetofPPCGuestState(guest_VSR10); 1233 case 11: return offsetofPPCGuestState(guest_VSR11); 1234 case 12: return offsetofPPCGuestState(guest_VSR12); 1235 case 13: return offsetofPPCGuestState(guest_VSR13); 1236 case 14: return offsetofPPCGuestState(guest_VSR14); 1237 case 15: return offsetofPPCGuestState(guest_VSR15); 1238 case 16: return offsetofPPCGuestState(guest_VSR16); 1239 case 17: return offsetofPPCGuestState(guest_VSR17); 1240 case 18: return offsetofPPCGuestState(guest_VSR18); 1241 case 19: return offsetofPPCGuestState(guest_VSR19); 1242 case 20: return offsetofPPCGuestState(guest_VSR20); 1243 case 21: return offsetofPPCGuestState(guest_VSR21); 1244 case 22: return offsetofPPCGuestState(guest_VSR22); 1245 case 23: return offsetofPPCGuestState(guest_VSR23); 1246 case 24: return offsetofPPCGuestState(guest_VSR24); 1247 case 25: return offsetofPPCGuestState(guest_VSR25); 1248 case 26: return offsetofPPCGuestState(guest_VSR26); 1249 case 27: return offsetofPPCGuestState(guest_VSR27); 1250 case 28: return offsetofPPCGuestState(guest_VSR28); 1251 case 29: return offsetofPPCGuestState(guest_VSR29); 1252 case 30: return offsetofPPCGuestState(guest_VSR30); 1253 case 31: return offsetofPPCGuestState(guest_VSR31); 1254 default: break; 1255 } 1256 } 1257 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/ 1258 } 1259 1260 static IRExpr* getFReg ( UInt archreg ) 1261 { 1262 vassert(archreg < 32); 1263 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 ); 1264 } 1265 1266 /* Ditto, but write to a reg instead. */ 1267 static void putFReg ( UInt archreg, IRExpr* e ) 1268 { 1269 vassert(archreg < 32); 1270 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1271 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) ); 1272 } 1273 1274 /* get Decimal float value. Note, they share floating point register file. */ 1275 static IRExpr* getDReg(UInt archreg) { 1276 IRExpr *e; 1277 vassert( archreg < 32 ); 1278 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 ); 1279 return e; 1280 } 1281 static IRExpr* getDReg32(UInt archreg) { 1282 IRExpr *e; 1283 vassert( archreg < 32 ); 1284 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 ); 1285 return e; 1286 } 1287 1288 /* Read a floating point register pair and combine their contents into a 1289 128-bit value */ 1290 static IRExpr *getDReg_pair(UInt archreg) { 1291 IRExpr *high = getDReg( archreg ); 1292 IRExpr *low = getDReg( archreg + 1 ); 1293 1294 return binop( Iop_D64HLtoD128, high, low ); 1295 } 1296 1297 /* Ditto, but write to a reg instead. */ 1298 static void putDReg32(UInt archreg, IRExpr* e) { 1299 vassert( archreg < 32 ); 1300 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 ); 1301 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1302 } 1303 1304 static void putDReg(UInt archreg, IRExpr* e) { 1305 vassert( archreg < 32 ); 1306 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 ); 1307 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1308 } 1309 1310 /* Write a 128-bit floating point value into a register pair. */ 1311 static void putDReg_pair(UInt archreg, IRExpr *e) { 1312 IRTemp low = newTemp( Ity_D64 ); 1313 IRTemp high = newTemp( Ity_D64 ); 1314 1315 vassert( archreg < 32 ); 1316 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 ); 1317 1318 assign( low, unop( Iop_D128LOtoD64, e ) ); 1319 assign( high, unop( Iop_D128HItoD64, e ) ); 1320 1321 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) ); 1322 stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) ); 1323 } 1324 1325 static Int vsxGuestRegOffset ( UInt archreg ) 1326 { 1327 vassert(archreg < 64); 1328 switch (archreg) { 1329 case 0: return offsetofPPCGuestState(guest_VSR0); 1330 case 1: return offsetofPPCGuestState(guest_VSR1); 1331 case 2: return offsetofPPCGuestState(guest_VSR2); 1332 case 3: return offsetofPPCGuestState(guest_VSR3); 1333 case 4: return offsetofPPCGuestState(guest_VSR4); 1334 case 5: return offsetofPPCGuestState(guest_VSR5); 1335 case 6: return offsetofPPCGuestState(guest_VSR6); 1336 case 7: return offsetofPPCGuestState(guest_VSR7); 1337 case 8: return offsetofPPCGuestState(guest_VSR8); 1338 case 9: return offsetofPPCGuestState(guest_VSR9); 1339 case 10: return offsetofPPCGuestState(guest_VSR10); 1340 case 11: return offsetofPPCGuestState(guest_VSR11); 1341 case 12: return offsetofPPCGuestState(guest_VSR12); 1342 case 13: return offsetofPPCGuestState(guest_VSR13); 1343 case 14: return offsetofPPCGuestState(guest_VSR14); 1344 case 15: return offsetofPPCGuestState(guest_VSR15); 1345 case 16: return offsetofPPCGuestState(guest_VSR16); 1346 case 17: return offsetofPPCGuestState(guest_VSR17); 1347 case 18: return offsetofPPCGuestState(guest_VSR18); 1348 case 19: return offsetofPPCGuestState(guest_VSR19); 1349 case 20: return offsetofPPCGuestState(guest_VSR20); 1350 case 21: return offsetofPPCGuestState(guest_VSR21); 1351 case 22: return offsetofPPCGuestState(guest_VSR22); 1352 case 23: return offsetofPPCGuestState(guest_VSR23); 1353 case 24: return offsetofPPCGuestState(guest_VSR24); 1354 case 25: return offsetofPPCGuestState(guest_VSR25); 1355 case 26: return offsetofPPCGuestState(guest_VSR26); 1356 case 27: return offsetofPPCGuestState(guest_VSR27); 1357 case 28: return offsetofPPCGuestState(guest_VSR28); 1358 case 29: return offsetofPPCGuestState(guest_VSR29); 1359 case 30: return offsetofPPCGuestState(guest_VSR30); 1360 case 31: return offsetofPPCGuestState(guest_VSR31); 1361 case 32: return offsetofPPCGuestState(guest_VSR32); 1362 case 33: return offsetofPPCGuestState(guest_VSR33); 1363 case 34: return offsetofPPCGuestState(guest_VSR34); 1364 case 35: return offsetofPPCGuestState(guest_VSR35); 1365 case 36: return offsetofPPCGuestState(guest_VSR36); 1366 case 37: return offsetofPPCGuestState(guest_VSR37); 1367 case 38: return offsetofPPCGuestState(guest_VSR38); 1368 case 39: return offsetofPPCGuestState(guest_VSR39); 1369 case 40: return offsetofPPCGuestState(guest_VSR40); 1370 case 41: return offsetofPPCGuestState(guest_VSR41); 1371 case 42: return offsetofPPCGuestState(guest_VSR42); 1372 case 43: return offsetofPPCGuestState(guest_VSR43); 1373 case 44: return offsetofPPCGuestState(guest_VSR44); 1374 case 45: return offsetofPPCGuestState(guest_VSR45); 1375 case 46: return offsetofPPCGuestState(guest_VSR46); 1376 case 47: return offsetofPPCGuestState(guest_VSR47); 1377 case 48: return offsetofPPCGuestState(guest_VSR48); 1378 case 49: return offsetofPPCGuestState(guest_VSR49); 1379 case 50: return offsetofPPCGuestState(guest_VSR50); 1380 case 51: return offsetofPPCGuestState(guest_VSR51); 1381 case 52: return offsetofPPCGuestState(guest_VSR52); 1382 case 53: return offsetofPPCGuestState(guest_VSR53); 1383 case 54: return offsetofPPCGuestState(guest_VSR54); 1384 case 55: return offsetofPPCGuestState(guest_VSR55); 1385 case 56: return offsetofPPCGuestState(guest_VSR56); 1386 case 57: return offsetofPPCGuestState(guest_VSR57); 1387 case 58: return offsetofPPCGuestState(guest_VSR58); 1388 case 59: return offsetofPPCGuestState(guest_VSR59); 1389 case 60: return offsetofPPCGuestState(guest_VSR60); 1390 case 61: return offsetofPPCGuestState(guest_VSR61); 1391 case 62: return offsetofPPCGuestState(guest_VSR62); 1392 case 63: return offsetofPPCGuestState(guest_VSR63); 1393 default: break; 1394 } 1395 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/ 1396 } 1397 1398 /* Vector registers are mapped to VSX registers[32..63]. */ 1399 static Int vectorGuestRegOffset ( UInt archreg ) 1400 { 1401 vassert(archreg < 32); 1402 1403 switch (archreg) { 1404 case 0: return offsetofPPCGuestState(guest_VSR32); 1405 case 1: return offsetofPPCGuestState(guest_VSR33); 1406 case 2: return offsetofPPCGuestState(guest_VSR34); 1407 case 3: return offsetofPPCGuestState(guest_VSR35); 1408 case 4: return offsetofPPCGuestState(guest_VSR36); 1409 case 5: return offsetofPPCGuestState(guest_VSR37); 1410 case 6: return offsetofPPCGuestState(guest_VSR38); 1411 case 7: return offsetofPPCGuestState(guest_VSR39); 1412 case 8: return offsetofPPCGuestState(guest_VSR40); 1413 case 9: return offsetofPPCGuestState(guest_VSR41); 1414 case 10: return offsetofPPCGuestState(guest_VSR42); 1415 case 11: return offsetofPPCGuestState(guest_VSR43); 1416 case 12: return offsetofPPCGuestState(guest_VSR44); 1417 case 13: return offsetofPPCGuestState(guest_VSR45); 1418 case 14: return offsetofPPCGuestState(guest_VSR46); 1419 case 15: return offsetofPPCGuestState(guest_VSR47); 1420 case 16: return offsetofPPCGuestState(guest_VSR48); 1421 case 17: return offsetofPPCGuestState(guest_VSR49); 1422 case 18: return offsetofPPCGuestState(guest_VSR50); 1423 case 19: return offsetofPPCGuestState(guest_VSR51); 1424 case 20: return offsetofPPCGuestState(guest_VSR52); 1425 case 21: return offsetofPPCGuestState(guest_VSR53); 1426 case 22: return offsetofPPCGuestState(guest_VSR54); 1427 case 23: return offsetofPPCGuestState(guest_VSR55); 1428 case 24: return offsetofPPCGuestState(guest_VSR56); 1429 case 25: return offsetofPPCGuestState(guest_VSR57); 1430 case 26: return offsetofPPCGuestState(guest_VSR58); 1431 case 27: return offsetofPPCGuestState(guest_VSR59); 1432 case 28: return offsetofPPCGuestState(guest_VSR60); 1433 case 29: return offsetofPPCGuestState(guest_VSR61); 1434 case 30: return offsetofPPCGuestState(guest_VSR62); 1435 case 31: return offsetofPPCGuestState(guest_VSR63); 1436 default: break; 1437 } 1438 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/ 1439 } 1440 1441 static IRExpr* getVReg ( UInt archreg ) 1442 { 1443 vassert(archreg < 32); 1444 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 ); 1445 } 1446 1447 /* Ditto, but write to a reg instead. */ 1448 static void putVReg ( UInt archreg, IRExpr* e ) 1449 { 1450 vassert(archreg < 32); 1451 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1452 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1453 } 1454 1455 /* Get contents of VSX guest register */ 1456 static IRExpr* getVSReg ( UInt archreg ) 1457 { 1458 vassert(archreg < 64); 1459 return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 ); 1460 } 1461 1462 /* Ditto, but write to a VSX reg instead. */ 1463 static void putVSReg ( UInt archreg, IRExpr* e ) 1464 { 1465 vassert(archreg < 64); 1466 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1467 stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) ); 1468 } 1469 1470 1471 static Int guestCR321offset ( UInt cr ) 1472 { 1473 switch (cr) { 1474 case 0: return offsetofPPCGuestState(guest_CR0_321 ); 1475 case 1: return offsetofPPCGuestState(guest_CR1_321 ); 1476 case 2: return offsetofPPCGuestState(guest_CR2_321 ); 1477 case 3: return offsetofPPCGuestState(guest_CR3_321 ); 1478 case 4: return offsetofPPCGuestState(guest_CR4_321 ); 1479 case 5: return offsetofPPCGuestState(guest_CR5_321 ); 1480 case 6: return offsetofPPCGuestState(guest_CR6_321 ); 1481 case 7: return offsetofPPCGuestState(guest_CR7_321 ); 1482 default: vpanic("guestCR321offset(ppc)"); 1483 } 1484 } 1485 1486 static Int guestCR0offset ( UInt cr ) 1487 { 1488 switch (cr) { 1489 case 0: return offsetofPPCGuestState(guest_CR0_0 ); 1490 case 1: return offsetofPPCGuestState(guest_CR1_0 ); 1491 case 2: return offsetofPPCGuestState(guest_CR2_0 ); 1492 case 3: return offsetofPPCGuestState(guest_CR3_0 ); 1493 case 4: return offsetofPPCGuestState(guest_CR4_0 ); 1494 case 5: return offsetofPPCGuestState(guest_CR5_0 ); 1495 case 6: return offsetofPPCGuestState(guest_CR6_0 ); 1496 case 7: return offsetofPPCGuestState(guest_CR7_0 ); 1497 default: vpanic("guestCR3offset(ppc)"); 1498 } 1499 } 1500 1501 typedef enum { 1502 _placeholder0, 1503 _placeholder1, 1504 _placeholder2, 1505 BYTE, 1506 HWORD, 1507 WORD, 1508 DWORD 1509 } _popcount_data_type; 1510 1511 /* Generate an IR sequence to do a popcount operation on the supplied 1512 IRTemp, and return a new IRTemp holding the result. 'ty' may be 1513 Ity_I32 or Ity_I64 only. */ 1514 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type ) 1515 { 1516 /* Do count across 2^data_type bits, 1517 byte: data_type = 3 1518 half word: data_type = 4 1519 word: data_type = 5 1520 double word: data_type = 6 (not supported for 32-bit type) 1521 */ 1522 Int shift[6]; 1523 _popcount_data_type idx, i; 1524 IRTemp mask[6]; 1525 IRTemp old = IRTemp_INVALID; 1526 IRTemp nyu = IRTemp_INVALID; 1527 1528 vassert(ty == Ity_I64 || ty == Ity_I32); 1529 1530 if (ty == Ity_I32) { 1531 1532 for (idx = 0; idx < WORD; idx++) { 1533 mask[idx] = newTemp(ty); 1534 shift[idx] = 1 << idx; 1535 } 1536 assign(mask[0], mkU32(0x55555555)); 1537 assign(mask[1], mkU32(0x33333333)); 1538 assign(mask[2], mkU32(0x0F0F0F0F)); 1539 assign(mask[3], mkU32(0x00FF00FF)); 1540 assign(mask[4], mkU32(0x0000FFFF)); 1541 old = src; 1542 for (i = 0; i < data_type; i++) { 1543 nyu = newTemp(ty); 1544 assign(nyu, 1545 binop(Iop_Add32, 1546 binop(Iop_And32, 1547 mkexpr(old), 1548 mkexpr(mask[i])), 1549 binop(Iop_And32, 1550 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1551 mkexpr(mask[i])))); 1552 old = nyu; 1553 } 1554 return nyu; 1555 } 1556 1557 // else, ty == Ity_I64 1558 vassert(mode64); 1559 1560 for (i = 0; i < DWORD; i++) { 1561 mask[i] = newTemp( Ity_I64 ); 1562 shift[i] = 1 << i; 1563 } 1564 assign( mask[0], mkU64( 0x5555555555555555ULL ) ); 1565 assign( mask[1], mkU64( 0x3333333333333333ULL ) ); 1566 assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) ); 1567 assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) ); 1568 assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) ); 1569 assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) ); 1570 old = src; 1571 for (i = 0; i < data_type; i++) { 1572 nyu = newTemp( Ity_I64 ); 1573 assign( nyu, 1574 binop( Iop_Add64, 1575 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ), 1576 binop( Iop_And64, 1577 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ), 1578 mkexpr( mask[i] ) ) ) ); 1579 old = nyu; 1580 } 1581 return nyu; 1582 } 1583 1584 /* Special purpose population count function for 1585 * vpopcntd in 32-bit mode. 1586 */ 1587 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 ) 1588 { 1589 Int i, shift[6]; 1590 IRTemp mask[6]; 1591 IRTemp old = IRTemp_INVALID; 1592 IRTemp nyu1 = IRTemp_INVALID; 1593 IRTemp nyu2 = IRTemp_INVALID; 1594 IRTemp retval = newTemp(Ity_I64); 1595 1596 vassert(!mode64); 1597 1598 for (i = 0; i < WORD; i++) { 1599 mask[i] = newTemp(Ity_I32); 1600 shift[i] = 1 << i; 1601 } 1602 assign(mask[0], mkU32(0x55555555)); 1603 assign(mask[1], mkU32(0x33333333)); 1604 assign(mask[2], mkU32(0x0F0F0F0F)); 1605 assign(mask[3], mkU32(0x00FF00FF)); 1606 assign(mask[4], mkU32(0x0000FFFF)); 1607 old = src1; 1608 for (i = 0; i < WORD; i++) { 1609 nyu1 = newTemp(Ity_I32); 1610 assign(nyu1, 1611 binop(Iop_Add32, 1612 binop(Iop_And32, 1613 mkexpr(old), 1614 mkexpr(mask[i])), 1615 binop(Iop_And32, 1616 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1617 mkexpr(mask[i])))); 1618 old = nyu1; 1619 } 1620 1621 old = src2; 1622 for (i = 0; i < WORD; i++) { 1623 nyu2 = newTemp(Ity_I32); 1624 assign(nyu2, 1625 binop(Iop_Add32, 1626 binop(Iop_And32, 1627 mkexpr(old), 1628 mkexpr(mask[i])), 1629 binop(Iop_And32, 1630 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1631 mkexpr(mask[i])))); 1632 old = nyu2; 1633 } 1634 assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2)))); 1635 return retval; 1636 } 1637 1638 1639 // ROTL(src32/64, rot_amt5/6) 1640 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src, 1641 IRExpr* rot_amt ) 1642 { 1643 IRExpr *mask, *rot; 1644 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8); 1645 1646 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) { 1647 // rot = (src << rot_amt) | (src >> (64-rot_amt)) 1648 mask = binop(Iop_And8, rot_amt, mkU8(63)); 1649 rot = binop(Iop_Or64, 1650 binop(Iop_Shl64, src, mask), 1651 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask))); 1652 } else { 1653 // rot = (src << rot_amt) | (src >> (32-rot_amt)) 1654 mask = binop(Iop_And8, rot_amt, mkU8(31)); 1655 rot = binop(Iop_Or32, 1656 binop(Iop_Shl32, src, mask), 1657 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask))); 1658 } 1659 /* Note: the ITE not merely an optimisation; it's needed 1660 because otherwise the Shr is a shift by the word size when 1661 mask denotes zero. For rotates by immediates, a lot of 1662 this junk gets folded out. */ 1663 return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)), 1664 /* non-zero rotate */ rot, 1665 /* zero rotate */ src); 1666 } 1667 1668 /* Standard effective address calc: (rA + rB) */ 1669 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB ) 1670 { 1671 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1672 vassert(rA < 32); 1673 vassert(rB < 32); 1674 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB)); 1675 } 1676 1677 /* Standard effective address calc: (rA + simm) */ 1678 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 ) 1679 { 1680 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1681 vassert(rA < 32); 1682 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), 1683 mkSzExtendS16(ty, simm16)); 1684 } 1685 1686 /* Standard effective address calc: (rA|0) */ 1687 static IRExpr* ea_rAor0 ( UInt rA ) 1688 { 1689 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1690 vassert(rA < 32); 1691 if (rA == 0) { 1692 return mkSzImm(ty, 0); 1693 } else { 1694 return getIReg(rA); 1695 } 1696 } 1697 1698 /* Standard effective address calc: (rA|0) + rB */ 1699 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB ) 1700 { 1701 vassert(rA < 32); 1702 vassert(rB < 32); 1703 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB ); 1704 } 1705 1706 /* Standard effective address calc: (rA|0) + simm16 */ 1707 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 ) 1708 { 1709 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1710 vassert(rA < 32); 1711 if (rA == 0) { 1712 return mkSzExtendS16(ty, simm16); 1713 } else { 1714 return ea_rA_simm( rA, simm16 ); 1715 } 1716 } 1717 1718 1719 /* Align effective address */ 1720 static IRExpr* addr_align( IRExpr* addr, UChar align ) 1721 { 1722 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1723 ULong mask; 1724 switch (align) { 1725 case 1: return addr; // byte aligned 1726 case 2: mask = ~0ULL << 1; break; // half-word aligned 1727 case 4: mask = ~0ULL << 2; break; // word aligned 1728 case 16: mask = ~0ULL << 4; break; // quad-word aligned 1729 default: 1730 vex_printf("addr_align: align = %u\n", align); 1731 vpanic("addr_align(ppc)"); 1732 } 1733 1734 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty); 1735 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) ); 1736 } 1737 1738 1739 /* Exit the trace if ADDR (intended to be a guest memory address) is 1740 not ALIGN-aligned, generating a request for a SIGBUS followed by a 1741 restart of the current insn. */ 1742 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align ) 1743 { 1744 vassert(align == 2 || align == 4 || align == 8 || align == 16); 1745 if (mode64) { 1746 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64); 1747 stmt( 1748 IRStmt_Exit( 1749 binop(Iop_CmpNE64, 1750 binop(Iop_And64, mkexpr(addr), mkU64(align-1)), 1751 mkU64(0)), 1752 Ijk_SigBUS, 1753 IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA 1754 ) 1755 ); 1756 } else { 1757 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32); 1758 stmt( 1759 IRStmt_Exit( 1760 binop(Iop_CmpNE32, 1761 binop(Iop_And32, mkexpr(addr), mkU32(align-1)), 1762 mkU32(0)), 1763 Ijk_SigBUS, 1764 IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA 1765 ) 1766 ); 1767 } 1768 } 1769 1770 1771 /* Generate AbiHints which mark points at which the ELF or PowerOpen 1772 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some 1773 N) becomes undefined. That is at function calls and returns. ELF 1774 ppc32 doesn't have this "feature" (how fortunate for it). nia is 1775 the address of the next instruction to be executed. 1776 */ 1777 static void make_redzone_AbiHint ( const VexAbiInfo* vbi, 1778 IRTemp nia, const HChar* who ) 1779 { 1780 Int szB = vbi->guest_stack_redzone_size; 1781 if (0) vex_printf("AbiHint: %s\n", who); 1782 vassert(szB >= 0); 1783 if (szB > 0) { 1784 if (mode64) { 1785 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64); 1786 stmt( IRStmt_AbiHint( 1787 binop(Iop_Sub64, getIReg(1), mkU64(szB)), 1788 szB, 1789 mkexpr(nia) 1790 )); 1791 } else { 1792 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32); 1793 stmt( IRStmt_AbiHint( 1794 binop(Iop_Sub32, getIReg(1), mkU32(szB)), 1795 szB, 1796 mkexpr(nia) 1797 )); 1798 } 1799 } 1800 } 1801 1802 1803 /*------------------------------------------------------------*/ 1804 /*--- Helpers for condition codes. ---*/ 1805 /*------------------------------------------------------------*/ 1806 1807 /* Condition register layout. 1808 1809 In the hardware, CR is laid out like this. The leftmost end is the 1810 most significant bit in the register; however the IBM documentation 1811 numbers the bits backwards for some reason. 1812 1813 CR0 CR1 .......... CR6 CR7 1814 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 1815 31 28 3 0 (normal bit numbering) 1816 1817 Each CR field is 4 bits: [<,>,==,SO] 1818 1819 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. 1820 1821 Indexing from BI to guest state: 1822 1823 let n = BI / 4 1824 off = BI % 4 1825 this references CR n: 1826 1827 off==0 -> guest_CRn_321 >> 3 1828 off==1 -> guest_CRn_321 >> 2 1829 off==2 -> guest_CRn_321 >> 1 1830 off==3 -> guest_CRn_SO 1831 1832 Bear in mind the only significant bit in guest_CRn_SO is bit 0 1833 (normal notation) and in guest_CRn_321 the significant bits are 1834 3, 2 and 1 (normal notation). 1835 */ 1836 1837 static void putCR321 ( UInt cr, IRExpr* e ) 1838 { 1839 vassert(cr < 8); 1840 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1841 stmt( IRStmt_Put(guestCR321offset(cr), e) ); 1842 } 1843 1844 static void putCR0 ( UInt cr, IRExpr* e ) 1845 { 1846 vassert(cr < 8); 1847 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1848 stmt( IRStmt_Put(guestCR0offset(cr), e) ); 1849 } 1850 1851 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) 1852 { 1853 vassert(cr < 8); 1854 return IRExpr_Get(guestCR0offset(cr), Ity_I8); 1855 } 1856 1857 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) 1858 { 1859 vassert(cr < 8); 1860 return IRExpr_Get(guestCR321offset(cr), Ity_I8); 1861 } 1862 1863 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1864 return it at the bottom of an I32; the top 31 bits are guaranteed 1865 to be zero. */ 1866 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi ) 1867 { 1868 UInt n = bi / 4; 1869 UInt off = bi % 4; 1870 vassert(bi < 32); 1871 if (off == 3) { 1872 /* Fetch the SO bit for this CR field */ 1873 /* Note: And32 is redundant paranoia iff guest state only has 0 1874 or 1 in that slot. */ 1875 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1876 } else { 1877 /* Fetch the <, > or == bit for this CR field */ 1878 return binop( Iop_And32, 1879 binop( Iop_Shr32, 1880 unop(Iop_8Uto32, getCR321(n)), 1881 mkU8(toUChar(3-off)) ), 1882 mkU32(1) ); 1883 } 1884 } 1885 1886 /* Dually, write the least significant bit of BIT to the specified CR 1887 bit. Indexing as per getCRbit. */ 1888 static void putCRbit ( UInt bi, IRExpr* bit ) 1889 { 1890 UInt n, off; 1891 IRExpr* safe; 1892 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32); 1893 safe = binop(Iop_And32, bit, mkU32(1)); 1894 n = bi / 4; 1895 off = bi % 4; 1896 vassert(bi < 32); 1897 if (off == 3) { 1898 /* This is the SO bit for this CR field */ 1899 putCR0(n, unop(Iop_32to8, safe)); 1900 } else { 1901 off = 3 - off; 1902 vassert(off == 1 || off == 2 || off == 3); 1903 putCR321( 1904 n, 1905 unop( Iop_32to8, 1906 binop( Iop_Or32, 1907 /* old value with field masked out */ 1908 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)), 1909 mkU32(~(1 << off))), 1910 /* new value in the right place */ 1911 binop(Iop_Shl32, safe, mkU8(toUChar(off))) 1912 ) 1913 ) 1914 ); 1915 } 1916 } 1917 1918 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1919 return it somewhere in an I32; it does not matter where, but 1920 whichever bit it is, all other bits are guaranteed to be zero. In 1921 other words, the I32-typed expression will be zero if the bit is 1922 zero and nonzero if the bit is 1. Write into *where the index 1923 of where the bit will be. */ 1924 1925 static 1926 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ) 1927 { 1928 UInt n = bi / 4; 1929 UInt off = bi % 4; 1930 vassert(bi < 32); 1931 if (off == 3) { 1932 /* Fetch the SO bit for this CR field */ 1933 /* Note: And32 is redundant paranoia iff guest state only has 0 1934 or 1 in that slot. */ 1935 *where = 0; 1936 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1937 } else { 1938 /* Fetch the <, > or == bit for this CR field */ 1939 *where = 3-off; 1940 return binop( Iop_And32, 1941 unop(Iop_8Uto32, getCR321(n)), 1942 mkU32(1 << (3-off)) ); 1943 } 1944 } 1945 1946 /* Set the CR0 flags following an arithmetic operation. 1947 (Condition Register CR0 Field Definition, PPC32 p60) 1948 */ 1949 static IRExpr* getXER_SO ( void ); 1950 static void set_CR0 ( IRExpr* result ) 1951 { 1952 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 || 1953 typeOfIRExpr(irsb->tyenv,result) == Ity_I64); 1954 if (mode64) { 1955 putCR321( 0, unop(Iop_64to8, 1956 binop(Iop_CmpORD64S, result, mkU64(0))) ); 1957 } else { 1958 putCR321( 0, unop(Iop_32to8, 1959 binop(Iop_CmpORD32S, result, mkU32(0))) ); 1960 } 1961 putCR0( 0, getXER_SO() ); 1962 } 1963 1964 1965 /* Set the CR6 flags following an AltiVec compare operation. 1966 * NOTE: This also works for VSX single-precision compares. 1967 * */ 1968 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) 1969 { 1970 /* CR6[0:3] = {all_ones, 0, all_zeros, 0} 1971 all_ones = (v[0] && v[1] && v[2] && v[3]) 1972 all_zeros = ~(v[0] || v[1] || v[2] || v[3]) 1973 */ 1974 IRTemp v0 = newTemp(Ity_V128); 1975 IRTemp v1 = newTemp(Ity_V128); 1976 IRTemp v2 = newTemp(Ity_V128); 1977 IRTemp v3 = newTemp(Ity_V128); 1978 IRTemp rOnes = newTemp(Ity_I8); 1979 IRTemp rZeros = newTemp(Ity_I8); 1980 1981 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128); 1982 1983 assign( v0, result ); 1984 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); 1985 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); 1986 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); 1987 1988 assign( rZeros, unop(Iop_1Uto8, 1989 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1990 unop(Iop_Not32, 1991 unop(Iop_V128to32, 1992 binop(Iop_OrV128, 1993 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), 1994 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) 1995 ))) ); 1996 1997 if (test_all_ones) { 1998 assign( rOnes, unop(Iop_1Uto8, 1999 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 2000 unop(Iop_V128to32, 2001 binop(Iop_AndV128, 2002 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), 2003 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))) 2004 ))) ); 2005 putCR321( 6, binop(Iop_Or8, 2006 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), 2007 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); 2008 } else { 2009 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); 2010 } 2011 putCR0( 6, mkU8(0) ); 2012 } 2013 2014 2015 2016 /*------------------------------------------------------------*/ 2017 /*--- Helpers for XER flags. ---*/ 2018 /*------------------------------------------------------------*/ 2019 2020 static void putXER_SO ( IRExpr* e ) 2021 { 2022 IRExpr* so; 2023 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2024 so = binop(Iop_And8, e, mkU8(1)); 2025 stmt( IRStmt_Put( OFFB_XER_SO, so ) ); 2026 } 2027 2028 static void putXER_OV ( IRExpr* e ) 2029 { 2030 IRExpr* ov; 2031 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2032 ov = binop(Iop_And8, e, mkU8(1)); 2033 stmt( IRStmt_Put( OFFB_XER_OV, ov ) ); 2034 } 2035 2036 static void putXER_CA ( IRExpr* e ) 2037 { 2038 IRExpr* ca; 2039 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2040 ca = binop(Iop_And8, e, mkU8(1)); 2041 stmt( IRStmt_Put( OFFB_XER_CA, ca ) ); 2042 } 2043 2044 static void putXER_BC ( IRExpr* e ) 2045 { 2046 IRExpr* bc; 2047 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 2048 bc = binop(Iop_And8, e, mkU8(0x7F)); 2049 stmt( IRStmt_Put( OFFB_XER_BC, bc ) ); 2050 } 2051 2052 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) 2053 { 2054 return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); 2055 } 2056 2057 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void ) 2058 { 2059 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) ); 2060 } 2061 2062 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ) 2063 { 2064 return IRExpr_Get( OFFB_XER_OV, Ity_I8 ); 2065 } 2066 2067 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void ) 2068 { 2069 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) ); 2070 } 2071 2072 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void ) 2073 { 2074 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 ); 2075 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 2076 } 2077 2078 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ) 2079 { 2080 return IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2081 } 2082 2083 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void ) 2084 { 2085 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 2086 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) ); 2087 } 2088 2089 2090 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and 2091 %XER.SO accordingly. */ 2092 2093 static void set_XER_OV_32( UInt op, IRExpr* res, 2094 IRExpr* argL, IRExpr* argR ) 2095 { 2096 IRTemp t64; 2097 IRExpr* xer_ov; 2098 vassert(op < PPCG_FLAG_OP_NUMBER); 2099 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2100 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2101 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2102 2103 # define INT32_MIN 0x80000000 2104 2105 # define XOR2(_aa,_bb) \ 2106 binop(Iop_Xor32,(_aa),(_bb)) 2107 2108 # define XOR3(_cc,_dd,_ee) \ 2109 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee)) 2110 2111 # define AND3(_ff,_gg,_hh) \ 2112 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh)) 2113 2114 #define NOT(_jj) \ 2115 unop(Iop_Not32, (_jj)) 2116 2117 switch (op) { 2118 case /* 0 */ PPCG_FLAG_OP_ADD: 2119 case /* 1 */ PPCG_FLAG_OP_ADDE: 2120 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */ 2121 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2122 xer_ov 2123 = AND3( XOR3(argL,argR,mkU32(-1)), 2124 XOR2(argL,res), 2125 mkU32(INT32_MIN) ); 2126 /* xer_ov can only be 0 or 1<<31 */ 2127 xer_ov 2128 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2129 break; 2130 2131 case /* 2 */ PPCG_FLAG_OP_DIVW: 2132 /* (argL == INT32_MIN && argR == -1) || argR == 0 */ 2133 xer_ov 2134 = mkOR1( 2135 mkAND1( 2136 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)), 2137 binop(Iop_CmpEQ32, argR, mkU32(-1)) 2138 ), 2139 binop(Iop_CmpEQ32, argR, mkU32(0) ) 2140 ); 2141 xer_ov 2142 = unop(Iop_1Uto32, xer_ov); 2143 break; 2144 2145 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2146 /* argR == 0 */ 2147 xer_ov 2148 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); 2149 break; 2150 2151 case /* 4 */ PPCG_FLAG_OP_MULLW: 2152 /* OV true if result can't be represented in 32 bits 2153 i.e sHi != sign extension of sLo */ 2154 t64 = newTemp(Ity_I64); 2155 assign( t64, binop(Iop_MullS32, argL, argR) ); 2156 xer_ov 2157 = binop( Iop_CmpNE32, 2158 unop(Iop_64HIto32, mkexpr(t64)), 2159 binop( Iop_Sar32, 2160 unop(Iop_64to32, mkexpr(t64)), 2161 mkU8(31)) 2162 ); 2163 xer_ov 2164 = unop(Iop_1Uto32, xer_ov); 2165 break; 2166 2167 case /* 5 */ PPCG_FLAG_OP_NEG: 2168 /* argL == INT32_MIN */ 2169 xer_ov 2170 = unop( Iop_1Uto32, 2171 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); 2172 break; 2173 2174 case /* 6 */ PPCG_FLAG_OP_SUBF: 2175 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2176 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2177 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */ 2178 xer_ov 2179 = AND3( XOR3(NOT(argL),argR,mkU32(-1)), 2180 XOR2(NOT(argL),res), 2181 mkU32(INT32_MIN) ); 2182 /* xer_ov can only be 0 or 1<<31 */ 2183 xer_ov 2184 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2185 break; 2186 2187 case PPCG_FLAG_OP_DIVWEU: 2188 xer_ov 2189 = binop( Iop_Or32, 2190 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2191 unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) ); 2192 break; 2193 2194 case PPCG_FLAG_OP_DIVWE: 2195 2196 /* If argR == 0 of if the result cannot fit in the 32-bit destination register, 2197 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero, 2198 * an overflow is implied. 2199 */ 2200 xer_ov = binop( Iop_Or32, 2201 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2202 unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ), 2203 mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ), 2204 binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) ); 2205 break; 2206 2207 2208 2209 default: 2210 vex_printf("set_XER_OV: op = %u\n", op); 2211 vpanic("set_XER_OV(ppc)"); 2212 } 2213 2214 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2215 putXER_OV( unop(Iop_32to8, xer_ov) ); 2216 2217 /* Update the summary overflow */ 2218 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2219 2220 # undef INT32_MIN 2221 # undef AND3 2222 # undef XOR3 2223 # undef XOR2 2224 # undef NOT 2225 } 2226 2227 static void set_XER_OV_64( UInt op, IRExpr* res, 2228 IRExpr* argL, IRExpr* argR ) 2229 { 2230 IRExpr* xer_ov; 2231 vassert(op < PPCG_FLAG_OP_NUMBER); 2232 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2233 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2234 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2235 2236 # define INT64_MIN 0x8000000000000000ULL 2237 2238 # define XOR2(_aa,_bb) \ 2239 binop(Iop_Xor64,(_aa),(_bb)) 2240 2241 # define XOR3(_cc,_dd,_ee) \ 2242 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee)) 2243 2244 # define AND3(_ff,_gg,_hh) \ 2245 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh)) 2246 2247 #define NOT(_jj) \ 2248 unop(Iop_Not64, (_jj)) 2249 2250 switch (op) { 2251 case /* 0 */ PPCG_FLAG_OP_ADD: 2252 case /* 1 */ PPCG_FLAG_OP_ADDE: 2253 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */ 2254 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2255 xer_ov 2256 = AND3( XOR3(argL,argR,mkU64(-1)), 2257 XOR2(argL,res), 2258 mkU64(INT64_MIN) ); 2259 /* xer_ov can only be 0 or 1<<63 */ 2260 xer_ov 2261 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2262 break; 2263 2264 case /* 2 */ PPCG_FLAG_OP_DIVW: 2265 /* (argL == INT64_MIN && argR == -1) || argR == 0 */ 2266 xer_ov 2267 = mkOR1( 2268 mkAND1( 2269 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)), 2270 binop(Iop_CmpEQ64, argR, mkU64(-1)) 2271 ), 2272 binop(Iop_CmpEQ64, argR, mkU64(0) ) 2273 ); 2274 break; 2275 2276 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2277 /* argR == 0 */ 2278 xer_ov 2279 = binop(Iop_CmpEQ64, argR, mkU64(0)); 2280 break; 2281 2282 case /* 4 */ PPCG_FLAG_OP_MULLW: { 2283 /* OV true if result can't be represented in 64 bits 2284 i.e sHi != sign extension of sLo */ 2285 xer_ov 2286 = binop( Iop_CmpNE32, 2287 unop(Iop_64HIto32, res), 2288 binop( Iop_Sar32, 2289 unop(Iop_64to32, res), 2290 mkU8(31)) 2291 ); 2292 break; 2293 } 2294 2295 case /* 5 */ PPCG_FLAG_OP_NEG: 2296 /* argL == INT64_MIN */ 2297 xer_ov 2298 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)); 2299 break; 2300 2301 case /* 6 */ PPCG_FLAG_OP_SUBF: 2302 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2303 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2304 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */ 2305 xer_ov 2306 = AND3( XOR3(NOT(argL),argR,mkU64(-1)), 2307 XOR2(NOT(argL),res), 2308 mkU64(INT64_MIN) ); 2309 /* xer_ov can only be 0 or 1<<63 */ 2310 xer_ov 2311 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2312 break; 2313 2314 case PPCG_FLAG_OP_DIVDE: 2315 2316 /* If argR == 0, we must set the OV bit. But there's another condition 2317 * where we can get overflow set for divde . . . when the 2318 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND 2319 * both dividend and divisor are non-zero, it implies an overflow. 2320 */ 2321 xer_ov 2322 = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2323 mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ), 2324 mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ), 2325 binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) ); 2326 break; 2327 2328 case PPCG_FLAG_OP_DIVDEU: 2329 /* If argR == 0 or if argL >= argR, set OV. */ 2330 xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2331 binop( Iop_CmpLE64U, argR, argL ) ); 2332 break; 2333 2334 case /* 18 */ PPCG_FLAG_OP_MULLD: { 2335 IRTemp t128; 2336 /* OV true if result can't be represented in 64 bits 2337 i.e sHi != sign extension of sLo */ 2338 t128 = newTemp(Ity_I128); 2339 assign( t128, binop(Iop_MullS64, argL, argR) ); 2340 xer_ov 2341 = binop( Iop_CmpNE64, 2342 unop(Iop_128HIto64, mkexpr(t128)), 2343 binop( Iop_Sar64, 2344 unop(Iop_128to64, mkexpr(t128)), 2345 mkU8(63)) 2346 ); 2347 break; 2348 } 2349 2350 default: 2351 vex_printf("set_XER_OV: op = %u\n", op); 2352 vpanic("set_XER_OV(ppc64)"); 2353 } 2354 2355 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2356 putXER_OV( unop(Iop_1Uto8, xer_ov) ); 2357 2358 /* Update the summary overflow */ 2359 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2360 2361 # undef INT64_MIN 2362 # undef AND3 2363 # undef XOR3 2364 # undef XOR2 2365 # undef NOT 2366 } 2367 2368 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res, 2369 IRExpr* argL, IRExpr* argR ) 2370 { 2371 if (ty == Ity_I32) 2372 set_XER_OV_32( op, res, argL, argR ); 2373 else 2374 set_XER_OV_64( op, res, argL, argR ); 2375 } 2376 2377 2378 2379 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA 2380 value being OLDCA. Set %XER.CA accordingly. */ 2381 2382 static void set_XER_CA_32 ( UInt op, IRExpr* res, 2383 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2384 { 2385 IRExpr* xer_ca; 2386 vassert(op < PPCG_FLAG_OP_NUMBER); 2387 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2388 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2389 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2390 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32); 2391 2392 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2393 seems reasonable given that it's always generated by 2394 getXER_CA32(), which masks it accordingly. In any case it being 2395 0 or 1 is an invariant of the ppc guest state representation; 2396 if it has any other value, that invariant has been violated. */ 2397 2398 switch (op) { 2399 case /* 0 */ PPCG_FLAG_OP_ADD: 2400 /* res <u argL */ 2401 xer_ca 2402 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); 2403 break; 2404 2405 case /* 1 */ PPCG_FLAG_OP_ADDE: 2406 /* res <u argL || (old_ca==1 && res==argL) */ 2407 xer_ca 2408 = mkOR1( 2409 binop(Iop_CmpLT32U, res, argL), 2410 mkAND1( 2411 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2412 binop(Iop_CmpEQ32, res, argL) 2413 ) 2414 ); 2415 xer_ca 2416 = unop(Iop_1Uto32, xer_ca); 2417 break; 2418 2419 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2420 /* res <u argR || (old_ca==1 && res==argR) */ 2421 xer_ca 2422 = mkOR1( 2423 binop(Iop_CmpLT32U, res, argR), 2424 mkAND1( 2425 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2426 binop(Iop_CmpEQ32, res, argR) 2427 ) 2428 ); 2429 xer_ca 2430 = unop(Iop_1Uto32, xer_ca); 2431 break; 2432 2433 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2434 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2435 /* res <=u argR */ 2436 xer_ca 2437 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); 2438 break; 2439 2440 case /* 10 */ PPCG_FLAG_OP_SRAW: 2441 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2442 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2443 bit of argL. */ 2444 /* This term valid for shift amount < 32 only */ 2445 xer_ca 2446 = binop( 2447 Iop_And32, 2448 binop(Iop_Sar32, argL, mkU8(31)), 2449 binop( Iop_And32, 2450 argL, 2451 binop( Iop_Sub32, 2452 binop(Iop_Shl32, mkU32(1), 2453 unop(Iop_32to8,argR)), 2454 mkU32(1) ) 2455 ) 2456 ); 2457 xer_ca 2458 = IRExpr_ITE( 2459 /* shift amt > 31 ? */ 2460 binop(Iop_CmpLT32U, mkU32(31), argR), 2461 /* yes -- get sign bit of argL */ 2462 binop(Iop_Shr32, argL, mkU8(31)), 2463 /* no -- be like srawi */ 2464 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))) 2465 ); 2466 break; 2467 2468 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2469 /* xer_ca is 1 iff src was negative and bits_shifted_out != 2470 0. Since the shift amount is known to be in the range 2471 0 .. 31 inclusive the following seems viable: 2472 xer.ca == 1 iff the following is nonzero: 2473 (argL >>s 31) -- either all 0s or all 1s 2474 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2475 xer_ca 2476 = binop( 2477 Iop_And32, 2478 binop(Iop_Sar32, argL, mkU8(31)), 2479 binop( Iop_And32, 2480 argL, 2481 binop( Iop_Sub32, 2482 binop(Iop_Shl32, mkU32(1), 2483 unop(Iop_32to8,argR)), 2484 mkU32(1) ) 2485 ) 2486 ); 2487 xer_ca 2488 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); 2489 break; 2490 2491 default: 2492 vex_printf("set_XER_CA: op = %u\n", op); 2493 vpanic("set_XER_CA(ppc)"); 2494 } 2495 2496 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2497 putXER_CA( unop(Iop_32to8, xer_ca) ); 2498 } 2499 2500 static void set_XER_CA_64 ( UInt op, IRExpr* res, 2501 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2502 { 2503 IRExpr* xer_ca; 2504 vassert(op < PPCG_FLAG_OP_NUMBER); 2505 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2506 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2507 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2508 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64); 2509 2510 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2511 seems reasonable given that it's always generated by 2512 getXER_CA32(), which masks it accordingly. In any case it being 2513 0 or 1 is an invariant of the ppc guest state representation; 2514 if it has any other value, that invariant has been violated. */ 2515 2516 switch (op) { 2517 case /* 0 */ PPCG_FLAG_OP_ADD: 2518 /* res <u argL */ 2519 xer_ca 2520 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL)); 2521 break; 2522 2523 case /* 1 */ PPCG_FLAG_OP_ADDE: 2524 /* res <u argL || (old_ca==1 && res==argL) */ 2525 xer_ca 2526 = mkOR1( 2527 binop(Iop_CmpLT64U, res, argL), 2528 mkAND1( 2529 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2530 binop(Iop_CmpEQ64, res, argL) 2531 ) 2532 ); 2533 xer_ca 2534 = unop(Iop_1Uto32, xer_ca); 2535 break; 2536 2537 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2538 /* res <u argR || (old_ca==1 && res==argR) */ 2539 xer_ca 2540 = mkOR1( 2541 binop(Iop_CmpLT64U, res, argR), 2542 mkAND1( 2543 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2544 binop(Iop_CmpEQ64, res, argR) 2545 ) 2546 ); 2547 xer_ca 2548 = unop(Iop_1Uto32, xer_ca); 2549 break; 2550 2551 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2552 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2553 /* res <=u argR */ 2554 xer_ca 2555 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR)); 2556 break; 2557 2558 2559 case /* 10 */ PPCG_FLAG_OP_SRAW: 2560 /* The shift amount is guaranteed to be in 0 .. 31 inclusive. 2561 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2562 bit of argL. */ 2563 /* This term valid for shift amount < 31 only */ 2564 2565 xer_ca 2566 = binop( 2567 Iop_And64, 2568 binop(Iop_Sar64, argL, mkU8(31)), 2569 binop( Iop_And64, 2570 argL, 2571 binop( Iop_Sub64, 2572 binop(Iop_Shl64, mkU64(1), 2573 unop(Iop_64to8,argR)), 2574 mkU64(1) ) 2575 ) 2576 ); 2577 xer_ca 2578 = IRExpr_ITE( 2579 /* shift amt > 31 ? */ 2580 binop(Iop_CmpLT64U, mkU64(31), argR), 2581 /* yes -- get sign bit of argL */ 2582 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2583 /* no -- be like srawi */ 2584 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2585 ); 2586 break; 2587 2588 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2589 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2590 Since the shift amount is known to be in the range 0 .. 31 2591 inclusive the following seems viable: 2592 xer.ca == 1 iff the following is nonzero: 2593 (argL >>s 31) -- either all 0s or all 1s 2594 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2595 2596 xer_ca 2597 = binop( 2598 Iop_And64, 2599 binop(Iop_Sar64, argL, mkU8(31)), 2600 binop( Iop_And64, 2601 argL, 2602 binop( Iop_Sub64, 2603 binop(Iop_Shl64, mkU64(1), 2604 unop(Iop_64to8,argR)), 2605 mkU64(1) ) 2606 ) 2607 ); 2608 xer_ca 2609 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2610 break; 2611 2612 2613 case /* 12 */ PPCG_FLAG_OP_SRAD: 2614 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2615 If it is <= 63, behave like SRADI; else XER.CA is the sign 2616 bit of argL. */ 2617 /* This term valid for shift amount < 63 only */ 2618 2619 xer_ca 2620 = binop( 2621 Iop_And64, 2622 binop(Iop_Sar64, argL, mkU8(63)), 2623 binop( Iop_And64, 2624 argL, 2625 binop( Iop_Sub64, 2626 binop(Iop_Shl64, mkU64(1), 2627 unop(Iop_64to8,argR)), 2628 mkU64(1) ) 2629 ) 2630 ); 2631 xer_ca 2632 = IRExpr_ITE( 2633 /* shift amt > 63 ? */ 2634 binop(Iop_CmpLT64U, mkU64(63), argR), 2635 /* yes -- get sign bit of argL */ 2636 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2637 /* no -- be like sradi */ 2638 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2639 ); 2640 break; 2641 2642 2643 case /* 13 */ PPCG_FLAG_OP_SRADI: 2644 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2645 Since the shift amount is known to be in the range 0 .. 63 2646 inclusive, the following seems viable: 2647 xer.ca == 1 iff the following is nonzero: 2648 (argL >>s 63) -- either all 0s or all 1s 2649 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2650 2651 xer_ca 2652 = binop( 2653 Iop_And64, 2654 binop(Iop_Sar64, argL, mkU8(63)), 2655 binop( Iop_And64, 2656 argL, 2657 binop( Iop_Sub64, 2658 binop(Iop_Shl64, mkU64(1), 2659 unop(Iop_64to8,argR)), 2660 mkU64(1) ) 2661 ) 2662 ); 2663 xer_ca 2664 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2665 break; 2666 2667 default: 2668 vex_printf("set_XER_CA: op = %u\n", op); 2669 vpanic("set_XER_CA(ppc64)"); 2670 } 2671 2672 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2673 putXER_CA( unop(Iop_32to8, xer_ca) ); 2674 } 2675 2676 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res, 2677 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2678 { 2679 if (ty == Ity_I32) 2680 set_XER_CA_32( op, res, argL, argR, oldca ); 2681 else 2682 set_XER_CA_64( op, res, argL, argR, oldca ); 2683 } 2684 2685 2686 2687 /*------------------------------------------------------------*/ 2688 /*--- Read/write to guest-state --- */ 2689 /*------------------------------------------------------------*/ 2690 2691 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg ) 2692 { 2693 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2694 switch (reg) { 2695 case PPC_GST_SPRG3_RO: 2696 return IRExpr_Get( OFFB_SPRG3_RO, ty ); 2697 2698 case PPC_GST_CIA: 2699 return IRExpr_Get( OFFB_CIA, ty ); 2700 2701 case PPC_GST_LR: 2702 return IRExpr_Get( OFFB_LR, ty ); 2703 2704 case PPC_GST_CTR: 2705 return IRExpr_Get( OFFB_CTR, ty ); 2706 2707 case PPC_GST_VRSAVE: 2708 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); 2709 2710 case PPC_GST_VSCR: 2711 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ), 2712 mkU32(MASK_VSCR_VALID)); 2713 2714 case PPC_GST_CR: { 2715 /* Synthesise the entire CR into a single word. Expensive. */ 2716 # define FIELD(_n) \ 2717 binop(Iop_Shl32, \ 2718 unop(Iop_8Uto32, \ 2719 binop(Iop_Or8, \ 2720 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ 2721 binop(Iop_And8, getCR0(_n), mkU8(1)) \ 2722 ) \ 2723 ), \ 2724 mkU8(4 * (7-(_n))) \ 2725 ) 2726 return binop(Iop_Or32, 2727 binop(Iop_Or32, 2728 binop(Iop_Or32, FIELD(0), FIELD(1)), 2729 binop(Iop_Or32, FIELD(2), FIELD(3)) 2730 ), 2731 binop(Iop_Or32, 2732 binop(Iop_Or32, FIELD(4), FIELD(5)), 2733 binop(Iop_Or32, FIELD(6), FIELD(7)) 2734 ) 2735 ); 2736 # undef FIELD 2737 } 2738 2739 case PPC_GST_XER: 2740 return binop(Iop_Or32, 2741 binop(Iop_Or32, 2742 binop( Iop_Shl32, getXER_SO32(), mkU8(31)), 2743 binop( Iop_Shl32, getXER_OV32(), mkU8(30))), 2744 binop(Iop_Or32, 2745 binop( Iop_Shl32, getXER_CA32(), mkU8(29)), 2746 getXER_BC32())); 2747 2748 case PPC_GST_TFHAR: 2749 return IRExpr_Get( OFFB_TFHAR, ty ); 2750 2751 case PPC_GST_TEXASR: 2752 return IRExpr_Get( OFFB_TEXASR, ty ); 2753 2754 case PPC_GST_TEXASRU: 2755 return IRExpr_Get( OFFB_TEXASRU, ty ); 2756 2757 case PPC_GST_TFIAR: 2758 return IRExpr_Get( OFFB_TFIAR, ty ); 2759 2760 case PPC_GST_PPR: 2761 return IRExpr_Get( OFFB_PPR, ty ); 2762 2763 case PPC_GST_PPR32: 2764 return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) ); 2765 2766 case PPC_GST_PSPB: 2767 return IRExpr_Get( OFFB_PSPB, ty ); 2768 2769 default: 2770 vex_printf("getGST(ppc): reg = %u", reg); 2771 vpanic("getGST(ppc)"); 2772 } 2773 } 2774 2775 /* Get a masked word from the given reg */ 2776 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask ) 2777 { 2778 IRTemp val = newTemp(Ity_I32); 2779 vassert( reg < PPC_GST_MAX ); 2780 2781 switch (reg) { 2782 2783 case PPC_GST_FPSCR: { 2784 /* Vex-generated code expects the FPSCR to be set as follows: 2785 all exceptions masked, round-to-nearest. 2786 This corresponds to a FPSCR value of 0x0. */ 2787 2788 /* In the lower 32 bits of FPSCR, we're only keeping track of 2789 * the binary floating point rounding mode, so if the mask isn't 2790 * asking for this, just return 0x0. 2791 */ 2792 if (mask & MASK_FPSCR_RN) { 2793 assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) ); 2794 } else { 2795 assign( val, mkU32(0x0) ); 2796 } 2797 break; 2798 } 2799 2800 default: 2801 vex_printf("getGST_masked(ppc): reg = %u", reg); 2802 vpanic("getGST_masked(ppc)"); 2803 } 2804 2805 if (mask != 0xFFFFFFFF) { 2806 return binop(Iop_And32, mkexpr(val), mkU32(mask)); 2807 } else { 2808 return mkexpr(val); 2809 } 2810 } 2811 2812 /* Get a masked word from the given reg */ 2813 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) { 2814 IRExpr * val; 2815 vassert( reg < PPC_GST_MAX ); 2816 2817 switch (reg) { 2818 2819 case PPC_GST_FPSCR: { 2820 /* In the upper 32 bits of FPSCR, we're only keeping track 2821 * of the decimal floating point rounding mode, so if the mask 2822 * isn't asking for this, just return 0x0. 2823 */ 2824 if (mask & MASK_FPSCR_DRN) { 2825 val = binop( Iop_And32, 2826 unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ), 2827 unop( Iop_64HIto32, mkU64( mask ) ) ); 2828 } else { 2829 val = mkU32( 0x0ULL ); 2830 } 2831 break; 2832 } 2833 2834 default: 2835 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg ); 2836 vpanic( "getGST_masked_upper(ppc)" ); 2837 } 2838 return val; 2839 } 2840 2841 2842 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation) 2843 and return it at the bottom of an I32; the top 27 bits are 2844 guaranteed to be zero. */ 2845 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld ) 2846 { 2847 UInt shft, mask; 2848 2849 vassert( fld < 8 ); 2850 vassert( reg < PPC_GST_MAX ); 2851 2852 shft = 4*(7-fld); 2853 mask = 0xF<<shft; 2854 2855 switch (reg) { 2856 case PPC_GST_XER: 2857 vassert(fld ==7); 2858 return binop(Iop_Or32, 2859 binop(Iop_Or32, 2860 binop(Iop_Shl32, getXER_SO32(), mkU8(3)), 2861 binop(Iop_Shl32, getXER_OV32(), mkU8(2))), 2862 binop( Iop_Shl32, getXER_CA32(), mkU8(1))); 2863 break; 2864 2865 default: 2866 if (shft == 0) 2867 return getGST_masked( reg, mask ); 2868 else 2869 return binop(Iop_Shr32, 2870 getGST_masked( reg, mask ), 2871 mkU8(toUChar( shft ))); 2872 } 2873 } 2874 2875 static void putGST ( PPC_GST reg, IRExpr* src ) 2876 { 2877 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2878 IRType ty_src = typeOfIRExpr(irsb->tyenv,src ); 2879 vassert( reg < PPC_GST_MAX ); 2880 switch (reg) { 2881 case PPC_GST_IP_AT_SYSCALL: 2882 vassert( ty_src == ty ); 2883 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) ); 2884 break; 2885 case PPC_GST_CIA: 2886 vassert( ty_src == ty ); 2887 stmt( IRStmt_Put( OFFB_CIA, src ) ); 2888 break; 2889 case PPC_GST_LR: 2890 vassert( ty_src == ty ); 2891 stmt( IRStmt_Put( OFFB_LR, src ) ); 2892 break; 2893 case PPC_GST_CTR: 2894 vassert( ty_src == ty ); 2895 stmt( IRStmt_Put( OFFB_CTR, src ) ); 2896 break; 2897 case PPC_GST_VRSAVE: 2898 vassert( ty_src == Ity_I32 ); 2899 stmt( IRStmt_Put( OFFB_VRSAVE,src)); 2900 break; 2901 case PPC_GST_VSCR: 2902 vassert( ty_src == Ity_I32 ); 2903 stmt( IRStmt_Put( OFFB_VSCR, 2904 binop(Iop_And32, src, 2905 mkU32(MASK_VSCR_VALID)) ) ); 2906 break; 2907 case PPC_GST_XER: 2908 vassert( ty_src == Ity_I32 ); 2909 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) ); 2910 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) ); 2911 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) ); 2912 putXER_BC( unop(Iop_32to8, src) ); 2913 break; 2914 2915 case PPC_GST_EMWARN: 2916 vassert( ty_src == Ity_I32 ); 2917 stmt( IRStmt_Put( OFFB_EMNOTE,src) ); 2918 break; 2919 2920 case PPC_GST_CMSTART: 2921 vassert( ty_src == ty ); 2922 stmt( IRStmt_Put( OFFB_CMSTART, src) ); 2923 break; 2924 2925 case PPC_GST_CMLEN: 2926 vassert( ty_src == ty ); 2927 stmt( IRStmt_Put( OFFB_CMLEN, src) ); 2928 break; 2929 2930 case PPC_GST_TEXASR: 2931 vassert( ty_src == Ity_I64 ); 2932 stmt( IRStmt_Put( OFFB_TEXASR, src ) ); 2933 break; 2934 2935 case PPC_GST_TEXASRU: 2936 vassert( ty_src == Ity_I32 ); 2937 stmt( IRStmt_Put( OFFB_TEXASRU, src ) ); 2938 break; 2939 2940 case PPC_GST_TFIAR: 2941 vassert( ty_src == Ity_I64 ); 2942 stmt( IRStmt_Put( OFFB_TFIAR, src ) ); 2943 break; 2944 case PPC_GST_TFHAR: 2945 vassert( ty_src == Ity_I64 ); 2946 stmt( IRStmt_Put( OFFB_TFHAR, src ) ); 2947 break; 2948 2949 case PPC_GST_PPR32: 2950 case PPC_GST_PPR: 2951 { 2952 /* The Program Priority Register (PPR) stores the priority in 2953 * bits [52:50]. The user setable priorities are: 2954 * 2955 * 001 very low 2956 * 010 low 2957 * 011 medium low 2958 * 100 medium 2959 * 101 medium high 2960 * 2961 * If the argument is not between 0b001 and 0b100 the priority is set 2962 * to 0b100. The priority can only be set to 0b101 if the the Problem 2963 * State Boost Register is non-zero. The value of the PPR is not 2964 * changed if the input is not valid. 2965 */ 2966 2967 IRTemp not_valid = newTemp(Ity_I64); 2968 IRTemp has_perm = newTemp(Ity_I64); 2969 IRTemp new_src = newTemp(Ity_I64); 2970 IRTemp PSPB_val = newTemp(Ity_I64); 2971 IRTemp value = newTemp(Ity_I64); 2972 2973 vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 )); 2974 assign( PSPB_val, binop( Iop_32HLto64, 2975 mkU32( 0 ), 2976 IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) ); 2977 if( reg == PPC_GST_PPR32 ) { 2978 vassert( ty_src == Ity_I32 ); 2979 assign( value, binop( Iop_32HLto64, 2980 mkU32(0), 2981 binop( Iop_And32, 2982 binop( Iop_Shr32, src, mkU8( 18 ) ), 2983 mkU32( 0x7 ) ) ) ); 2984 } else { 2985 vassert( ty_src == Ity_I64 ); 2986 assign( value, binop( Iop_And64, 2987 binop( Iop_Shr64, src, mkU8( 50 ) ), 2988 mkU64( 0x7 ) ) ); 2989 } 2990 assign( has_perm, 2991 binop( Iop_And64, 2992 unop( Iop_1Sto64, 2993 binop( Iop_CmpEQ64, 2994 mkexpr( PSPB_val ), 2995 mkU64( 0 ) ) ), 2996 unop( Iop_1Sto64, 2997 binop( Iop_CmpEQ64, 2998 mkU64( 0x5 ), 2999 mkexpr( value ) ) ) ) ); 3000 assign( not_valid, 3001 binop( Iop_Or64, 3002 unop( Iop_1Sto64, 3003 binop( Iop_CmpEQ64, 3004 mkexpr( value ), 3005 mkU64( 0 ) ) ), 3006 unop( Iop_1Sto64, 3007 binop( Iop_CmpLT64U, 3008 mkU64( 0x5 ), 3009 mkexpr( value ) ) ) ) ); 3010 assign( new_src, 3011 binop( Iop_Or64, 3012 binop( Iop_And64, 3013 unop( Iop_Not64, 3014 mkexpr( not_valid ) ), 3015 src ), 3016 binop( Iop_And64, 3017 mkexpr( not_valid ), 3018 binop( Iop_Or64, 3019 binop( Iop_And64, 3020 mkexpr( has_perm), 3021 binop( Iop_Shl64, 3022 mkexpr( value ), 3023 mkU8( 50 ) ) ), 3024 binop( Iop_And64, 3025 IRExpr_Get( OFFB_PPR, ty ), 3026 unop( Iop_Not64, 3027 mkexpr( has_perm ) 3028 ) ) ) ) ) ); 3029 3030 /* make sure we only set the valid bit field [52:50] */ 3031 stmt( IRStmt_Put( OFFB_PPR, 3032 binop( Iop_And64, 3033 mkexpr( new_src ), 3034 mkU64( 0x1C000000000000) ) ) ); 3035 break; 3036 } 3037 default: 3038 vex_printf("putGST(ppc): reg = %u", reg); 3039 vpanic("putGST(ppc)"); 3040 } 3041 } 3042 3043 /* Write masked src to the given reg */ 3044 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask ) 3045 { 3046 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3047 vassert( reg < PPC_GST_MAX ); 3048 vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 ); 3049 3050 switch (reg) { 3051 case PPC_GST_FPSCR: { 3052 /* Allow writes to either binary or decimal floating point 3053 Rounding Mode. 3054 */ 3055 /* If any part of |mask| covers FPSCR.RN, update the bits of 3056 FPSCR.RN by copying in |src| for locations where the 3057 corresponding bit in |mask| is 1, and leaving it unchanged 3058 for corresponding |mask| zero bits. */ 3059 if (mask & MASK_FPSCR_RN) { 3060 stmt( 3061 IRStmt_Put( 3062 OFFB_FPROUND, 3063 unop( 3064 Iop_32to8, 3065 binop( 3066 Iop_Or32, 3067 binop( 3068 Iop_And32, 3069 unop(Iop_64to32, src), 3070 mkU32(MASK_FPSCR_RN & mask) 3071 ), 3072 binop( 3073 Iop_And32, 3074 unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)), 3075 mkU32(MASK_FPSCR_RN & ~mask) 3076 ) 3077 ) 3078 ) 3079 ) 3080 ); 3081 } 3082 /* Similarly, update FPSCR.DRN if any bits of |mask| 3083 corresponding to FPSCR.DRN are set. */ 3084 if (mask & MASK_FPSCR_DRN) { 3085 stmt( 3086 IRStmt_Put( 3087 OFFB_DFPROUND, 3088 unop( 3089 Iop_32to8, 3090 binop( 3091 Iop_Or32, 3092 binop( 3093 Iop_And32, 3094 unop(Iop_64HIto32, src), 3095 mkU32((MASK_FPSCR_DRN & mask) >> 32) 3096 ), 3097 binop( 3098 Iop_And32, 3099 unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)), 3100 mkU32((MASK_FPSCR_DRN & ~mask) >> 32) 3101 ) 3102 ) 3103 ) 3104 ) 3105 ); 3106 } 3107 3108 /* Give EmNote for attempted writes to: 3109 - Exception Controls 3110 - Non-IEEE Mode 3111 */ 3112 if (mask & 0xFC) { // Exception Control, Non-IEE mode 3113 VexEmNote ew = EmWarn_PPCexns; 3114 3115 /* If any of the src::exception_control bits are actually set, 3116 side-exit to the next insn, reporting the warning, 3117 so that Valgrind's dispatcher sees the warning. */ 3118 putGST( PPC_GST_EMWARN, mkU32(ew) ); 3119 stmt( 3120 IRStmt_Exit( 3121 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)), 3122 Ijk_EmWarn, 3123 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 3124 } 3125 3126 /* Ignore all other writes */ 3127 break; 3128 } 3129 3130 default: 3131 vex_printf("putGST_masked(ppc): reg = %u", reg); 3132 vpanic("putGST_masked(ppc)"); 3133 } 3134 } 3135 3136 /* Write the least significant nibble of src to the specified 3137 REG[FLD] (as per IBM/hardware notation). */ 3138 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld ) 3139 { 3140 UInt shft; 3141 ULong mask; 3142 3143 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 3144 vassert( fld < 16 ); 3145 vassert( reg < PPC_GST_MAX ); 3146 3147 if (fld < 8) 3148 shft = 4*(7-fld); 3149 else 3150 shft = 4*(15-fld); 3151 mask = 0xF; 3152 mask = mask << shft; 3153 3154 switch (reg) { 3155 case PPC_GST_CR: 3156 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src))); 3157 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src))); 3158 break; 3159 3160 default: 3161 { 3162 IRExpr * src64 = unop( Iop_32Uto64, src ); 3163 3164 if (shft == 0) { 3165 putGST_masked( reg, src64, mask ); 3166 } else { 3167 putGST_masked( reg, 3168 binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ), 3169 mask ); 3170 } 3171 } 3172 } 3173 } 3174 3175 /*------------------------------------------------------------*/ 3176 /* Helpers for VSX instructions that do floating point 3177 * operations and need to determine if a src contains a 3178 * special FP value. 3179 * 3180 *------------------------------------------------------------*/ 3181 3182 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL 3183 #define FP_FRAC_PART(x) binop( Iop_And64, \ 3184 mkexpr( x ), \ 3185 mkU64( NONZERO_FRAC_MASK ) ) 3186 3187 // Returns exponent part of a single precision floating point as I32 3188 static IRExpr * fp_exp_part_sp(IRTemp src) 3189 { 3190 return binop( Iop_And32, 3191 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 3192 mkU32( 0xff ) ); 3193 } 3194 3195 // Returns exponent part of floating point as I32 3196 static IRExpr * fp_exp_part(IRTemp src, Bool sp) 3197 { 3198 IRExpr * exp; 3199 if (sp) 3200 return fp_exp_part_sp(src); 3201 3202 if (!mode64) 3203 exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32, 3204 mkexpr( src ) ), 3205 mkU8( 20 ) ), mkU32( 0x7ff ) ); 3206 else 3207 exp = unop( Iop_64to32, 3208 binop( Iop_And64, 3209 binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ), 3210 mkU64( 0x7ff ) ) ); 3211 return exp; 3212 } 3213 3214 static IRExpr * is_Inf_sp(IRTemp src) 3215 { 3216 IRTemp frac_part = newTemp(Ity_I32); 3217 IRExpr * Inf_exp; 3218 3219 assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) ); 3220 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) ); 3221 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) ); 3222 } 3223 3224 3225 // Infinity: exp = 7ff and fraction is zero; s = 0/1 3226 static IRExpr * is_Inf(IRTemp src, Bool sp) 3227 { 3228 IRExpr * Inf_exp, * hi32, * low32; 3229 IRTemp frac_part; 3230 3231 if (sp) 3232 return is_Inf_sp(src); 3233 3234 frac_part = newTemp(Ity_I64); 3235 assign( frac_part, FP_FRAC_PART(src) ); 3236 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), mkU32( 0x7ff ) ); 3237 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 3238 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 3239 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 3240 mkU32( 0 ) ) ); 3241 } 3242 3243 static IRExpr * is_Zero_sp(IRTemp src) 3244 { 3245 IRTemp sign_less_part = newTemp(Ity_I32); 3246 assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) ); 3247 return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) ); 3248 } 3249 3250 // Zero: exp is zero and fraction is zero; s = 0/1 3251 static IRExpr * is_Zero(IRTemp src, Bool sp) 3252 { 3253 IRExpr * hi32, * low32; 3254 IRTemp sign_less_part; 3255 if (sp) 3256 return is_Zero_sp(src); 3257 3258 sign_less_part = newTemp(Ity_I64); 3259 3260 assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) ); 3261 hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) ); 3262 low32 = unop( Iop_64to32, mkexpr( sign_less_part ) ); 3263 return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 3264 mkU32( 0 ) ); 3265 } 3266 3267 /* SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1' 3268 * QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0' 3269 * This function returns an IRExpr value of '1' for any type of NaN. 3270 */ 3271 static IRExpr * is_NaN(IRTemp src) 3272 { 3273 IRExpr * NaN_exp, * hi32, * low32; 3274 IRTemp frac_part = newTemp(Ity_I64); 3275 3276 assign( frac_part, FP_FRAC_PART(src) ); 3277 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 3278 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 3279 NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), 3280 mkU32( 0x7ff ) ); 3281 3282 return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 3283 mkU32( 0 ) ) ); 3284 } 3285 3286 /* This function returns an IRExpr value of '1' for any type of NaN. 3287 * The passed 'src' argument is assumed to be Ity_I32. 3288 */ 3289 static IRExpr * is_NaN_32(IRTemp src) 3290 { 3291 #define NONZERO_FRAC_MASK32 0x007fffffULL 3292 #define FP_FRAC_PART32(x) binop( Iop_And32, \ 3293 mkexpr( x ), \ 3294 mkU32( NONZERO_FRAC_MASK32 ) ) 3295 3296 IRExpr * frac_part = FP_FRAC_PART32(src); 3297 IRExpr * exp_part = binop( Iop_And32, 3298 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 3299 mkU32( 0x0ff ) ); 3300 IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) ); 3301 3302 return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) ); 3303 } 3304 3305 /* This function takes an Ity_I32 input argument interpreted 3306 * as a single-precision floating point value. If src is a 3307 * SNaN, it is changed to a QNaN and returned; otherwise, 3308 * the original value is returned. 3309 */ 3310 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src) 3311 { 3312 #define SNAN_MASK32 0x00400000 3313 IRTemp tmp = newTemp(Ity_I32); 3314 IRTemp mask = newTemp(Ity_I32); 3315 IRTemp is_SNAN = newTemp(Ity_I1); 3316 3317 vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 ); 3318 assign(tmp, src); 3319 3320 /* check if input is SNaN, if it is convert to QNaN */ 3321 assign( is_SNAN, 3322 mkAND1( is_NaN_32( tmp ), 3323 binop( Iop_CmpEQ32, 3324 binop( Iop_And32, mkexpr( tmp ), 3325 mkU32( SNAN_MASK32 ) ), 3326 mkU32( 0 ) ) ) ); 3327 /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */ 3328 assign ( mask, binop( Iop_And32, 3329 unop( Iop_1Sto32, mkexpr( is_SNAN ) ), 3330 mkU32( SNAN_MASK32 ) ) ); 3331 return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) ); 3332 } 3333 3334 3335 /* This helper function performs the negation part of operations of the form: 3336 * "Negate Multiply-<op>" 3337 * where "<op>" is either "Add" or "Sub". 3338 * 3339 * This function takes one argument -- the floating point intermediate result (converted to 3340 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of 3341 * the operation described above. 3342 */ 3343 static IRTemp getNegatedResult(IRTemp intermediateResult) 3344 { 3345 ULong signbit_mask = 0x8000000000000000ULL; 3346 IRTemp signbit_32 = newTemp(Ity_I32); 3347 IRTemp resultantSignbit = newTemp(Ity_I1); 3348 IRTemp negatedResult = newTemp(Ity_I64); 3349 assign( signbit_32, binop( Iop_Shr32, 3350 unop( Iop_64HIto32, 3351 binop( Iop_And64, mkexpr( intermediateResult ), 3352 mkU64( signbit_mask ) ) ), 3353 mkU8( 31 ) ) ); 3354 /* We negate the signbit if and only if the intermediate result from the 3355 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 3356 */ 3357 assign( resultantSignbit, 3358 unop( Iop_Not1, 3359 binop( Iop_CmpEQ32, 3360 binop( Iop_Xor32, 3361 mkexpr( signbit_32 ), 3362 unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ), 3363 mkU32( 1 ) ) ) ); 3364 3365 assign( negatedResult, 3366 binop( Iop_Or64, 3367 binop( Iop_And64, 3368 mkexpr( intermediateResult ), 3369 mkU64( ~signbit_mask ) ), 3370 binop( Iop_32HLto64, 3371 binop( Iop_Shl32, 3372 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 3373 mkU8( 31 ) ), 3374 mkU32( 0 ) ) ) ); 3375 3376 return negatedResult; 3377 } 3378 3379 /* This helper function performs the negation part of operations of the form: 3380 * "Negate Multiply-<op>" 3381 * where "<op>" is either "Add" or "Sub". 3382 * 3383 * This function takes one argument -- the floating point intermediate result (converted to 3384 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of 3385 * the operation described above. 3386 */ 3387 static IRTemp getNegatedResult_32(IRTemp intermediateResult) 3388 { 3389 UInt signbit_mask = 0x80000000; 3390 IRTemp signbit_32 = newTemp(Ity_I32); 3391 IRTemp resultantSignbit = newTemp(Ity_I1); 3392 IRTemp negatedResult = newTemp(Ity_I32); 3393 assign( signbit_32, binop( Iop_Shr32, 3394 binop( Iop_And32, mkexpr( intermediateResult ), 3395 mkU32( signbit_mask ) ), 3396 mkU8( 31 ) ) ); 3397 /* We negate the signbit if and only if the intermediate result from the 3398 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 3399 */ 3400 assign( resultantSignbit, 3401 unop( Iop_Not1, 3402 binop( Iop_CmpEQ32, 3403 binop( Iop_Xor32, 3404 mkexpr( signbit_32 ), 3405 unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ), 3406 mkU32( 1 ) ) ) ); 3407 3408 assign( negatedResult, 3409 binop( Iop_Or32, 3410 binop( Iop_And32, 3411 mkexpr( intermediateResult ), 3412 mkU32( ~signbit_mask ) ), 3413 binop( Iop_Shl32, 3414 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 3415 mkU8( 31 ) ) ) ); 3416 3417 return negatedResult; 3418 } 3419 3420 /*------------------------------------------------------------*/ 3421 /* Transactional memory helpers 3422 * 3423 *------------------------------------------------------------*/ 3424 3425 static ULong generate_TMreason( UInt failure_code, 3426 UInt persistant, 3427 UInt nest_overflow, 3428 UInt tm_exact ) 3429 { 3430 ULong tm_err_code = 3431 ( (ULong) 0) << (63-6) /* Failure code */ 3432 | ( (ULong) persistant) << (63-7) /* Failure persistant */ 3433 | ( (ULong) 0) << (63-8) /* Disallowed */ 3434 | ( (ULong) nest_overflow) << (63-9) /* Nesting Overflow */ 3435 | ( (ULong) 0) << (63-10) /* Footprint Overflow */ 3436 | ( (ULong) 0) << (63-11) /* Self-Induced Conflict */ 3437 | ( (ULong) 0) << (63-12) /* Non-Transactional Conflict */ 3438 | ( (ULong) 0) << (63-13) /* Transactional Conflict */ 3439 | ( (ULong) 0) << (63-14) /* Translation Invalidation Conflict */ 3440 | ( (ULong) 0) << (63-15) /* Implementation-specific */ 3441 | ( (ULong) 0) << (63-16) /* Instruction Fetch Conflict */ 3442 | ( (ULong) 0) << (63-30) /* Reserved */ 3443 | ( (ULong) 0) << (63-31) /* Abort */ 3444 | ( (ULong) 0) << (63-32) /* Suspend */ 3445 | ( (ULong) 0) << (63-33) /* Reserved */ 3446 | ( (ULong) 0) << (63-35) /* Privilege */ 3447 | ( (ULong) 0) << (63-36) /* Failure Summary */ 3448 | ( (ULong) tm_exact) << (63-37) /* TFIAR Exact */ 3449 | ( (ULong) 0) << (63-38) /* ROT */ 3450 | ( (ULong) 0) << (63-51) /* Reserved */ 3451 | ( (ULong) 0) << (63-63); /* Transaction Level */ 3452 3453 return tm_err_code; 3454 } 3455 3456 static void storeTMfailure( Addr64 err_address, ULong tm_reason, 3457 Addr64 handler_address ) 3458 { 3459 putGST( PPC_GST_TFIAR, mkU64( err_address ) ); 3460 putGST( PPC_GST_TEXASR, mkU64( tm_reason ) ); 3461 putGST( PPC_GST_TEXASRU, mkU32( 0 ) ); 3462 putGST( PPC_GST_TFHAR, mkU64( handler_address ) ); 3463 } 3464 3465 /*------------------------------------------------------------*/ 3466 /*--- Integer Instruction Translation --- */ 3467 /*------------------------------------------------------------*/ 3468 3469 /* 3470 Integer Arithmetic Instructions 3471 */ 3472 static Bool dis_int_arith ( UInt theInstr ) 3473 { 3474 /* D-Form, XO-Form */ 3475 UChar opc1 = ifieldOPC(theInstr); 3476 UChar rD_addr = ifieldRegDS(theInstr); 3477 UChar rA_addr = ifieldRegA(theInstr); 3478 UInt uimm16 = ifieldUIMM16(theInstr); 3479 UChar rB_addr = ifieldRegB(theInstr); 3480 UChar flag_OE = ifieldBIT10(theInstr); 3481 UInt opc2 = ifieldOPClo9(theInstr); 3482 UChar flag_rC = ifieldBIT0(theInstr); 3483 3484 Long simm16 = extend_s_16to64(uimm16); 3485 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3486 IRTemp rA = newTemp(ty); 3487 IRTemp rB = newTemp(ty); 3488 IRTemp rD = newTemp(ty); 3489 3490 Bool do_rc = False; 3491 3492 assign( rA, getIReg(rA_addr) ); 3493 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB 3494 3495 switch (opc1) { 3496 /* D-Form */ 3497 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 3498 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3499 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3500 mkSzExtendS16(ty, uimm16) ) ); 3501 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3502 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3503 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3504 break; 3505 3506 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) 3507 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3508 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3509 mkSzExtendS16(ty, uimm16) ) ); 3510 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3511 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3512 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3513 do_rc = True; // Always record to CR 3514 flag_rC = 1; 3515 break; 3516 3517 case 0x0E: // addi (Add Immediate, PPC32 p350) 3518 // li rD,val == addi rD,0,val 3519 // la disp(rA) == addi rD,rA,disp 3520 if ( rA_addr == 0 ) { 3521 DIP("li r%u,%d\n", rD_addr, (Int)simm16); 3522 assign( rD, mkSzExtendS16(ty, uimm16) ); 3523 } else { 3524 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3525 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3526 mkSzExtendS16(ty, uimm16) ) ); 3527 } 3528 break; 3529 3530 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353) 3531 // lis rD,val == addis rD,0,val 3532 if ( rA_addr == 0 ) { 3533 DIP("lis r%u,%d\n", rD_addr, (Int)simm16); 3534 assign( rD, mkSzExtendS32(ty, uimm16 << 16) ); 3535 } else { 3536 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (UInt)simm16); 3537 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3538 mkSzExtendS32(ty, uimm16 << 16) ) ); 3539 } 3540 break; 3541 3542 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490) 3543 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3544 if (mode64) 3545 assign( rD, unop(Iop_128to64, 3546 binop(Iop_MullS64, mkexpr(rA), 3547 mkSzExtendS16(ty, uimm16))) ); 3548 else 3549 assign( rD, unop(Iop_64to32, 3550 binop(Iop_MullS32, mkexpr(rA), 3551 mkSzExtendS16(ty, uimm16))) ); 3552 break; 3553 3554 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540) 3555 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3556 // rD = simm16 - rA 3557 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3558 mkSzExtendS16(ty, uimm16), 3559 mkexpr(rA)) ); 3560 set_XER_CA( ty, PPCG_FLAG_OP_SUBFI, 3561 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3562 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3563 break; 3564 3565 /* XO-Form */ 3566 case 0x1F: 3567 do_rc = True; // All below record to CR 3568 3569 switch (opc2) { 3570 case 0x10A: // add (Add, PPC32 p347) 3571 DIP("add%s%s r%u,r%u,r%u\n", 3572 flag_OE ? "o" : "", flag_rC ? ".":"", 3573 rD_addr, rA_addr, rB_addr); 3574 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3575 mkexpr(rA), mkexpr(rB) ) ); 3576 if (flag_OE) { 3577 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3578 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3579 } 3580 break; 3581 3582 case 0x00A: // addc (Add Carrying, PPC32 p348) 3583 DIP("addc%s%s r%u,r%u,r%u\n", 3584 flag_OE ? "o" : "", flag_rC ? ".":"", 3585 rD_addr, rA_addr, rB_addr); 3586 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3587 mkexpr(rA), mkexpr(rB)) ); 3588 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3589 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3590 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3591 if (flag_OE) { 3592 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3593 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3594 } 3595 break; 3596 3597 case 0x08A: { // adde (Add Extended, PPC32 p349) 3598 IRTemp old_xer_ca = newTemp(ty); 3599 DIP("adde%s%s r%u,r%u,r%u\n", 3600 flag_OE ? "o" : "", flag_rC ? ".":"", 3601 rD_addr, rA_addr, rB_addr); 3602 // rD = rA + rB + XER[CA] 3603 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3604 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3605 binop( mkSzOp(ty, Iop_Add8), 3606 mkexpr(rB), mkexpr(old_xer_ca))) ); 3607 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3608 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3609 mkexpr(old_xer_ca) ); 3610 if (flag_OE) { 3611 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3612 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3613 } 3614 break; 3615 } 3616 3617 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354) 3618 IRTemp old_xer_ca = newTemp(ty); 3619 IRExpr *min_one; 3620 if (rB_addr != 0) { 3621 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n"); 3622 return False; 3623 } 3624 DIP("addme%s%s r%u,r%u,r%u\n", 3625 flag_OE ? "o" : "", flag_rC ? ".":"", 3626 rD_addr, rA_addr, rB_addr); 3627 // rD = rA + (-1) + XER[CA] 3628 // => Just another form of adde 3629 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3630 min_one = mkSzImm(ty, (Long)-1); 3631 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3632 binop( mkSzOp(ty, Iop_Add8), 3633 min_one, mkexpr(old_xer_ca)) )); 3634 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3635 mkexpr(rD), mkexpr(rA), min_one, 3636 mkexpr(old_xer_ca) ); 3637 if (flag_OE) { 3638 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3639 mkexpr(rD), mkexpr(rA), min_one ); 3640 } 3641 break; 3642 } 3643 3644 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355) 3645 IRTemp old_xer_ca = newTemp(ty); 3646 if (rB_addr != 0) { 3647 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n"); 3648 return False; 3649 } 3650 DIP("addze%s%s r%u,r%u,r%u\n", 3651 flag_OE ? "o" : "", flag_rC ? ".":"", 3652 rD_addr, rA_addr, rB_addr); 3653 // rD = rA + (0) + XER[CA] 3654 // => Just another form of adde 3655 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3656 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3657 mkexpr(rA), mkexpr(old_xer_ca)) ); 3658 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3659 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3660 mkexpr(old_xer_ca) ); 3661 if (flag_OE) { 3662 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3663 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3664 } 3665 break; 3666 } 3667 3668 case 0x1EB: // divw (Divide Word, PPC32 p388) 3669 DIP("divw%s%s r%u,r%u,r%u\n", 3670 flag_OE ? "o" : "", flag_rC ? ".":"", 3671 rD_addr, rA_addr, rB_addr); 3672 if (mode64) { 3673 /* Note: 3674 XER settings are mode independent, and reflect the 3675 overflow of the low-order 32bit result 3676 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3677 */ 3678 /* rD[hi32] are undefined: setting them to sign of lo32 3679 - makes set_CR0 happy */ 3680 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) ); 3681 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) ); 3682 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend, 3683 divisor) ) ); 3684 if (flag_OE) { 3685 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3686 mkexpr(rD), dividend, divisor ); 3687 } 3688 } else { 3689 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) ); 3690 if (flag_OE) { 3691 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3692 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3693 } 3694 } 3695 /* Note: 3696 if (0x8000_0000 / -1) or (x / 0) 3697 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3698 => But _no_ exception raised. */ 3699 break; 3700 3701 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389) 3702 DIP("divwu%s%s r%u,r%u,r%u\n", 3703 flag_OE ? "o" : "", flag_rC ? ".":"", 3704 rD_addr, rA_addr, rB_addr); 3705 if (mode64) { 3706 /* Note: 3707 XER settings are mode independent, and reflect the 3708 overflow of the low-order 32bit result 3709 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3710 */ 3711 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) ); 3712 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) ); 3713 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend, 3714 divisor) ) ); 3715 if (flag_OE) { 3716 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3717 mkexpr(rD), dividend, divisor ); 3718 } 3719 } else { 3720 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) ); 3721 if (flag_OE) { 3722 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3723 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3724 } 3725 } 3726 /* Note: ditto comment divw, for (x / 0) */ 3727 break; 3728 3729 case 0x04B: // mulhw (Multiply High Word, PPC32 p488) 3730 if (flag_OE != 0) { 3731 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n"); 3732 return False; 3733 } 3734 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3735 rD_addr, rA_addr, rB_addr); 3736 if (mode64) { 3737 /* rD[hi32] are undefined: setting them to sign of lo32 3738 - makes set_CR0 happy */ 3739 assign( rD, binop(Iop_Sar64, 3740 binop(Iop_Mul64, 3741 mk64lo32Sto64( mkexpr(rA) ), 3742 mk64lo32Sto64( mkexpr(rB) )), 3743 mkU8(32)) ); 3744 } else { 3745 assign( rD, unop(Iop_64HIto32, 3746 binop(Iop_MullS32, 3747 mkexpr(rA), mkexpr(rB))) ); 3748 } 3749 break; 3750 3751 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489) 3752 if (flag_OE != 0) { 3753 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n"); 3754 return False; 3755 } 3756 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3757 rD_addr, rA_addr, rB_addr); 3758 if (mode64) { 3759 /* rD[hi32] are undefined: setting them to sign of lo32 3760 - makes set_CR0 happy */ 3761 assign( rD, binop(Iop_Sar64, 3762 binop(Iop_Mul64, 3763 mk64lo32Uto64( mkexpr(rA) ), 3764 mk64lo32Uto64( mkexpr(rB) ) ), 3765 mkU8(32)) ); 3766 } else { 3767 assign( rD, unop(Iop_64HIto32, 3768 binop(Iop_MullU32, 3769 mkexpr(rA), mkexpr(rB))) ); 3770 } 3771 break; 3772 3773 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491) 3774 DIP("mullw%s%s r%u,r%u,r%u\n", 3775 flag_OE ? "o" : "", flag_rC ? ".":"", 3776 rD_addr, rA_addr, rB_addr); 3777 if (mode64) { 3778 /* rD[hi32] are undefined: setting them to sign of lo32 3779 - set_XER_OV() and set_CR0() depend on this */ 3780 IRExpr *a = unop(Iop_64to32, mkexpr(rA) ); 3781 IRExpr *b = unop(Iop_64to32, mkexpr(rB) ); 3782 assign( rD, binop(Iop_MullS32, a, b) ); 3783 if (flag_OE) { 3784 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3785 mkexpr(rD), 3786 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) ); 3787 } 3788 } else { 3789 assign( rD, unop(Iop_64to32, 3790 binop(Iop_MullU32, 3791 mkexpr(rA), mkexpr(rB))) ); 3792 if (flag_OE) { 3793 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3794 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3795 } 3796 } 3797 break; 3798 3799 case 0x068: // neg (Negate, PPC32 p493) 3800 if (rB_addr != 0) { 3801 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n"); 3802 return False; 3803 } 3804 DIP("neg%s%s r%u,r%u\n", 3805 flag_OE ? "o" : "", flag_rC ? ".":"", 3806 rD_addr, rA_addr); 3807 // rD = (~rA) + 1 3808 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3809 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ), 3810 mkSzImm(ty, 1)) ); 3811 if (flag_OE) { 3812 set_XER_OV( ty, PPCG_FLAG_OP_NEG, 3813 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3814 } 3815 break; 3816 3817 case 0x028: // subf (Subtract From, PPC32 p537) 3818 DIP("subf%s%s r%u,r%u,r%u\n", 3819 flag_OE ? "o" : "", flag_rC ? ".":"", 3820 rD_addr, rA_addr, rB_addr); 3821 // rD = rB - rA 3822 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3823 mkexpr(rB), mkexpr(rA)) ); 3824 if (flag_OE) { 3825 set_XER_OV( ty, PPCG_FLAG_OP_SUBF, 3826 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3827 } 3828 break; 3829 3830 case 0x008: // subfc (Subtract from Carrying, PPC32 p538) 3831 DIP("subfc%s%s r%u,r%u,r%u\n", 3832 flag_OE ? "o" : "", flag_rC ? ".":"", 3833 rD_addr, rA_addr, rB_addr); 3834 // rD = rB - rA 3835 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3836 mkexpr(rB), mkexpr(rA)) ); 3837 set_XER_CA( ty, PPCG_FLAG_OP_SUBFC, 3838 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3839 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3840 if (flag_OE) { 3841 set_XER_OV( ty, PPCG_FLAG_OP_SUBFC, 3842 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3843 } 3844 break; 3845 3846 case 0x088: {// subfe (Subtract from Extended, PPC32 p539) 3847 IRTemp old_xer_ca = newTemp(ty); 3848 DIP("subfe%s%s r%u,r%u,r%u\n", 3849 flag_OE ? "o" : "", flag_rC ? ".":"", 3850 rD_addr, rA_addr, rB_addr); 3851 // rD = (log not)rA + rB + XER[CA] 3852 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3853 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3854 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3855 binop( mkSzOp(ty, Iop_Add8), 3856 mkexpr(rB), mkexpr(old_xer_ca))) ); 3857 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3858 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3859 mkexpr(old_xer_ca) ); 3860 if (flag_OE) { 3861 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3862 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3863 } 3864 break; 3865 } 3866 3867 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541) 3868 IRTemp old_xer_ca = newTemp(ty); 3869 IRExpr *min_one; 3870 if (rB_addr != 0) { 3871 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n"); 3872 return False; 3873 } 3874 DIP("subfme%s%s r%u,r%u\n", 3875 flag_OE ? "o" : "", flag_rC ? ".":"", 3876 rD_addr, rA_addr); 3877 // rD = (log not)rA + (-1) + XER[CA] 3878 // => Just another form of subfe 3879 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3880 min_one = mkSzImm(ty, (Long)-1); 3881 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3882 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3883 binop( mkSzOp(ty, Iop_Add8), 3884 min_one, mkexpr(old_xer_ca))) ); 3885 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3886 mkexpr(rD), mkexpr(rA), min_one, 3887 mkexpr(old_xer_ca) ); 3888 if (flag_OE) { 3889 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3890 mkexpr(rD), mkexpr(rA), min_one ); 3891 } 3892 break; 3893 } 3894 3895 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542) 3896 IRTemp old_xer_ca = newTemp(ty); 3897 if (rB_addr != 0) { 3898 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n"); 3899 return False; 3900 } 3901 DIP("subfze%s%s r%u,r%u\n", 3902 flag_OE ? "o" : "", flag_rC ? ".":"", 3903 rD_addr, rA_addr); 3904 // rD = (log not)rA + (0) + XER[CA] 3905 // => Just another form of subfe 3906 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3907 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3908 unop( mkSzOp(ty, Iop_Not8), 3909 mkexpr(rA)), mkexpr(old_xer_ca)) ); 3910 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3911 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3912 mkexpr(old_xer_ca) ); 3913 if (flag_OE) { 3914 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3915 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3916 } 3917 break; 3918 } 3919 3920 3921 /* 64bit Arithmetic */ 3922 case 0x49: // mulhd (Multiply High DWord, PPC64 p539) 3923 if (flag_OE != 0) { 3924 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n"); 3925 return False; 3926 } 3927 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3928 rD_addr, rA_addr, rB_addr); 3929 assign( rD, unop(Iop_128HIto64, 3930 binop(Iop_MullS64, 3931 mkexpr(rA), mkexpr(rB))) ); 3932 3933 break; 3934 3935 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540) 3936 if (flag_OE != 0) { 3937 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n"); 3938 return False; 3939 } 3940 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3941 rD_addr, rA_addr, rB_addr); 3942 assign( rD, unop(Iop_128HIto64, 3943 binop(Iop_MullU64, 3944 mkexpr(rA), mkexpr(rB))) ); 3945 break; 3946 3947 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543) 3948 DIP("mulld%s%s r%u,r%u,r%u\n", 3949 flag_OE ? "o" : "", flag_rC ? ".":"", 3950 rD_addr, rA_addr, rB_addr); 3951 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) ); 3952 if (flag_OE) { 3953 set_XER_OV( ty, PPCG_FLAG_OP_MULLD, 3954 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3955 } 3956 break; 3957 3958 case 0x1E9: // divd (Divide DWord, PPC64 p419) 3959 DIP("divd%s%s r%u,r%u,r%u\n", 3960 flag_OE ? "o" : "", flag_rC ? ".":"", 3961 rD_addr, rA_addr, rB_addr); 3962 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) ); 3963 if (flag_OE) { 3964 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3965 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3966 } 3967 break; 3968 /* Note: 3969 if (0x8000_0000_0000_0000 / -1) or (x / 0) 3970 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3971 => But _no_ exception raised. */ 3972 3973 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420) 3974 DIP("divdu%s%s r%u,r%u,r%u\n", 3975 flag_OE ? "o" : "", flag_rC ? ".":"", 3976 rD_addr, rA_addr, rB_addr); 3977 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) ); 3978 if (flag_OE) { 3979 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3980 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3981 } 3982 break; 3983 /* Note: ditto comment divd, for (x / 0) */ 3984 3985 case 0x18B: // divweu (Divide Word Extended Unsigned) 3986 { 3987 /* 3988 * If (RA) >= (RB), or if an attempt is made to perform the division 3989 * <anything> / 0 3990 * then the contents of register RD are undefined as are (if Rc=1) the contents of 3991 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set 3992 * to 1. 3993 */ 3994 IRTemp res = newTemp(Ity_I32); 3995 IRExpr * dividend, * divisor; 3996 DIP("divweu%s%s r%u,r%u,r%u\n", 3997 flag_OE ? "o" : "", flag_rC ? ".":"", 3998 rD_addr, rA_addr, rB_addr); 3999 if (mode64) { 4000 dividend = unop( Iop_64to32, mkexpr( rA ) ); 4001 divisor = unop( Iop_64to32, mkexpr( rB ) ); 4002 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 4003 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 4004 } else { 4005 dividend = mkexpr( rA ); 4006 divisor = mkexpr( rB ); 4007 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 4008 assign( rD, mkexpr( res) ); 4009 } 4010 4011 if (flag_OE) { 4012 set_XER_OV_32( PPCG_FLAG_OP_DIVWEU, 4013 mkexpr(res), dividend, divisor ); 4014 } 4015 break; 4016 } 4017 4018 case 0x1AB: // divwe (Divide Word Extended) 4019 { 4020 /* 4021 * If the quotient cannot be represented in 32 bits, or if an 4022 * attempt is made to perform the division 4023 * <anything> / 0 4024 * then the contents of register RD are undefined as are (if 4025 * Rc=1) the contents of the LT, GT, and EQ bits of CR 4026 * Field 0. In these cases, if OE=1 then OV is set to 1. 4027 */ 4028 4029 IRTemp res = newTemp(Ity_I32); 4030 IRExpr * dividend, * divisor; 4031 DIP("divwe%s%s r%u,r%u,r%u\n", 4032 flag_OE ? "o" : "", flag_rC ? ".":"", 4033 rD_addr, rA_addr, rB_addr); 4034 if (mode64) { 4035 dividend = unop( Iop_64to32, mkexpr( rA ) ); 4036 divisor = unop( Iop_64to32, mkexpr( rB ) ); 4037 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 4038 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 4039 } else { 4040 dividend = mkexpr( rA ); 4041 divisor = mkexpr( rB ); 4042 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 4043 assign( rD, mkexpr( res) ); 4044 } 4045 4046 if (flag_OE) { 4047 set_XER_OV_32( PPCG_FLAG_OP_DIVWE, 4048 mkexpr(res), dividend, divisor ); 4049 } 4050 break; 4051 } 4052 4053 4054 case 0x1A9: // divde (Divide Doubleword Extended) 4055 /* 4056 * If the quotient cannot be represented in 64 bits, or if an 4057 * attempt is made to perform the division 4058 * <anything> / 0 4059 * then the contents of register RD are undefined as are (if 4060 * Rc=1) the contents of the LT, GT, and EQ bits of CR 4061 * Field 0. In these cases, if OE=1 then OV is set to 1. 4062 */ 4063 DIP("divde%s%s r%u,r%u,r%u\n", 4064 flag_OE ? "o" : "", flag_rC ? ".":"", 4065 rD_addr, rA_addr, rB_addr); 4066 assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) ); 4067 if (flag_OE) { 4068 set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ), 4069 mkexpr( rA ), mkexpr( rB ) ); 4070 } 4071 break; 4072 4073 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned) 4074 // Same CR and OV rules as given for divweu above 4075 DIP("divdeu%s%s r%u,r%u,r%u\n", 4076 flag_OE ? "o" : "", flag_rC ? ".":"", 4077 rD_addr, rA_addr, rB_addr); 4078 assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) ); 4079 if (flag_OE) { 4080 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ), 4081 mkexpr( rA ), mkexpr( rB ) ); 4082 } 4083 break; 4084 4085 default: 4086 vex_printf("dis_int_arith(ppc)(opc2)\n"); 4087 return False; 4088 } 4089 break; 4090 4091 default: 4092 vex_printf("dis_int_arith(ppc)(opc1)\n"); 4093 return False; 4094 } 4095 4096 putIReg( rD_addr, mkexpr(rD) ); 4097 4098 if (do_rc && flag_rC) { 4099 set_CR0( mkexpr(rD) ); 4100 } 4101 return True; 4102 } 4103 4104 4105 4106 /* 4107 Integer Compare Instructions 4108 */ 4109 static Bool dis_int_cmp ( UInt theInstr ) 4110 { 4111 /* D-Form, X-Form */ 4112 UChar opc1 = ifieldOPC(theInstr); 4113 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 4114 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) ); 4115 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) ); 4116 UChar rA_addr = ifieldRegA(theInstr); 4117 UInt uimm16 = ifieldUIMM16(theInstr); 4118 UChar rB_addr = ifieldRegB(theInstr); 4119 UInt opc2 = ifieldOPClo10(theInstr); 4120 UChar b0 = ifieldBIT0(theInstr); 4121 4122 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4123 IRExpr *a = getIReg(rA_addr); 4124 IRExpr *b; 4125 4126 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit. 4127 vex_printf("dis_int_cmp(ppc)(flag_L)\n"); 4128 return False; 4129 } 4130 4131 if (b22 != 0) { 4132 vex_printf("dis_int_cmp(ppc)(b22)\n"); 4133 return False; 4134 } 4135 4136 switch (opc1) { 4137 case 0x0B: // cmpi (Compare Immediate, PPC32 p368) 4138 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr, 4139 (Int)extend_s_16to32(uimm16)); 4140 b = mkSzExtendS16( ty, uimm16 ); 4141 if (flag_L == 1) { 4142 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 4143 } else { 4144 a = mkNarrowTo32( ty, a ); 4145 b = mkNarrowTo32( ty, b ); 4146 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b))); 4147 } 4148 putCR0( crfD, getXER_SO() ); 4149 break; 4150 4151 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370) 4152 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16); 4153 b = mkSzImm( ty, uimm16 ); 4154 if (flag_L == 1) { 4155 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 4156 } else { 4157 a = mkNarrowTo32( ty, a ); 4158 b = mkNarrowTo32( ty, b ); 4159 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 4160 } 4161 putCR0( crfD, getXER_SO() ); 4162 break; 4163 4164 /* X Form */ 4165 case 0x1F: 4166 if (b0 != 0) { 4167 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n"); 4168 return False; 4169 } 4170 b = getIReg(rB_addr); 4171 4172 switch (opc2) { 4173 case 0x000: // cmp (Compare, PPC32 p367) 4174 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 4175 /* Comparing a reg with itself produces a result which 4176 doesn't depend on the contents of the reg. Therefore 4177 remove the false dependency, which has been known to cause 4178 memcheck to produce false errors. */ 4179 if (rA_addr == rB_addr) 4180 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 4181 ? mkU64(0) : mkU32(0); 4182 if (flag_L == 1) { 4183 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 4184 } else { 4185 a = mkNarrowTo32( ty, a ); 4186 b = mkNarrowTo32( ty, b ); 4187 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b))); 4188 } 4189 putCR0( crfD, getXER_SO() ); 4190 break; 4191 4192 case 0x020: // cmpl (Compare Logical, PPC32 p369) 4193 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 4194 /* Comparing a reg with itself produces a result which 4195 doesn't depend on the contents of the reg. Therefore 4196 remove the false dependency, which has been known to cause 4197 memcheck to produce false errors. */ 4198 if (rA_addr == rB_addr) 4199 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 4200 ? mkU64(0) : mkU32(0); 4201 if (flag_L == 1) { 4202 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 4203 } else { 4204 a = mkNarrowTo32( ty, a ); 4205 b = mkNarrowTo32( ty, b ); 4206 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 4207 } 4208 putCR0( crfD, getXER_SO() ); 4209 break; 4210 4211 default: 4212 vex_printf("dis_int_cmp(ppc)(opc2)\n"); 4213 return False; 4214 } 4215 break; 4216 4217 default: 4218 vex_printf("dis_int_cmp(ppc)(opc1)\n"); 4219 return False; 4220 } 4221 4222 return True; 4223 } 4224 4225 4226 /* 4227 Integer Logical Instructions 4228 */ 4229 static Bool dis_int_logic ( UInt theInstr ) 4230 { 4231 /* D-Form, X-Form */ 4232 UChar opc1 = ifieldOPC(theInstr); 4233 UChar rS_addr = ifieldRegDS(theInstr); 4234 UChar rA_addr = ifieldRegA(theInstr); 4235 UInt uimm16 = ifieldUIMM16(theInstr); 4236 UChar rB_addr = ifieldRegB(theInstr); 4237 UInt opc2 = ifieldOPClo10(theInstr); 4238 UChar flag_rC = ifieldBIT0(theInstr); 4239 4240 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4241 IRTemp rS = newTemp(ty); 4242 IRTemp rA = newTemp(ty); 4243 IRTemp rB = newTemp(ty); 4244 IRExpr* irx; 4245 Bool do_rc = False; 4246 4247 assign( rS, getIReg(rS_addr) ); 4248 assign( rB, getIReg(rB_addr) ); 4249 4250 switch (opc1) { 4251 case 0x1C: // andi. (AND Immediate, PPC32 p358) 4252 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4253 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4254 mkSzImm(ty, uimm16)) ); 4255 do_rc = True; // Always record to CR 4256 flag_rC = 1; 4257 break; 4258 4259 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359) 4260 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4261 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4262 mkSzImm(ty, uimm16 << 16)) ); 4263 do_rc = True; // Always record to CR 4264 flag_rC = 1; 4265 break; 4266 4267 case 0x18: // ori (OR Immediate, PPC32 p497) 4268 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4269 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4270 mkSzImm(ty, uimm16)) ); 4271 break; 4272 4273 case 0x19: // oris (OR Immediate Shifted, PPC32 p498) 4274 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4275 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4276 mkSzImm(ty, uimm16 << 16)) ); 4277 break; 4278 4279 case 0x1A: // xori (XOR Immediate, PPC32 p550) 4280 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4281 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 4282 mkSzImm(ty, uimm16)) ); 4283 break; 4284 4285 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551) 4286 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4287 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 4288 mkSzImm(ty, uimm16 << 16)) ); 4289 break; 4290 4291 /* X Form */ 4292 case 0x1F: 4293 do_rc = True; // All below record to CR, except for where we return at case end. 4294 4295 switch (opc2) { 4296 case 0x01C: // and (AND, PPC32 p356) 4297 DIP("and%s r%u,r%u,r%u\n", 4298 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4299 assign(rA, binop( mkSzOp(ty, Iop_And8), 4300 mkexpr(rS), mkexpr(rB))); 4301 break; 4302 4303 case 0x03C: // andc (AND with Complement, PPC32 p357) 4304 DIP("andc%s r%u,r%u,r%u\n", 4305 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4306 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4307 unop( mkSzOp(ty, Iop_Not8), 4308 mkexpr(rB)))); 4309 break; 4310 4311 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371) 4312 IRExpr* lo32; 4313 if (rB_addr!=0) { 4314 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n"); 4315 return False; 4316 } 4317 DIP("cntlzw%s r%u,r%u\n", 4318 flag_rC ? ".":"", rA_addr, rS_addr); 4319 4320 // mode64: count in low word only 4321 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS); 4322 4323 // Iop_Clz32 undefined for arg==0, so deal with that case: 4324 irx = binop(Iop_CmpNE32, lo32, mkU32(0)); 4325 assign(rA, mkWidenFrom32(ty, 4326 IRExpr_ITE( irx, 4327 unop(Iop_Clz32, lo32), 4328 mkU32(32)), 4329 False)); 4330 4331 // TODO: alternatively: assign(rA, verbose_Clz32(rS)); 4332 break; 4333 } 4334 4335 case 0x11C: // eqv (Equivalent, PPC32 p396) 4336 DIP("eqv%s r%u,r%u,r%u\n", 4337 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4338 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4339 binop( mkSzOp(ty, Iop_Xor8), 4340 mkexpr(rS), mkexpr(rB))) ); 4341 break; 4342 4343 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397 4344 if (rB_addr!=0) { 4345 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n"); 4346 return False; 4347 } 4348 DIP("extsb%s r%u,r%u\n", 4349 flag_rC ? ".":"", rA_addr, rS_addr); 4350 if (mode64) 4351 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) ); 4352 else 4353 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) ); 4354 break; 4355 4356 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398) 4357 if (rB_addr!=0) { 4358 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n"); 4359 return False; 4360 } 4361 DIP("extsh%s r%u,r%u\n", 4362 flag_rC ? ".":"", rA_addr, rS_addr); 4363 if (mode64) 4364 assign( rA, unop(Iop_16Sto64, 4365 unop(Iop_64to16, mkexpr(rS))) ); 4366 else 4367 assign( rA, unop(Iop_16Sto32, 4368 unop(Iop_32to16, mkexpr(rS))) ); 4369 break; 4370 4371 case 0x1DC: // nand (NAND, PPC32 p492) 4372 DIP("nand%s r%u,r%u,r%u\n", 4373 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4374 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4375 binop( mkSzOp(ty, Iop_And8), 4376 mkexpr(rS), mkexpr(rB))) ); 4377 break; 4378 4379 case 0x07C: // nor (NOR, PPC32 p494) 4380 DIP("nor%s r%u,r%u,r%u\n", 4381 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4382 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4383 binop( mkSzOp(ty, Iop_Or8), 4384 mkexpr(rS), mkexpr(rB))) ); 4385 break; 4386 4387 case 0x1BC: // or (OR, PPC32 p495) 4388 if ((!flag_rC) && rS_addr == rB_addr) { 4389 DIP("mr r%u,r%u\n", rA_addr, rS_addr); 4390 assign( rA, mkexpr(rS) ); 4391 } else { 4392 DIP("or%s r%u,r%u,r%u\n", 4393 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4394 assign( rA, binop( mkSzOp(ty, Iop_Or8), 4395 mkexpr(rS), mkexpr(rB)) ); 4396 } 4397 break; 4398 4399 case 0x19C: // orc (OR with Complement, PPC32 p496) 4400 DIP("orc%s r%u,r%u,r%u\n", 4401 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4402 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4403 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB)))); 4404 break; 4405 4406 case 0x13C: // xor (XOR, PPC32 p549) 4407 DIP("xor%s r%u,r%u,r%u\n", 4408 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4409 assign( rA, binop( mkSzOp(ty, Iop_Xor8), 4410 mkexpr(rS), mkexpr(rB)) ); 4411 break; 4412 4413 4414 /* 64bit Integer Logical Instructions */ 4415 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430) 4416 if (rB_addr!=0) { 4417 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n"); 4418 return False; 4419 } 4420 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr); 4421 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS)))); 4422 break; 4423 4424 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401) 4425 if (rB_addr!=0) { 4426 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n"); 4427 return False; 4428 } 4429 DIP("cntlzd%s r%u,r%u\n", 4430 flag_rC ? ".":"", rA_addr, rS_addr); 4431 // Iop_Clz64 undefined for arg==0, so deal with that case: 4432 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0)); 4433 assign(rA, IRExpr_ITE( irx, 4434 unop(Iop_Clz64, mkexpr(rS)), 4435 mkU64(64) )); 4436 // TODO: alternatively: assign(rA, verbose_Clz64(rS)); 4437 break; 4438 4439 case 0x1FC: // cmpb (Power6: compare bytes) 4440 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 4441 4442 if (mode64) 4443 assign( rA, unop( Iop_V128to64, 4444 binop( Iop_CmpEQ8x16, 4445 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ), 4446 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) ) 4447 )) ); 4448 else 4449 assign( rA, unop( Iop_V128to32, 4450 binop( Iop_CmpEQ8x16, 4451 unop( Iop_32UtoV128, mkexpr(rS) ), 4452 unop( Iop_32UtoV128, mkexpr(rB) ) 4453 )) ); 4454 break; 4455 4456 case 0x2DF: { // mftgpr (move floating-point to general purpose register) 4457 IRTemp frB = newTemp(Ity_F64); 4458 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr); 4459 4460 assign( frB, getFReg(rB_addr)); // always F64 4461 if (mode64) 4462 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 4463 else 4464 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) ); 4465 4466 putIReg( rS_addr, mkexpr(rA)); 4467 return True; 4468 } 4469 4470 case 0x25F: { // mffgpr (move floating-point from general purpose register) 4471 IRTemp frA = newTemp(Ity_F64); 4472 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr); 4473 4474 if (mode64) 4475 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) ); 4476 else 4477 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) ); 4478 4479 putFReg( rS_addr, mkexpr(frA)); 4480 return True; 4481 } 4482 case 0x1FA: // popcntd (population count doubleword 4483 { 4484 DIP("popcntd r%u,r%u\n", rA_addr, rS_addr); 4485 IRTemp result = gen_POPCOUNT(ty, rS, DWORD); 4486 putIReg( rA_addr, mkexpr(result) ); 4487 return True; 4488 } 4489 case 0x17A: // popcntw (Population Count Words) 4490 { 4491 DIP("popcntw r%u,r%u\n", rA_addr, rS_addr); 4492 if (mode64) { 4493 IRTemp resultHi, resultLo; 4494 IRTemp argLo = newTemp(Ity_I32); 4495 IRTemp argHi = newTemp(Ity_I32); 4496 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4497 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4498 resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD); 4499 resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD); 4500 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo))); 4501 } else { 4502 IRTemp result = gen_POPCOUNT(ty, rS, WORD); 4503 putIReg( rA_addr, mkexpr(result) ); 4504 } 4505 return True; 4506 } 4507 case 0x7A: // popcntb (Population Count Byte) 4508 { 4509 DIP("popcntb r%u,r%u\n", rA_addr, rS_addr); 4510 4511 if (mode64) { 4512 IRTemp resultHi, resultLo; 4513 IRTemp argLo = newTemp(Ity_I32); 4514 IRTemp argHi = newTemp(Ity_I32); 4515 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4516 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4517 resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE); 4518 resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE); 4519 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), 4520 mkexpr(resultLo))); 4521 } else { 4522 IRTemp result = gen_POPCOUNT(ty, rS, BYTE); 4523 putIReg( rA_addr, mkexpr(result) ); 4524 } 4525 return True; 4526 } 4527 case 0x0FC: // bpermd (Bit Permute Doubleword) 4528 { 4529 /* This is a lot of rigmarole to emulate bpermd like this, as it 4530 * could be done much faster by implementing a call to the native 4531 * instruction. However, where possible I want to avoid using new 4532 * native instructions so that we can use valgrind to emulate those 4533 * instructions on older PPC64 hardware. 4534 */ 4535 #define BPERMD_IDX_MASK 0x00000000000000FFULL 4536 #define BPERMD_BIT_MASK 0x8000000000000000ULL 4537 int i; 4538 IRExpr * rS_expr = mkexpr(rS); 4539 IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0)); 4540 DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 4541 for (i = 0; i < 8; i++) { 4542 IRTemp idx_tmp = newTemp( Ity_I64 ); 4543 IRTemp perm_bit = newTemp( Ity_I64 ); 4544 IRTemp idx = newTemp( Ity_I8 ); 4545 IRTemp idx_LT64 = newTemp( Ity_I1 ); 4546 IRTemp idx_LT64_ity64 = newTemp( Ity_I64 ); 4547 4548 assign( idx_tmp, 4549 binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) ); 4550 assign( idx_LT64, 4551 binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) ); 4552 assign( idx, 4553 binop( Iop_And8, 4554 unop( Iop_1Sto8, 4555 mkexpr(idx_LT64) ), 4556 unop( Iop_64to8, mkexpr( idx_tmp ) ) ) ); 4557 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx 4558 * to determine which bit of rB to use for the perm bit, and then we shift 4559 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64 4560 * to set the final perm bit. 4561 */ 4562 assign( idx_LT64_ity64, 4563 unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) ); 4564 assign( perm_bit, 4565 binop( Iop_And64, 4566 mkexpr( idx_LT64_ity64 ), 4567 binop( Iop_Shr64, 4568 binop( Iop_And64, 4569 mkU64( BPERMD_BIT_MASK ), 4570 binop( Iop_Shl64, 4571 mkexpr( rB ), 4572 mkexpr( idx ) ) ), 4573 mkU8( 63 ) ) ) ); 4574 res = binop( Iop_Or64, 4575 res, 4576 binop( Iop_Shl64, 4577 mkexpr( perm_bit ), 4578 mkU8( i ) ) ); 4579 rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) ); 4580 } 4581 putIReg(rA_addr, res); 4582 return True; 4583 } 4584 4585 default: 4586 vex_printf("dis_int_logic(ppc)(opc2)\n"); 4587 return False; 4588 } 4589 break; 4590 4591 default: 4592 vex_printf("dis_int_logic(ppc)(opc1)\n"); 4593 return False; 4594 } 4595 4596 putIReg( rA_addr, mkexpr(rA) ); 4597 4598 if (do_rc && flag_rC) { 4599 set_CR0( mkexpr(rA) ); 4600 } 4601 return True; 4602 } 4603 4604 /* 4605 Integer Parity Instructions 4606 */ 4607 static Bool dis_int_parity ( UInt theInstr ) 4608 { 4609 /* X-Form */ 4610 UChar opc1 = ifieldOPC(theInstr); 4611 UChar rS_addr = ifieldRegDS(theInstr); 4612 UChar rA_addr = ifieldRegA(theInstr); 4613 UChar rB_addr = ifieldRegB(theInstr); 4614 UInt opc2 = ifieldOPClo10(theInstr); 4615 UChar b0 = ifieldBIT0(theInstr); 4616 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4617 4618 IRTemp rS = newTemp(ty); 4619 IRTemp rA = newTemp(ty); 4620 IRTemp iTot1 = newTemp(Ity_I32); 4621 IRTemp iTot2 = newTemp(Ity_I32); 4622 IRTemp iTot3 = newTemp(Ity_I32); 4623 IRTemp iTot4 = newTemp(Ity_I32); 4624 IRTemp iTot5 = newTemp(Ity_I32); 4625 IRTemp iTot6 = newTemp(Ity_I32); 4626 IRTemp iTot7 = newTemp(Ity_I32); 4627 IRTemp iTot8 = newTemp(Ity_I32); 4628 IRTemp rS1 = newTemp(ty); 4629 IRTemp rS2 = newTemp(ty); 4630 IRTemp rS3 = newTemp(ty); 4631 IRTemp rS4 = newTemp(ty); 4632 IRTemp rS5 = newTemp(ty); 4633 IRTemp rS6 = newTemp(ty); 4634 IRTemp rS7 = newTemp(ty); 4635 IRTemp iHi = newTemp(Ity_I32); 4636 IRTemp iLo = newTemp(Ity_I32); 4637 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1); 4638 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32); 4639 4640 if (opc1 != 0x1f || rB_addr || b0) { 4641 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n"); 4642 return False; 4643 } 4644 4645 assign( rS, getIReg(rS_addr) ); 4646 4647 switch (opc2) { 4648 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320) 4649 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr); 4650 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4651 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4652 assign( iTot2, binop(Iop_Add32, 4653 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4654 mkexpr(iTot1)) ); 4655 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4656 assign( iTot3, binop(Iop_Add32, 4657 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4658 mkexpr(iTot2)) ); 4659 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4660 assign( iTot4, binop(Iop_Add32, 4661 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4662 mkexpr(iTot3)) ); 4663 if (mode64) { 4664 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4665 assign( iTot5, binop(Iop_Add32, 4666 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))), 4667 mkexpr(iTot4)) ); 4668 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4669 assign( iTot6, binop(Iop_Add32, 4670 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4671 mkexpr(iTot5)) ); 4672 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4673 assign( iTot7, binop(Iop_Add32, 4674 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4675 mkexpr(iTot6)) ); 4676 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) ); 4677 assign( iTot8, binop(Iop_Add32, 4678 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4679 mkexpr(iTot7)) ); 4680 assign( rA, unop(Iop_32Uto64, 4681 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) ); 4682 } else 4683 assign( rA, mkexpr(iTot4) ); 4684 4685 break; 4686 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320) 4687 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4688 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4689 assign( iTot2, binop(Iop_Add32, 4690 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4691 mkexpr(iTot1)) ); 4692 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4693 assign( iTot3, binop(Iop_Add32, 4694 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4695 mkexpr(iTot2)) ); 4696 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4697 assign( iTot4, binop(Iop_Add32, 4698 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4699 mkexpr(iTot3)) ); 4700 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) ); 4701 4702 if (mode64) { 4703 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4704 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) ); 4705 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4706 assign( iTot6, binop(Iop_Add32, 4707 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4708 mkexpr(iTot5)) ); 4709 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4710 assign( iTot7, binop(Iop_Add32, 4711 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4712 mkexpr(iTot6)) ); 4713 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8))); 4714 assign( iTot8, binop(Iop_Add32, 4715 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4716 mkexpr(iTot7)) ); 4717 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ), 4718 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) ); 4719 } else 4720 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) ); 4721 break; 4722 default: 4723 vex_printf("dis_int_parity(ppc)(opc2)\n"); 4724 return False; 4725 } 4726 4727 putIReg( rA_addr, mkexpr(rA) ); 4728 4729 return True; 4730 } 4731 4732 4733 /* 4734 Integer Rotate Instructions 4735 */ 4736 static Bool dis_int_rot ( UInt theInstr ) 4737 { 4738 /* M-Form, MDS-Form */ 4739 UChar opc1 = ifieldOPC(theInstr); 4740 UChar rS_addr = ifieldRegDS(theInstr); 4741 UChar rA_addr = ifieldRegA(theInstr); 4742 UChar rB_addr = ifieldRegB(theInstr); 4743 UChar sh_imm = rB_addr; 4744 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) ); 4745 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) ); 4746 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) ); 4747 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) ); 4748 UChar b1 = ifieldBIT1(theInstr); 4749 UChar flag_rC = ifieldBIT0(theInstr); 4750 4751 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4752 IRTemp rS = newTemp(ty); 4753 IRTemp rA = newTemp(ty); 4754 IRTemp rB = newTemp(ty); 4755 IRTemp rot = newTemp(ty); 4756 IRExpr *r; 4757 UInt mask32; 4758 ULong mask64; 4759 4760 assign( rS, getIReg(rS_addr) ); 4761 assign( rB, getIReg(rB_addr) ); 4762 4763 switch (opc1) { 4764 case 0x14: { 4765 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500) 4766 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4767 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4768 if (mode64) { 4769 // tmp32 = (ROTL(rS_Lo32, Imm) 4770 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64) 4771 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4772 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4773 r = unop(Iop_32Uto64, r); 4774 assign( rot, binop(Iop_Or64, r, 4775 binop(Iop_Shl64, r, mkU8(32))) ); 4776 assign( rA, 4777 binop(Iop_Or64, 4778 binop(Iop_And64, mkexpr(rot), mkU64(mask64)), 4779 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) ); 4780 } 4781 else { 4782 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask); 4783 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4784 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4785 assign( rA, 4786 binop(Iop_Or32, 4787 binop(Iop_And32, mkU32(mask32), r), 4788 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) ); 4789 } 4790 break; 4791 } 4792 4793 case 0x15: { 4794 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501) 4795 vassert(MaskBeg < 32); 4796 vassert(MaskEnd < 32); 4797 vassert(sh_imm < 32); 4798 4799 if (mode64) { 4800 IRTemp rTmp = newTemp(Ity_I64); 4801 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4802 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4803 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4804 // tmp32 = (ROTL(rS_Lo32, Imm) 4805 // rA = ((tmp32 || tmp32) & mask64) 4806 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4807 r = unop(Iop_32Uto64, r); 4808 assign( rTmp, r ); 4809 r = NULL; 4810 assign( rot, binop(Iop_Or64, mkexpr(rTmp), 4811 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) ); 4812 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4813 } 4814 else { 4815 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) { 4816 /* Special-case the ,n,0,31-n form as that is just n-bit 4817 shift left, PPC32 p501 */ 4818 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4819 rA_addr, rS_addr, sh_imm); 4820 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) ); 4821 } 4822 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) { 4823 /* Special-case the ,32-n,n,31 form as that is just n-bit 4824 unsigned shift right, PPC32 p501 */ 4825 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4826 rA_addr, rS_addr, MaskBeg); 4827 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) ); 4828 } 4829 else { 4830 /* General case. */ 4831 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4832 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4833 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4834 // rA = ROTL(rS, Imm) & mask 4835 assign( rA, binop(Iop_And32, 4836 ROTL(mkexpr(rS), mkU8(sh_imm)), 4837 mkU32(mask32)) ); 4838 } 4839 } 4840 break; 4841 } 4842 4843 case 0x17: { 4844 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503 4845 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"", 4846 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd); 4847 if (mode64) { 4848 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4849 /* weird insn alert! 4850 tmp32 = (ROTL(rS_Lo32, rB[0-4]) 4851 rA = ((tmp32 || tmp32) & mask64) 4852 */ 4853 // note, ROTL does the masking, so we don't do it here 4854 r = ROTL( unop(Iop_64to32, mkexpr(rS)), 4855 unop(Iop_64to8, mkexpr(rB)) ); 4856 r = unop(Iop_32Uto64, r); 4857 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)))); 4858 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4859 } else { 4860 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4861 // rA = ROTL(rS, rB[0-4]) & mask 4862 // note, ROTL does the masking, so we don't do it here 4863 assign( rA, binop(Iop_And32, 4864 ROTL(mkexpr(rS), 4865 unop(Iop_32to8, mkexpr(rB))), 4866 mkU32(mask32)) ); 4867 } 4868 break; 4869 } 4870 4871 /* 64bit Integer Rotates */ 4872 case 0x1E: { 4873 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1); 4874 sh_imm |= b1 << 5; 4875 4876 vassert( msk_imm < 64 ); 4877 vassert( sh_imm < 64 ); 4878 4879 switch (opc2) { 4880 case 0x4: { 4881 /* r = ROTL64( rS, rB_lo6) */ 4882 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) ); 4883 4884 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555) 4885 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4886 rA_addr, rS_addr, rB_addr, msk_imm); 4887 // note, ROTL does the masking, so we don't do it here 4888 mask64 = MASK64(0, 63-msk_imm); 4889 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4890 break; 4891 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556) 4892 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4893 rA_addr, rS_addr, rB_addr, msk_imm); 4894 mask64 = MASK64(63-msk_imm, 63); 4895 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4896 break; 4897 } 4898 break; 4899 } 4900 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557) 4901 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4902 rA_addr, rS_addr, sh_imm, msk_imm); 4903 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4904 mask64 = MASK64(sh_imm, 63-msk_imm); 4905 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4906 break; 4907 // later: deal with special case: (msk_imm==0) => SHL(sh_imm) 4908 /* 4909 Hmm... looks like this'll do the job more simply: 4910 r = SHL(rS, sh_imm) 4911 m = ~(1 << (63-msk_imm)) 4912 assign(rA, r & m); 4913 */ 4914 4915 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558) 4916 if (mode64 4917 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) { 4918 /* special-case the ,64-n,n form as that is just 4919 unsigned shift-right by n */ 4920 DIP("srdi%s r%u,r%u,%u\n", 4921 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm); 4922 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) ); 4923 } else { 4924 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4925 rA_addr, rS_addr, sh_imm, msk_imm); 4926 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4927 mask64 = MASK64(0, 63-msk_imm); 4928 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4929 } 4930 break; 4931 4932 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559) 4933 if (mode64 4934 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) { 4935 /* special-case the ,n,63-n form as that is just 4936 shift-left by n */ 4937 DIP("sldi%s r%u,r%u,%u\n", 4938 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 4939 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) ); 4940 } else { 4941 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4942 rA_addr, rS_addr, sh_imm, msk_imm); 4943 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4944 mask64 = MASK64(63-msk_imm, 63); 4945 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4946 } 4947 break; 4948 4949 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560) 4950 IRTemp rA_orig = newTemp(ty); 4951 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4952 rA_addr, rS_addr, sh_imm, msk_imm); 4953 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4954 mask64 = MASK64(sh_imm, 63-msk_imm); 4955 assign( rA_orig, getIReg(rA_addr) ); 4956 assign( rA, binop(Iop_Or64, 4957 binop(Iop_And64, mkU64(mask64), r), 4958 binop(Iop_And64, mkU64(~mask64), 4959 mkexpr(rA_orig))) ); 4960 break; 4961 } 4962 default: 4963 vex_printf("dis_int_rot(ppc)(opc2)\n"); 4964 return False; 4965 } 4966 break; 4967 } 4968 4969 default: 4970 vex_printf("dis_int_rot(ppc)(opc1)\n"); 4971 return False; 4972 } 4973 4974 putIReg( rA_addr, mkexpr(rA) ); 4975 4976 if (flag_rC) { 4977 set_CR0( mkexpr(rA) ); 4978 } 4979 return True; 4980 } 4981 4982 4983 /* 4984 Integer Load Instructions 4985 */ 4986 static Bool dis_int_load ( UInt theInstr ) 4987 { 4988 /* D-Form, X-Form, DS-Form */ 4989 UChar opc1 = ifieldOPC(theInstr); 4990 UChar rD_addr = ifieldRegDS(theInstr); 4991 UChar rA_addr = ifieldRegA(theInstr); 4992 UInt uimm16 = ifieldUIMM16(theInstr); 4993 UChar rB_addr = ifieldRegB(theInstr); 4994 UInt opc2 = ifieldOPClo10(theInstr); 4995 UChar b1 = ifieldBIT1(theInstr); 4996 UChar b0 = ifieldBIT0(theInstr); 4997 4998 Int simm16 = extend_s_16to32(uimm16); 4999 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5000 IRTemp EA = newTemp(ty); 5001 IRExpr* val; 5002 5003 switch (opc1) { 5004 case 0x1F: // register offset 5005 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 5006 break; 5007 case 0x38: // immediate offset: 64bit: lq: maskoff 5008 // lowest 4 bits of immediate before forming EA 5009 simm16 = simm16 & 0xFFFFFFF0; 5010 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5011 break; 5012 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off 5013 // lowest 2 bits of immediate before forming EA 5014 simm16 = simm16 & 0xFFFFFFFC; 5015 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5016 break; 5017 default: // immediate offset 5018 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5019 break; 5020 } 5021 5022 switch (opc1) { 5023 case 0x22: // lbz (Load B & Zero, PPC32 p433) 5024 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5025 val = load(Ity_I8, mkexpr(EA)); 5026 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 5027