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 break; 5028 5029 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434) 5030 if (rA_addr == 0 || rA_addr == rD_addr) { 5031 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n"); 5032 return False; 5033 } 5034 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5035 val = load(Ity_I8, mkexpr(EA)); 5036 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 5037 putIReg( rA_addr, mkexpr(EA) ); 5038 break; 5039 5040 case 0x2A: // lha (Load HW Alg, PPC32 p445) 5041 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5042 val = load(Ity_I16, mkexpr(EA)); 5043 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5044 break; 5045 5046 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446) 5047 if (rA_addr == 0 || rA_addr == rD_addr) { 5048 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n"); 5049 return False; 5050 } 5051 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5052 val = load(Ity_I16, mkexpr(EA)); 5053 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5054 putIReg( rA_addr, mkexpr(EA) ); 5055 break; 5056 5057 case 0x28: // lhz (Load HW & Zero, PPC32 p450) 5058 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5059 val = load(Ity_I16, mkexpr(EA)); 5060 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5061 break; 5062 5063 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451) 5064 if (rA_addr == 0 || rA_addr == rD_addr) { 5065 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n"); 5066 return False; 5067 } 5068 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5069 val = load(Ity_I16, mkexpr(EA)); 5070 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5071 putIReg( rA_addr, mkexpr(EA) ); 5072 break; 5073 5074 case 0x20: // lwz (Load W & Zero, PPC32 p460) 5075 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5076 val = load(Ity_I32, mkexpr(EA)); 5077 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5078 break; 5079 5080 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461)) 5081 if (rA_addr == 0 || rA_addr == rD_addr) { 5082 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n"); 5083 return False; 5084 } 5085 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 5086 val = load(Ity_I32, mkexpr(EA)); 5087 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5088 putIReg( rA_addr, mkexpr(EA) ); 5089 break; 5090 5091 /* X Form */ 5092 case 0x1F: 5093 if (b0 != 0) { 5094 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n"); 5095 return False; 5096 } 5097 5098 switch (opc2) { 5099 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435) 5100 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5101 if (rA_addr == 0 || rA_addr == rD_addr) { 5102 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 5103 return False; 5104 } 5105 val = load(Ity_I8, mkexpr(EA)); 5106 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 5107 putIReg( rA_addr, mkexpr(EA) ); 5108 break; 5109 5110 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436) 5111 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5112 val = load(Ity_I8, mkexpr(EA)); 5113 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 5114 break; 5115 5116 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447) 5117 if (rA_addr == 0 || rA_addr == rD_addr) { 5118 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n"); 5119 return False; 5120 } 5121 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5122 val = load(Ity_I16, mkexpr(EA)); 5123 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5124 putIReg( rA_addr, mkexpr(EA) ); 5125 break; 5126 5127 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448) 5128 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5129 val = load(Ity_I16, mkexpr(EA)); 5130 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 5131 break; 5132 5133 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452) 5134 if (rA_addr == 0 || rA_addr == rD_addr) { 5135 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n"); 5136 return False; 5137 } 5138 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5139 val = load(Ity_I16, mkexpr(EA)); 5140 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5141 putIReg( rA_addr, mkexpr(EA) ); 5142 break; 5143 5144 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453) 5145 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5146 val = load(Ity_I16, mkexpr(EA)); 5147 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 5148 break; 5149 5150 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462) 5151 if (rA_addr == 0 || rA_addr == rD_addr) { 5152 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 5153 return False; 5154 } 5155 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5156 val = load(Ity_I32, mkexpr(EA)); 5157 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5158 putIReg( rA_addr, mkexpr(EA) ); 5159 break; 5160 5161 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463) 5162 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5163 val = load(Ity_I32, mkexpr(EA)); 5164 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 5165 break; 5166 5167 5168 /* 64bit Loads */ 5169 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475) 5170 if (rA_addr == 0 || rA_addr == rD_addr) { 5171 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n"); 5172 return False; 5173 } 5174 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5175 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5176 putIReg( rA_addr, mkexpr(EA) ); 5177 break; 5178 5179 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476) 5180 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5181 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5182 break; 5183 5184 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501) 5185 if (rA_addr == 0 || rA_addr == rD_addr) { 5186 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n"); 5187 return False; 5188 } 5189 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5190 putIReg( rD_addr, 5191 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5192 putIReg( rA_addr, mkexpr(EA) ); 5193 break; 5194 5195 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502) 5196 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5197 putIReg( rD_addr, 5198 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5199 break; 5200 5201 default: 5202 vex_printf("dis_int_load(ppc)(opc2)\n"); 5203 return False; 5204 } 5205 break; 5206 5207 /* DS Form - 64bit Loads. In each case EA will have been formed 5208 with the lowest 2 bits masked off the immediate offset. */ 5209 case 0x3A: 5210 switch ((b1<<1) | b0) { 5211 case 0x0: // ld (Load DWord, PPC64 p472) 5212 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5213 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5214 break; 5215 5216 case 0x1: // ldu (Load DWord, Update, PPC64 p474) 5217 if (rA_addr == 0 || rA_addr == rD_addr) { 5218 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n"); 5219 return False; 5220 } 5221 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5222 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) ); 5223 putIReg( rA_addr, mkexpr(EA) ); 5224 break; 5225 5226 case 0x2: // lwa (Load Word Alg, PPC64 p499) 5227 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5228 putIReg( rD_addr, 5229 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) ); 5230 break; 5231 5232 default: 5233 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 5234 return False; 5235 } 5236 break; 5237 5238 case 0x38: { 5239 IRTemp high = newTemp(ty); 5240 IRTemp low = newTemp(ty); 5241 /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */ 5242 DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5243 /* NOTE: there are some changes to XER[41:42] that have not been 5244 * implemented. 5245 */ 5246 // trap if EA misaligned on 16 byte address 5247 if (mode64) { 5248 if (host_endness == VexEndnessBE) { 5249 assign(high, load(ty, mkexpr( EA ) ) ); 5250 assign(low, load(ty, binop( Iop_Add64, 5251 mkexpr( EA ), 5252 mkU64( 8 ) ) ) ); 5253 } else { 5254 assign(low, load(ty, mkexpr( EA ) ) ); 5255 assign(high, load(ty, binop( Iop_Add64, 5256 mkexpr( EA ), 5257 mkU64( 8 ) ) ) ); 5258 } 5259 } else { 5260 assign(high, load(ty, binop( Iop_Add32, 5261 mkexpr( EA ), 5262 mkU32( 4 ) ) ) ); 5263 assign(low, load(ty, binop( Iop_Add32, 5264 mkexpr( EA ), 5265 mkU32( 12 ) ) ) ); 5266 } 5267 gen_SIGBUS_if_misaligned( EA, 16 ); 5268 putIReg( rD_addr, mkexpr( high) ); 5269 putIReg( rD_addr+1, mkexpr( low) ); 5270 break; 5271 } 5272 default: 5273 vex_printf("dis_int_load(ppc)(opc1)\n"); 5274 return False; 5275 } 5276 return True; 5277 } 5278 5279 5280 5281 /* 5282 Integer Store Instructions 5283 */ 5284 static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi ) 5285 { 5286 /* D-Form, X-Form, DS-Form */ 5287 UChar opc1 = ifieldOPC(theInstr); 5288 UInt rS_addr = ifieldRegDS(theInstr); 5289 UInt rA_addr = ifieldRegA(theInstr); 5290 UInt uimm16 = ifieldUIMM16(theInstr); 5291 UInt rB_addr = ifieldRegB(theInstr); 5292 UInt opc2 = ifieldOPClo10(theInstr); 5293 UChar b1 = ifieldBIT1(theInstr); 5294 UChar b0 = ifieldBIT0(theInstr); 5295 5296 Int simm16 = extend_s_16to32(uimm16); 5297 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5298 IRTemp rS = newTemp(ty); 5299 IRTemp rB = newTemp(ty); 5300 IRTemp EA = newTemp(ty); 5301 5302 assign( rB, getIReg(rB_addr) ); 5303 assign( rS, getIReg(rS_addr) ); 5304 5305 switch (opc1) { 5306 case 0x1F: // register offset 5307 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 5308 break; 5309 case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off 5310 // lowest 2 bits of immediate before forming EA 5311 simm16 = simm16 & 0xFFFFFFFC; 5312 default: // immediate offset 5313 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5314 break; 5315 } 5316 5317 switch (opc1) { 5318 case 0x26: // stb (Store B, PPC32 p509) 5319 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5320 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5321 break; 5322 5323 case 0x27: // stbu (Store B, Update, PPC32 p510) 5324 if (rA_addr == 0 ) { 5325 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n"); 5326 return False; 5327 } 5328 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5329 putIReg( rA_addr, mkexpr(EA) ); 5330 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5331 break; 5332 5333 case 0x2C: // sth (Store HW, PPC32 p522) 5334 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5335 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5336 break; 5337 5338 case 0x2D: // sthu (Store HW, Update, PPC32 p524) 5339 if (rA_addr == 0) { 5340 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n"); 5341 return False; 5342 } 5343 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5344 putIReg( rA_addr, mkexpr(EA) ); 5345 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5346 break; 5347 5348 case 0x24: // stw (Store W, PPC32 p530) 5349 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5350 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5351 break; 5352 5353 case 0x25: // stwu (Store W, Update, PPC32 p534) 5354 if (rA_addr == 0) { 5355 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n"); 5356 return False; 5357 } 5358 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5359 putIReg( rA_addr, mkexpr(EA) ); 5360 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5361 break; 5362 5363 /* X Form : all these use EA_indexed */ 5364 case 0x1F: 5365 if (b0 != 0) { 5366 vex_printf("dis_int_store(ppc)(0x1F,b0)\n"); 5367 return False; 5368 } 5369 5370 switch (opc2) { 5371 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511) 5372 if (rA_addr == 0) { 5373 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n"); 5374 return False; 5375 } 5376 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5377 putIReg( rA_addr, mkexpr(EA) ); 5378 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5379 break; 5380 5381 case 0x0D7: // stbx (Store B Indexed, PPC32 p512) 5382 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5383 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5384 break; 5385 5386 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525) 5387 if (rA_addr == 0) { 5388 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n"); 5389 return False; 5390 } 5391 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5392 putIReg( rA_addr, mkexpr(EA) ); 5393 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5394 break; 5395 5396 case 0x197: // sthx (Store HW Indexed, PPC32 p526) 5397 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5398 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5399 break; 5400 5401 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535) 5402 if (rA_addr == 0) { 5403 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n"); 5404 return False; 5405 } 5406 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5407 putIReg( rA_addr, mkexpr(EA) ); 5408 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5409 break; 5410 5411 case 0x097: // stwx (Store W Indexed, PPC32 p536) 5412 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5413 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5414 break; 5415 5416 5417 /* 64bit Stores */ 5418 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584) 5419 if (rA_addr == 0) { 5420 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n"); 5421 return False; 5422 } 5423 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5424 putIReg( rA_addr, mkexpr(EA) ); 5425 store( mkexpr(EA), mkexpr(rS) ); 5426 break; 5427 5428 case 0x095: // stdx (Store DWord Indexed, PPC64 p585) 5429 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5430 store( mkexpr(EA), mkexpr(rS) ); 5431 break; 5432 5433 default: 5434 vex_printf("dis_int_store(ppc)(opc2)\n"); 5435 return False; 5436 } 5437 break; 5438 5439 /* DS Form - 64bit Stores. In each case EA will have been formed 5440 with the lowest 2 bits masked off the immediate offset. */ 5441 case 0x3E: 5442 switch ((b1<<1) | b0) { 5443 case 0x0: // std (Store DWord, PPC64 p580) 5444 if (!mode64) 5445 return False; 5446 5447 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5448 store( mkexpr(EA), mkexpr(rS) ); 5449 break; 5450 5451 case 0x1: // stdu (Store DWord, Update, PPC64 p583) 5452 if (!mode64) 5453 return False; 5454 5455 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5456 putIReg( rA_addr, mkexpr(EA) ); 5457 store( mkexpr(EA), mkexpr(rS) ); 5458 break; 5459 5460 case 0x2: { // stq (Store QuadWord, Update, PPC64 p583) 5461 IRTemp EA_hi = newTemp(ty); 5462 IRTemp EA_lo = newTemp(ty); 5463 DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5464 5465 if (mode64) { 5466 if (host_endness == VexEndnessBE) { 5467 5468 /* upper 64-bits */ 5469 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 5470 5471 /* lower 64-bits */ 5472 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) ); 5473 } else { 5474 /* upper 64-bits */ 5475 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) ); 5476 5477 /* lower 64-bits */ 5478 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) ); 5479 } 5480 } else { 5481 /* upper half of upper 64-bits */ 5482 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) ); 5483 5484 /* lower half of upper 64-bits */ 5485 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) ); 5486 } 5487 store( mkexpr(EA_hi), mkexpr(rS) ); 5488 store( mkexpr(EA_lo), getIReg( rS_addr+1 ) ); 5489 break; 5490 } 5491 default: 5492 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 5493 return False; 5494 } 5495 break; 5496 5497 default: 5498 vex_printf("dis_int_store(ppc)(opc1)\n"); 5499 return False; 5500 } 5501 return True; 5502 } 5503 5504 5505 5506 /* 5507 Integer Load/Store Multiple Instructions 5508 */ 5509 static Bool dis_int_ldst_mult ( UInt theInstr ) 5510 { 5511 /* D-Form */ 5512 UChar opc1 = ifieldOPC(theInstr); 5513 UChar rD_addr = ifieldRegDS(theInstr); 5514 UChar rS_addr = rD_addr; 5515 UChar rA_addr = ifieldRegA(theInstr); 5516 UInt uimm16 = ifieldUIMM16(theInstr); 5517 5518 Int simm16 = extend_s_16to32(uimm16); 5519 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5520 IROp mkAdd = mode64 ? Iop_Add64 : Iop_Add32; 5521 IRTemp EA = newTemp(ty); 5522 UInt r = 0; 5523 UInt ea_off = 0; 5524 IRExpr* irx_addr; 5525 5526 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5527 5528 switch (opc1) { 5529 case 0x2E: // lmw (Load Multiple Word, PPC32 p454) 5530 if (rA_addr >= rD_addr) { 5531 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n"); 5532 return False; 5533 } 5534 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5535 for (r = rD_addr; r <= 31; r++) { 5536 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 5537 putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ), 5538 False) ); 5539 ea_off += 4; 5540 } 5541 break; 5542 5543 case 0x2F: // stmw (Store Multiple Word, PPC32 p527) 5544 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5545 for (r = rS_addr; r <= 31; r++) { 5546 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 5547 store( irx_addr, mkNarrowTo32(ty, getIReg(r)) ); 5548 ea_off += 4; 5549 } 5550 break; 5551 5552 default: 5553 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n"); 5554 return False; 5555 } 5556 return True; 5557 } 5558 5559 5560 5561 /* 5562 Integer Load/Store String Instructions 5563 */ 5564 static 5565 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5566 IRTemp EA, // EA 5567 Int rD, // first dst register 5568 Int maxBytes ) // 32 or 128 5569 { 5570 Int i, shift = 24; 5571 IRExpr* e_nbytes = mkexpr(tNBytes); 5572 IRExpr* e_EA = mkexpr(EA); 5573 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5574 5575 vassert(rD >= 0 && rD < 32); 5576 rD--; if (rD < 0) rD = 31; 5577 5578 for (i = 0; i < maxBytes; i++) { 5579 /* if (nBytes < (i+1)) goto NIA; */ 5580 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5581 Ijk_Boring, 5582 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 5583 /* when crossing into a new dest register, set it to zero. */ 5584 if ((i % 4) == 0) { 5585 rD++; if (rD == 32) rD = 0; 5586 putIReg(rD, mkSzImm(ty, 0)); 5587 shift = 24; 5588 } 5589 /* rD |= (8Uto32(*(EA+i))) << shift */ 5590 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5591 putIReg( 5592 rD, 5593 mkWidenFrom32( 5594 ty, 5595 binop( 5596 Iop_Or32, 5597 mkNarrowTo32(ty, getIReg(rD)), 5598 binop( 5599 Iop_Shl32, 5600 unop( 5601 Iop_8Uto32, 5602 load( Ity_I8, 5603 binop( mkSzOp(ty,Iop_Add8), 5604 e_EA, mkSzImm(ty,i))) 5605 ), 5606 mkU8(toUChar(shift)) 5607 ) 5608 ), 5609 /*Signed*/False 5610 ) 5611 ); 5612 shift -= 8; 5613 } 5614 } 5615 5616 static 5617 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5618 IRTemp EA, // EA 5619 Int rS, // first src register 5620 Int maxBytes ) // 32 or 128 5621 { 5622 Int i, shift = 24; 5623 IRExpr* e_nbytes = mkexpr(tNBytes); 5624 IRExpr* e_EA = mkexpr(EA); 5625 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5626 5627 vassert(rS >= 0 && rS < 32); 5628 rS--; if (rS < 0) rS = 31; 5629 5630 for (i = 0; i < maxBytes; i++) { 5631 /* if (nBytes < (i+1)) goto NIA; */ 5632 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5633 Ijk_Boring, 5634 mkSzConst( ty, nextInsnAddr() ), OFFB_CIA )); 5635 /* check for crossing into a new src register. */ 5636 if ((i % 4) == 0) { 5637 rS++; if (rS == 32) rS = 0; 5638 shift = 24; 5639 } 5640 /* *(EA+i) = 32to8(rS >> shift) */ 5641 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5642 store( 5643 binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)), 5644 unop( Iop_32to8, 5645 binop( Iop_Shr32, 5646 mkNarrowTo32( ty, getIReg(rS) ), 5647 mkU8( toUChar(shift) ))) 5648 ); 5649 shift -= 8; 5650 } 5651 } 5652 5653 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) 5654 { 5655 /* X-Form */ 5656 UChar opc1 = ifieldOPC(theInstr); 5657 UChar rD_addr = ifieldRegDS(theInstr); 5658 UChar rS_addr = rD_addr; 5659 UChar rA_addr = ifieldRegA(theInstr); 5660 UChar rB_addr = ifieldRegB(theInstr); 5661 UChar NumBytes = rB_addr; 5662 UInt opc2 = ifieldOPClo10(theInstr); 5663 UChar b0 = ifieldBIT0(theInstr); 5664 5665 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5666 IRTemp t_EA = newTemp(ty); 5667 IRTemp t_nbytes = IRTemp_INVALID; 5668 5669 *stopHere = False; 5670 5671 if (opc1 != 0x1F || b0 != 0) { 5672 vex_printf("dis_int_ldst_str(ppc)(opc1)\n"); 5673 return False; 5674 } 5675 5676 switch (opc2) { 5677 case 0x255: // lswi (Load String Word Immediate, PPC32 p455) 5678 /* NB: does not reject the case where RA is in the range of 5679 registers to be loaded. It should. */ 5680 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes); 5681 assign( t_EA, ea_rAor0(rA_addr) ); 5682 if (NumBytes == 8 && !mode64) { 5683 /* Special case hack */ 5684 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */ 5685 putIReg( rD_addr, 5686 load(Ity_I32, mkexpr(t_EA)) ); 5687 putIReg( (rD_addr+1) % 32, 5688 load(Ity_I32, 5689 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) ); 5690 } else { 5691 t_nbytes = newTemp(Ity_I32); 5692 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5693 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5694 *stopHere = True; 5695 } 5696 return True; 5697 5698 case 0x215: // lswx (Load String Word Indexed, PPC32 p456) 5699 /* NB: does not reject the case where RA is in the range of 5700 registers to be loaded. It should. Although considering 5701 that that can only be detected at run time, it's not easy to 5702 do so. */ 5703 if (rD_addr == rA_addr || rD_addr == rB_addr) 5704 return False; 5705 if (rD_addr == 0 && rA_addr == 0) 5706 return False; 5707 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5708 t_nbytes = newTemp(Ity_I32); 5709 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5710 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5711 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 ); 5712 *stopHere = True; 5713 return True; 5714 5715 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528) 5716 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes); 5717 assign( t_EA, ea_rAor0(rA_addr) ); 5718 if (NumBytes == 8 && !mode64) { 5719 /* Special case hack */ 5720 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */ 5721 store( mkexpr(t_EA), 5722 getIReg(rD_addr) ); 5723 store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)), 5724 getIReg((rD_addr+1) % 32) ); 5725 } else { 5726 t_nbytes = newTemp(Ity_I32); 5727 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5728 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5729 *stopHere = True; 5730 } 5731 return True; 5732 5733 case 0x295: // stswx (Store String Word Indexed, PPC32 p529) 5734 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5735 t_nbytes = newTemp(Ity_I32); 5736 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5737 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5738 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 ); 5739 *stopHere = True; 5740 return True; 5741 5742 default: 5743 vex_printf("dis_int_ldst_str(ppc)(opc2)\n"); 5744 return False; 5745 } 5746 return True; 5747 } 5748 5749 5750 /* ------------------------------------------------------------------ 5751 Integer Branch Instructions 5752 ------------------------------------------------------------------ */ 5753 5754 /* 5755 Branch helper function 5756 ok = BO[2] | ((CTR[0] != 0) ^ BO[1]) 5757 Returns an I32 which is 0x00000000 if the ctr condition failed 5758 and 0xFFFFFFFF otherwise. 5759 */ 5760 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO ) 5761 { 5762 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5763 IRTemp ok = newTemp(Ity_I32); 5764 5765 if ((BO >> 2) & 1) { // independent of ctr 5766 assign( ok, mkU32(0xFFFFFFFF) ); 5767 } else { 5768 if ((BO >> 1) & 1) { // ctr == 0 ? 5769 assign( ok, unop( Iop_1Sto32, 5770 binop( mkSzOp(ty, Iop_CmpEQ8), 5771 getGST( PPC_GST_CTR ), 5772 mkSzImm(ty,0))) ); 5773 } else { // ctr != 0 ? 5774 assign( ok, unop( Iop_1Sto32, 5775 binop( mkSzOp(ty, Iop_CmpNE8), 5776 getGST( PPC_GST_CTR ), 5777 mkSzImm(ty,0))) ); 5778 } 5779 } 5780 return mkexpr(ok); 5781 } 5782 5783 5784 /* 5785 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3]) 5786 Returns an I32 which is either 0 if the condition failed or 5787 some arbitrary nonzero value otherwise. */ 5788 5789 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) 5790 { 5791 Int where; 5792 IRTemp res = newTemp(Ity_I32); 5793 IRTemp cr_bi = newTemp(Ity_I32); 5794 5795 if ((BO >> 4) & 1) { 5796 assign( res, mkU32(1) ); 5797 } else { 5798 // ok = (CR[BI] == BO[3]) Note, the following relies on 5799 // getCRbit_anywhere returning a value which 5800 // is either zero or has exactly 1 bit set. 5801 assign( cr_bi, getCRbit_anywhere( BI, &where ) ); 5802 5803 if ((BO >> 3) & 1) { 5804 /* We can use cr_bi as-is. */ 5805 assign( res, mkexpr(cr_bi) ); 5806 } else { 5807 /* We have to invert the sense of the information held in 5808 cr_bi. For that we need to know which bit 5809 getCRbit_anywhere regards as significant. */ 5810 assign( res, binop(Iop_Xor32, mkexpr(cr_bi), 5811 mkU32(1<<where)) ); 5812 } 5813 } 5814 return mkexpr(res); 5815 } 5816 5817 5818 /* 5819 Integer Branch Instructions 5820 */ 5821 static Bool dis_branch ( UInt theInstr, 5822 const VexAbiInfo* vbi, 5823 /*OUT*/DisResult* dres, 5824 Bool (*resteerOkFn)(void*,Addr), 5825 void* callback_opaque ) 5826 { 5827 UChar opc1 = ifieldOPC(theInstr); 5828 UChar BO = ifieldRegDS(theInstr); 5829 UChar BI = ifieldRegA(theInstr); 5830 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */ 5831 UChar b11to15 = ifieldRegB(theInstr); 5832 UInt opc2 = ifieldOPClo10(theInstr); 5833 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */ 5834 UChar flag_AA = ifieldBIT1(theInstr); 5835 UChar flag_LK = ifieldBIT0(theInstr); 5836 5837 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5838 Addr64 tgt = 0; 5839 UInt BD = extend_s_16to32(BD_u16); 5840 IRTemp do_branch = newTemp(Ity_I32); 5841 IRTemp ctr_ok = newTemp(Ity_I32); 5842 IRTemp cond_ok = newTemp(Ity_I32); 5843 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr()); 5844 IRConst* c_nia = mkSzConst(ty, nextInsnAddr()); 5845 IRTemp lr_old = newTemp(ty); 5846 5847 /* Hack to pass through code that just wants to read the PC */ 5848 if (theInstr == 0x429F0005) { 5849 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI); 5850 putGST( PPC_GST_LR, e_nia ); 5851 return True; 5852 } 5853 5854 /* The default what-next. Individual cases can override it. */ 5855 dres->whatNext = Dis_StopHere; 5856 vassert(dres->jk_StopHere == Ijk_INVALID); 5857 5858 switch (opc1) { 5859 case 0x12: // b (Branch, PPC32 p360) 5860 if (flag_AA) { 5861 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) ); 5862 } else { 5863 tgt = mkSzAddr( ty, guest_CIA_curr_instr + 5864 (Long)extend_s_26to64(LI_u26) ); 5865 } 5866 if (mode64) { 5867 DIP("b%s%s 0x%llx\n", 5868 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt); 5869 } else { 5870 DIP("b%s%s 0x%x\n", 5871 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt); 5872 } 5873 5874 if (flag_LK) { 5875 putGST( PPC_GST_LR, e_nia ); 5876 if (vbi->guest_ppc_zap_RZ_at_bl 5877 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) { 5878 IRTemp t_tgt = newTemp(ty); 5879 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) ); 5880 make_redzone_AbiHint( vbi, t_tgt, 5881 "branch-and-link (unconditional call)" ); 5882 } 5883 } 5884 5885 if (resteerOkFn( callback_opaque, tgt )) { 5886 dres->whatNext = Dis_ResteerU; 5887 dres->continueAt = tgt; 5888 } else { 5889 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ; 5890 putGST( PPC_GST_CIA, mkSzImm(ty, tgt) ); 5891 } 5892 break; 5893 5894 case 0x10: // bc (Branch Conditional, PPC32 p361) 5895 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", 5896 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); 5897 5898 if (!(BO & 0x4)) { 5899 putGST( PPC_GST_CTR, 5900 binop(mkSzOp(ty, Iop_Sub8), 5901 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5902 } 5903 5904 /* This is a bit subtle. ctr_ok is either all 0s or all 1s. 5905 cond_ok is either zero or nonzero, since that's the cheapest 5906 way to compute it. Anding them together gives a value which 5907 is either zero or non zero and so that's what we must test 5908 for in the IRStmt_Exit. */ 5909 assign( ctr_ok, branch_ctr_ok( BO ) ); 5910 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5911 assign( do_branch, 5912 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5913 5914 if (flag_AA) { 5915 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16)); 5916 } else { 5917 tgt = mkSzAddr(ty, guest_CIA_curr_instr + 5918 (Long)extend_s_16to64(BD_u16)); 5919 } 5920 if (flag_LK) 5921 putGST( PPC_GST_LR, e_nia ); 5922 5923 stmt( IRStmt_Exit( 5924 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)), 5925 flag_LK ? Ijk_Call : Ijk_Boring, 5926 mkSzConst(ty, tgt), OFFB_CIA ) ); 5927 5928 dres->jk_StopHere = Ijk_Boring; 5929 putGST( PPC_GST_CIA, e_nia ); 5930 break; 5931 5932 case 0x13: 5933 /* For bclr and bcctr, it appears that the lowest two bits of 5934 b11to15 are a branch hint, and so we only need to ensure it's 5935 of the form 000XX. */ 5936 if ((b11to15 & ~3) != 0) { 5937 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15); 5938 return False; 5939 } 5940 5941 switch (opc2) { 5942 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363) 5943 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid 5944 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n"); 5945 return False; 5946 } 5947 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5948 5949 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5950 5951 /* FIXME: this is confusing. lr_old holds the old value 5952 of ctr, not lr :-) */ 5953 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 )); 5954 5955 if (flag_LK) 5956 putGST( PPC_GST_LR, e_nia ); 5957 5958 stmt( IRStmt_Exit( 5959 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)), 5960 Ijk_Boring, 5961 c_nia, OFFB_CIA )); 5962 5963 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) { 5964 make_redzone_AbiHint( vbi, lr_old, 5965 "b-ctr-l (indirect call)" ); 5966 } 5967 5968 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;; 5969 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 5970 break; 5971 5972 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365) 5973 Bool vanilla_return = False; 5974 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) { 5975 DIP("blr\n"); 5976 vanilla_return = True; 5977 } else { 5978 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5979 } 5980 5981 if (!(BO & 0x4)) { 5982 putGST( PPC_GST_CTR, 5983 binop(mkSzOp(ty, Iop_Sub8), 5984 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5985 } 5986 5987 /* See comments above for 'bc' about this */ 5988 assign( ctr_ok, branch_ctr_ok( BO ) ); 5989 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5990 assign( do_branch, 5991 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5992 5993 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 )); 5994 5995 if (flag_LK) 5996 putGST( PPC_GST_LR, e_nia ); 5997 5998 stmt( IRStmt_Exit( 5999 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)), 6000 Ijk_Boring, 6001 c_nia, OFFB_CIA )); 6002 6003 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) { 6004 make_redzone_AbiHint( vbi, lr_old, 6005 "branch-to-lr (unconditional return)" ); 6006 } 6007 6008 /* blrl is pretty strange; it's like a return that sets the 6009 return address of its caller to the insn following this 6010 one. Mark it as a return. */ 6011 dres->jk_StopHere = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */ 6012 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 6013 break; 6014 } 6015 default: 6016 vex_printf("dis_int_branch(ppc)(opc2)\n"); 6017 return False; 6018 } 6019 break; 6020 6021 default: 6022 vex_printf("dis_int_branch(ppc)(opc1)\n"); 6023 return False; 6024 } 6025 6026 return True; 6027 } 6028 6029 6030 6031 /* 6032 Condition Register Logical Instructions 6033 */ 6034 static Bool dis_cond_logic ( UInt theInstr ) 6035 { 6036 /* XL-Form */ 6037 UChar opc1 = ifieldOPC(theInstr); 6038 UChar crbD_addr = ifieldRegDS(theInstr); 6039 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) ); 6040 UChar crbA_addr = ifieldRegA(theInstr); 6041 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) ); 6042 UChar crbB_addr = ifieldRegB(theInstr); 6043 UInt opc2 = ifieldOPClo10(theInstr); 6044 UChar b0 = ifieldBIT0(theInstr); 6045 6046 IRTemp crbD = newTemp(Ity_I32); 6047 IRTemp crbA = newTemp(Ity_I32); 6048 IRTemp crbB = newTemp(Ity_I32); 6049 6050 if (opc1 != 19 || b0 != 0) { 6051 vex_printf("dis_cond_logic(ppc)(opc1)\n"); 6052 return False; 6053 } 6054 6055 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464) 6056 if (((crbD_addr & 0x3) != 0) || 6057 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) { 6058 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n"); 6059 return False; 6060 } 6061 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr); 6062 putCR0( crfD_addr, getCR0( crfS_addr) ); 6063 putCR321( crfD_addr, getCR321(crfS_addr) ); 6064 } else { 6065 assign( crbA, getCRbit(crbA_addr) ); 6066 if (crbA_addr == crbB_addr) 6067 crbB = crbA; 6068 else 6069 assign( crbB, getCRbit(crbB_addr) ); 6070 6071 switch (opc2) { 6072 case 0x101: // crand (Cond Reg AND, PPC32 p372) 6073 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6074 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) ); 6075 break; 6076 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373) 6077 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6078 assign( crbD, binop(Iop_And32, 6079 mkexpr(crbA), 6080 unop(Iop_Not32, mkexpr(crbB))) ); 6081 break; 6082 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374) 6083 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6084 assign( crbD, unop(Iop_Not32, 6085 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) ); 6086 break; 6087 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375) 6088 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6089 assign( crbD, unop(Iop_Not32, 6090 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) ); 6091 break; 6092 case 0x021: // crnor (Cond Reg NOR, PPC32 p376) 6093 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6094 assign( crbD, unop(Iop_Not32, 6095 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) ); 6096 break; 6097 case 0x1C1: // cror (Cond Reg OR, PPC32 p377) 6098 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6099 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) ); 6100 break; 6101 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378) 6102 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6103 assign( crbD, binop(Iop_Or32, 6104 mkexpr(crbA), 6105 unop(Iop_Not32, mkexpr(crbB))) ); 6106 break; 6107 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379) 6108 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 6109 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) ); 6110 break; 6111 default: 6112 vex_printf("dis_cond_logic(ppc)(opc2)\n"); 6113 return False; 6114 } 6115 6116 putCRbit( crbD_addr, mkexpr(crbD) ); 6117 } 6118 return True; 6119 } 6120 6121 6122 /* 6123 Trap instructions 6124 */ 6125 6126 /* Do the code generation for a trap. Returned Bool is true iff 6127 this is an unconditional trap. If the two arg IRExpr*s are 6128 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s 6129 then they are 64-bit, and we must be disassembling 64-bit 6130 instructions. */ 6131 static Bool do_trap ( UChar TO, 6132 IRExpr* argL0, IRExpr* argR0, Addr64 cia ) 6133 { 6134 IRTemp argL, argR; 6135 IRExpr *argLe, *argRe, *cond, *tmp; 6136 6137 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32; 6138 6139 IROp opAND = is32bit ? Iop_And32 : Iop_And64; 6140 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64; 6141 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S; 6142 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U; 6143 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64; 6144 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64; 6145 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0); 6146 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2); 6147 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4); 6148 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8); 6149 6150 const UChar b11100 = 0x1C; 6151 const UChar b00111 = 0x07; 6152 6153 if (is32bit) { 6154 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 ); 6155 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 ); 6156 } else { 6157 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 ); 6158 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 ); 6159 vassert( mode64 ); 6160 } 6161 6162 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) { 6163 /* Unconditional trap. Just do the exit without 6164 testing the arguments. */ 6165 stmt( IRStmt_Exit( 6166 binop(opCMPEQ, const0, const0), 6167 Ijk_SigTRAP, 6168 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 6169 OFFB_CIA 6170 )); 6171 return True; /* unconditional trap */ 6172 } 6173 6174 if (is32bit) { 6175 argL = newTemp(Ity_I32); 6176 argR = newTemp(Ity_I32); 6177 } else { 6178 argL = newTemp(Ity_I64); 6179 argR = newTemp(Ity_I64); 6180 } 6181 6182 assign( argL, argL0 ); 6183 assign( argR, argR0 ); 6184 6185 argLe = mkexpr(argL); 6186 argRe = mkexpr(argR); 6187 6188 cond = const0; 6189 if (TO & 16) { // L <s R 6190 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8); 6191 cond = binop(opOR, tmp, cond); 6192 } 6193 if (TO & 8) { // L >s R 6194 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4); 6195 cond = binop(opOR, tmp, cond); 6196 } 6197 if (TO & 4) { // L == R 6198 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2); 6199 cond = binop(opOR, tmp, cond); 6200 } 6201 if (TO & 2) { // L <u R 6202 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8); 6203 cond = binop(opOR, tmp, cond); 6204 } 6205 if (TO & 1) { // L >u R 6206 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4); 6207 cond = binop(opOR, tmp, cond); 6208 } 6209 stmt( IRStmt_Exit( 6210 binop(opCMPNE, cond, const0), 6211 Ijk_SigTRAP, 6212 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 6213 OFFB_CIA 6214 )); 6215 return False; /* not an unconditional trap */ 6216 } 6217 6218 static Bool dis_trapi ( UInt theInstr, 6219 /*OUT*/DisResult* dres ) 6220 { 6221 /* D-Form */ 6222 UChar opc1 = ifieldOPC(theInstr); 6223 UChar TO = ifieldRegDS(theInstr); 6224 UChar rA_addr = ifieldRegA(theInstr); 6225 UInt uimm16 = ifieldUIMM16(theInstr); 6226 ULong simm16 = extend_s_16to64(uimm16); 6227 Addr64 cia = guest_CIA_curr_instr; 6228 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6229 Bool uncond = False; 6230 6231 switch (opc1) { 6232 case 0x03: // twi (Trap Word Immediate, PPC32 p548) 6233 uncond = do_trap( TO, 6234 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 6235 : getIReg(rA_addr), 6236 mkU32( (UInt)simm16 ), 6237 cia ); 6238 if (TO == 4) { 6239 DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16); 6240 } else { 6241 DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16); 6242 } 6243 break; 6244 case 0x02: // tdi 6245 if (!mode64) 6246 return False; 6247 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia ); 6248 if (TO == 4) { 6249 DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16); 6250 } else { 6251 DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16); 6252 } 6253 break; 6254 default: 6255 return False; 6256 } 6257 6258 if (uncond) { 6259 /* If the trap shows signs of being unconditional, don't 6260 continue decoding past it. */ 6261 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6262 dres->jk_StopHere = Ijk_Boring; 6263 dres->whatNext = Dis_StopHere; 6264 } 6265 6266 return True; 6267 } 6268 6269 static Bool dis_trap ( UInt theInstr, 6270 /*OUT*/DisResult* dres ) 6271 { 6272 /* X-Form */ 6273 UInt opc2 = ifieldOPClo10(theInstr); 6274 UChar TO = ifieldRegDS(theInstr); 6275 UChar rA_addr = ifieldRegA(theInstr); 6276 UChar rB_addr = ifieldRegB(theInstr); 6277 Addr64 cia = guest_CIA_curr_instr; 6278 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6279 Bool uncond = False; 6280 6281 if (ifieldBIT0(theInstr) != 0) 6282 return False; 6283 6284 switch (opc2) { 6285 case 0x004: // tw (Trap Word, PPC64 p540) 6286 uncond = do_trap( TO, 6287 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 6288 : getIReg(rA_addr), 6289 mode64 ? unop(Iop_64to32, getIReg(rB_addr)) 6290 : getIReg(rB_addr), 6291 cia ); 6292 if (TO == 4) { 6293 DIP("tweq r%u,r%u\n", rA_addr, rB_addr); 6294 } else { 6295 DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr); 6296 } 6297 break; 6298 case 0x044: // td (Trap Doubleword, PPC64 p534) 6299 if (!mode64) 6300 return False; 6301 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia ); 6302 if (TO == 4) { 6303 DIP("tdeq r%u,r%u\n", rA_addr, rB_addr); 6304 } else { 6305 DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr); 6306 } 6307 break; 6308 default: 6309 return False; 6310 } 6311 6312 if (uncond) { 6313 /* If the trap shows signs of being unconditional, don't 6314 continue decoding past it. */ 6315 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6316 dres->jk_StopHere = Ijk_Boring; 6317 dres->whatNext = Dis_StopHere; 6318 } 6319 6320 return True; 6321 } 6322 6323 6324 /* 6325 System Linkage Instructions 6326 */ 6327 static Bool dis_syslink ( UInt theInstr, 6328 const VexAbiInfo* abiinfo, DisResult* dres ) 6329 { 6330 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6331 6332 if (theInstr != 0x44000002) { 6333 vex_printf("dis_syslink(ppc)(theInstr)\n"); 6334 return False; 6335 } 6336 6337 // sc (System Call, PPC32 p504) 6338 DIP("sc\n"); 6339 6340 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin 6341 Valgrind can back the guest up to this instruction if it needs 6342 to restart the syscall. */ 6343 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) ); 6344 6345 /* It's important that all ArchRegs carry their up-to-date value 6346 at this point. So we declare an end-of-block here, which 6347 forces any TempRegs caching ArchRegs to be flushed. */ 6348 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6349 6350 dres->whatNext = Dis_StopHere; 6351 dres->jk_StopHere = Ijk_Sys_syscall; 6352 return True; 6353 } 6354 6355 6356 /* 6357 Memory Synchronization Instructions 6358 6359 Note on Reservations: 6360 We rely on the assumption that V will in fact only allow one thread at 6361 once to run. In effect, a thread can make a reservation, but we don't 6362 check any stores it does. Instead, the reservation is cancelled when 6363 the scheduler switches to another thread (run_thread_for_a_while()). 6364 */ 6365 static Bool dis_memsync ( UInt theInstr ) 6366 { 6367 /* X-Form, XL-Form */ 6368 UChar opc1 = ifieldOPC(theInstr); 6369 UInt b11to25 = IFIELD(theInstr, 11, 15); 6370 UChar flag_L = ifieldRegDS(theInstr); 6371 UInt b11to20 = IFIELD(theInstr, 11, 10); 6372 UInt M0 = IFIELD(theInstr, 11, 5); 6373 UChar rD_addr = ifieldRegDS(theInstr); 6374 UChar rS_addr = rD_addr; 6375 UChar rA_addr = ifieldRegA(theInstr); 6376 UChar rB_addr = ifieldRegB(theInstr); 6377 UInt opc2 = ifieldOPClo10(theInstr); 6378 UChar b0 = ifieldBIT0(theInstr); 6379 6380 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6381 IRTemp EA = newTemp(ty); 6382 6383 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6384 6385 switch (opc1) { 6386 /* XL-Form */ 6387 case 0x13: // isync (Instruction Synchronize, PPC32 p432) 6388 if (opc2 != 0x096) { 6389 vex_printf("dis_memsync(ppc)(0x13,opc2)\n"); 6390 return False; 6391 } 6392 if (b11to25 != 0 || b0 != 0) { 6393 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n"); 6394 return False; 6395 } 6396 DIP("isync\n"); 6397 stmt( IRStmt_MBE(Imbe_Fence) ); 6398 break; 6399 6400 /* X-Form */ 6401 case 0x1F: 6402 switch (opc2) { 6403 case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394) 6404 if (M0 == 0) { 6405 if (b11to20 != 0 || b0 != 0) { 6406 vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n"); 6407 return False; 6408 } 6409 DIP("eieio\n"); 6410 } else { 6411 if (b11to20 != 0 || b0 != 0) { 6412 vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n"); 6413 return False; 6414 } 6415 DIP("mbar %d\n", M0); 6416 } 6417 /* Insert a memory fence, just to be on the safe side. */ 6418 stmt( IRStmt_MBE(Imbe_Fence) ); 6419 break; 6420 6421 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458) 6422 IRTemp res; 6423 /* According to the PowerPC ISA version 2.05, b0 (called EH 6424 in the documentation) is merely a hint bit to the 6425 hardware, I think as to whether or not contention is 6426 likely. So we can just ignore it. */ 6427 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 6428 6429 // trap if misaligned 6430 gen_SIGBUS_if_misaligned( EA, 4 ); 6431 6432 // and actually do the load 6433 res = newTemp(Ity_I32); 6434 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6435 6436 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) ); 6437 break; 6438 } 6439 6440 case 0x034: { // lbarx (Load Word and Reserve Indexed) 6441 IRTemp res; 6442 /* According to the PowerPC ISA version 2.05, b0 (called EH 6443 in the documentation) is merely a hint bit to the 6444 hardware, I think as to whether or not contention is 6445 likely. So we can just ignore it. */ 6446 DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 6447 6448 // and actually do the load 6449 res = newTemp(Ity_I8); 6450 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6451 6452 putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) ); 6453 break; 6454 } 6455 6456 case 0x074: { // lharx (Load Word and Reserve Indexed) 6457 IRTemp res; 6458 /* According to the PowerPC ISA version 2.05, b0 (called EH 6459 in the documentation) is merely a hint bit to the 6460 hardware, I think as to whether or not contention is 6461 likely. So we can just ignore it. */ 6462 DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 6463 6464 // trap if misaligned 6465 gen_SIGBUS_if_misaligned( EA, 2 ); 6466 6467 // and actually do the load 6468 res = newTemp(Ity_I16); 6469 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) ); 6470 6471 putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) ); 6472 break; 6473 } 6474 6475 case 0x096: { 6476 // stwcx. (Store Word Conditional Indexed, PPC32 p532) 6477 // Note this has to handle stwcx. in both 32- and 64-bit modes, 6478 // so isn't quite as straightforward as it might otherwise be. 6479 IRTemp rS = newTemp(Ity_I32); 6480 IRTemp resSC; 6481 if (b0 != 1) { 6482 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 6483 return False; 6484 } 6485 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6486 6487 // trap if misaligned 6488 gen_SIGBUS_if_misaligned( EA, 4 ); 6489 6490 // Get the data to be stored, and narrow to 32 bits if necessary 6491 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6492 6493 // Do the store, and get success/failure bit into resSC 6494 resSC = newTemp(Ity_I1); 6495 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6496 6497 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6498 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6499 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6500 putCR0(0, getXER_SO()); 6501 6502 /* Note: 6503 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 6504 whether rS is stored is dependent on that value. */ 6505 /* So I guess we can just ignore this case? */ 6506 break; 6507 } 6508 6509 case 0x2B6: { 6510 // stbcx. (Store Byte Conditional Indexed) 6511 // Note this has to handle stbcx. in both 32- and 64-bit modes, 6512 // so isn't quite as straightforward as it might otherwise be. 6513 IRTemp rS = newTemp(Ity_I8); 6514 IRTemp resSC; 6515 if (b0 != 1) { 6516 vex_printf("dis_memsync(ppc)(stbcx.,b0)\n"); 6517 return False; 6518 } 6519 DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6520 6521 // Get the data to be stored, and narrow to 32 bits if necessary 6522 assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) ); 6523 6524 // Do the store, and get success/failure bit into resSC 6525 resSC = newTemp(Ity_I1); 6526 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6527 6528 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6529 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6530 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6531 putCR0(0, getXER_SO()); 6532 6533 /* Note: 6534 If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and 6535 whether rS is stored is dependent on that value. */ 6536 /* So I guess we can just ignore this case? */ 6537 break; 6538 } 6539 6540 case 0x2D6: { 6541 // sthcx. (Store Word Conditional Indexed, PPC32 p532) 6542 // Note this has to handle sthcx. in both 32- and 64-bit modes, 6543 // so isn't quite as straightforward as it might otherwise be. 6544 IRTemp rS = newTemp(Ity_I16); 6545 IRTemp resSC; 6546 if (b0 != 1) { 6547 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 6548 return False; 6549 } 6550 DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6551 6552 // trap if misaligned 6553 gen_SIGBUS_if_misaligned( EA, 2 ); 6554 6555 // Get the data to be stored, and narrow to 16 bits if necessary 6556 assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) ); 6557 6558 // Do the store, and get success/failure bit into resSC 6559 resSC = newTemp(Ity_I1); 6560 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6561 6562 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6563 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6564 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6565 putCR0(0, getXER_SO()); 6566 6567 /* Note: 6568 If resaddr != lharx_resaddr, CR0[EQ] is undefined, and 6569 whether rS is stored is dependent on that value. */ 6570 /* So I guess we can just ignore this case? */ 6571 break; 6572 } 6573 6574 case 0x256: // sync (Synchronize, PPC32 p543), 6575 // also lwsync (L==1), ptesync (L==2) 6576 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html 6577 6578 The PowerPC architecture used in IBM chips has expanded 6579 the sync instruction into two variants: lightweight sync 6580 and heavyweight sync. The original sync instruction is 6581 the new heavyweight sync and lightweight sync is a strict 6582 subset of the heavyweight sync functionality. This allows 6583 the programmer to specify a less expensive operation on 6584 high-end systems when the full sync functionality is not 6585 necessary. 6586 6587 The basic "sync" mnemonic now utilizes an operand. "sync" 6588 without an operand now becomes a extended mnemonic for 6589 heavyweight sync. Processors without the lwsync 6590 instruction will not decode the L field and will perform a 6591 heavyweight sync. Everything is backward compatible. 6592 6593 sync = sync 0 6594 lwsync = sync 1 6595 ptesync = sync 2 *** TODO - not implemented *** 6596 */ 6597 if (b11to20 != 0 || b0 != 0) { 6598 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n"); 6599 return False; 6600 } 6601 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) { 6602 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n"); 6603 return False; 6604 } 6605 DIP("%ssync\n", flag_L == 1 ? "lw" : ""); 6606 /* Insert a memory fence. It's sometimes important that these 6607 are carried through to the generated code. */ 6608 stmt( IRStmt_MBE(Imbe_Fence) ); 6609 break; 6610 6611 /* 64bit Memsync */ 6612 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473) 6613 IRTemp res; 6614 /* According to the PowerPC ISA version 2.05, b0 (called EH 6615 in the documentation) is merely a hint bit to the 6616 hardware, I think as to whether or not contention is 6617 likely. So we can just ignore it. */ 6618 if (!mode64) 6619 return False; 6620 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 6621 6622 // trap if misaligned 6623 gen_SIGBUS_if_misaligned( EA, 8 ); 6624 6625 // and actually do the load 6626 res = newTemp(Ity_I64); 6627 stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) ); 6628 6629 putIReg( rD_addr, mkexpr(res) ); 6630 break; 6631 } 6632 6633 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581) 6634 // A marginally simplified version of the stwcx. case 6635 IRTemp rS = newTemp(Ity_I64); 6636 IRTemp resSC; 6637 if (b0 != 1) { 6638 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n"); 6639 return False; 6640 } 6641 if (!mode64) 6642 return False; 6643 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6644 6645 // trap if misaligned 6646 gen_SIGBUS_if_misaligned( EA, 8 ); 6647 6648 // Get the data to be stored 6649 assign( rS, getIReg(rS_addr) ); 6650 6651 // Do the store, and get success/failure bit into resSC 6652 resSC = newTemp(Ity_I1); 6653 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) ); 6654 6655 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6656 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6657 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6658 putCR0(0, getXER_SO()); 6659 6660 /* Note: 6661 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 6662 whether rS is stored is dependent on that value. */ 6663 /* So I guess we can just ignore this case? */ 6664 break; 6665 } 6666 6667 /* 128bit Memsync */ 6668 case 0x114: { // lqarx (Load QuadWord and Reserve Indexed) 6669 IRTemp res_hi = newTemp(ty); 6670 IRTemp res_lo = newTemp(ty); 6671 6672 /* According to the PowerPC ISA version 2.07, b0 (called EH 6673 in the documentation) is merely a hint bit to the 6674 hardware, I think as to whether or not contention is 6675 likely. So we can just ignore it. */ 6676 DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0); 6677 6678 // trap if misaligned 6679 gen_SIGBUS_if_misaligned( EA, 16 ); 6680 6681 // and actually do the load 6682 if (mode64) { 6683 if (host_endness == VexEndnessBE) { 6684 stmt( stmt_load( res_hi, 6685 mkexpr(EA), NULL/*this is a load*/) ); 6686 stmt( stmt_load( res_lo, 6687 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 6688 NULL/*this is a load*/) ); 6689 } else { 6690 stmt( stmt_load( res_lo, 6691 mkexpr(EA), NULL/*this is a load*/) ); 6692 stmt( stmt_load( res_hi, 6693 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 6694 NULL/*this is a load*/) ); 6695 } 6696 } else { 6697 stmt( stmt_load( res_hi, 6698 binop( Iop_Add32, mkexpr(EA), mkU32(4) ), 6699 NULL/*this is a load*/) ); 6700 stmt( stmt_load( res_lo, 6701 binop( Iop_Add32, mkexpr(EA), mkU32(12) ), 6702 NULL/*this is a load*/) ); 6703 } 6704 putIReg( rD_addr, mkexpr(res_hi) ); 6705 putIReg( rD_addr+1, mkexpr(res_lo) ); 6706 break; 6707 } 6708 6709 case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64) 6710 // A marginally simplified version of the stwcx. case 6711 IRTemp rS_hi = newTemp(ty); 6712 IRTemp rS_lo = newTemp(ty); 6713 IRTemp resSC; 6714 if (b0 != 1) { 6715 vex_printf("dis_memsync(ppc)(stqcx.,b0)\n"); 6716 return False; 6717 } 6718 6719 DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6720 6721 // trap if misaligned 6722 gen_SIGBUS_if_misaligned( EA, 16 ); 6723 // Get the data to be stored 6724 assign( rS_hi, getIReg(rS_addr) ); 6725 assign( rS_lo, getIReg(rS_addr+1) ); 6726 6727 // Do the store, and get success/failure bit into resSC 6728 resSC = newTemp(Ity_I1); 6729 6730 if (mode64) { 6731 if (host_endness == VexEndnessBE) { 6732 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) ); 6733 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 6734 mkexpr(rS_lo) ); 6735 } else { 6736 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) ); 6737 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), 6738 mkexpr(rS_hi) ); 6739 } 6740 } else { 6741 stmt( stmt_load( resSC, binop( Iop_Add32, 6742 mkexpr(EA), 6743 mkU32(4) ), 6744 mkexpr(rS_hi) ) ); 6745 store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) ); 6746 } 6747 6748 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6749 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6750 putCR321(0, binop( Iop_Shl8, 6751 unop(Iop_1Uto8, mkexpr(resSC) ), 6752 mkU8(1))); 6753 putCR0(0, getXER_SO()); 6754 break; 6755 } 6756 6757 default: 6758 vex_printf("dis_memsync(ppc)(opc2)\n"); 6759 return False; 6760 } 6761 break; 6762 6763 default: 6764 vex_printf("dis_memsync(ppc)(opc1)\n"); 6765 return False; 6766 } 6767 return True; 6768 } 6769 6770 6771 6772 /* 6773 Integer Shift Instructions 6774 */ 6775 static Bool dis_int_shift ( UInt theInstr ) 6776 { 6777 /* X-Form, XS-Form */ 6778 UChar opc1 = ifieldOPC(theInstr); 6779 UChar rS_addr = ifieldRegDS(theInstr); 6780 UChar rA_addr = ifieldRegA(theInstr); 6781 UChar rB_addr = ifieldRegB(theInstr); 6782 UChar sh_imm = rB_addr; 6783 UInt opc2 = ifieldOPClo10(theInstr); 6784 UChar b1 = ifieldBIT1(theInstr); 6785 UChar flag_rC = ifieldBIT0(theInstr); 6786 6787 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6788 IRTemp rA = newTemp(ty); 6789 IRTemp rS = newTemp(ty); 6790 IRTemp rB = newTemp(ty); 6791 IRTemp outofrange = newTemp(Ity_I1); 6792 IRTemp rS_lo32 = newTemp(Ity_I32); 6793 IRTemp rB_lo32 = newTemp(Ity_I32); 6794 IRExpr* e_tmp; 6795 6796 assign( rS, getIReg(rS_addr) ); 6797 assign( rB, getIReg(rB_addr) ); 6798 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) ); 6799 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) ); 6800 6801 if (opc1 == 0x1F) { 6802 switch (opc2) { 6803 case 0x018: { // slw (Shift Left Word, PPC32 p505) 6804 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6805 rA_addr, rS_addr, rB_addr); 6806 /* rA = rS << rB */ 6807 /* ppc32 semantics are: 6808 slw(x,y) = (x << (y & 31)) -- primary result 6809 & ~((y << 26) >>s 31) -- make result 0 6810 for y in 32 .. 63 6811 */ 6812 e_tmp = 6813 binop( Iop_And32, 6814 binop( Iop_Shl32, 6815 mkexpr(rS_lo32), 6816 unop( Iop_32to8, 6817 binop(Iop_And32, 6818 mkexpr(rB_lo32), mkU32(31)))), 6819 unop( Iop_Not32, 6820 binop( Iop_Sar32, 6821 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)), 6822 mkU8(31))) ); 6823 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6824 break; 6825 } 6826 6827 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506) 6828 IRTemp sh_amt = newTemp(Ity_I32); 6829 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6830 rA_addr, rS_addr, rB_addr); 6831 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is: 6832 amt = rB & 63 6833 rA = Sar32( rS, amt > 31 ? 31 : amt ) 6834 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi) 6835 */ 6836 assign( sh_amt, binop(Iop_And32, mkU32(0x3F), 6837 mkexpr(rB_lo32)) ); 6838 assign( outofrange, 6839 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) ); 6840 e_tmp = binop( Iop_Sar32, 6841 mkexpr(rS_lo32), 6842 unop( Iop_32to8, 6843 IRExpr_ITE( mkexpr(outofrange), 6844 mkU32(31), 6845 mkexpr(sh_amt)) ) ); 6846 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) ); 6847 6848 set_XER_CA( ty, PPCG_FLAG_OP_SRAW, 6849 mkexpr(rA), 6850 mkWidenFrom32(ty, mkexpr(rS_lo32), True), 6851 mkWidenFrom32(ty, mkexpr(sh_amt), True ), 6852 mkWidenFrom32(ty, getXER_CA32(), True) ); 6853 break; 6854 } 6855 6856 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507) 6857 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"", 6858 rA_addr, rS_addr, sh_imm); 6859 vassert(sh_imm < 32); 6860 if (mode64) { 6861 assign( rA, binop(Iop_Sar64, 6862 binop(Iop_Shl64, getIReg(rS_addr), 6863 mkU8(32)), 6864 mkU8(32 + sh_imm)) ); 6865 } else { 6866 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32), 6867 mkU8(sh_imm)) ); 6868 } 6869 6870 set_XER_CA( ty, PPCG_FLAG_OP_SRAWI, 6871 mkexpr(rA), 6872 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True), 6873 mkSzImm(ty, sh_imm), 6874 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6875 break; 6876 6877 case 0x218: // srw (Shift Right Word, PPC32 p508) 6878 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6879 rA_addr, rS_addr, rB_addr); 6880 /* rA = rS >>u rB */ 6881 /* ppc32 semantics are: 6882 srw(x,y) = (x >>u (y & 31)) -- primary result 6883 & ~((y << 26) >>s 31) -- make result 0 6884 for y in 32 .. 63 6885 */ 6886 e_tmp = 6887 binop( 6888 Iop_And32, 6889 binop( Iop_Shr32, 6890 mkexpr(rS_lo32), 6891 unop( Iop_32to8, 6892 binop(Iop_And32, mkexpr(rB_lo32), 6893 mkU32(31)))), 6894 unop( Iop_Not32, 6895 binop( Iop_Sar32, 6896 binop(Iop_Shl32, mkexpr(rB_lo32), 6897 mkU8(26)), 6898 mkU8(31)))); 6899 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6900 break; 6901 6902 6903 /* 64bit Shifts */ 6904 case 0x01B: // sld (Shift Left DWord, PPC64 p568) 6905 DIP("sld%s r%u,r%u,r%u\n", 6906 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6907 /* rA = rS << rB */ 6908 /* ppc64 semantics are: 6909 slw(x,y) = (x << (y & 63)) -- primary result 6910 & ~((y << 57) >>s 63) -- make result 0 6911 for y in 64 .. 6912 */ 6913 assign( rA, 6914 binop( 6915 Iop_And64, 6916 binop( Iop_Shl64, 6917 mkexpr(rS), 6918 unop( Iop_64to8, 6919 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6920 unop( Iop_Not64, 6921 binop( Iop_Sar64, 6922 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6923 mkU8(63)))) ); 6924 break; 6925 6926 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570) 6927 IRTemp sh_amt = newTemp(Ity_I64); 6928 DIP("srad%s r%u,r%u,r%u\n", 6929 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6930 /* amt = rB & 127 6931 rA = Sar64( rS, amt > 63 ? 63 : amt ) 6932 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi) 6933 */ 6934 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) ); 6935 assign( outofrange, 6936 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) ); 6937 assign( rA, 6938 binop( Iop_Sar64, 6939 mkexpr(rS), 6940 unop( Iop_64to8, 6941 IRExpr_ITE( mkexpr(outofrange), 6942 mkU64(63), 6943 mkexpr(sh_amt)) )) 6944 ); 6945 set_XER_CA( ty, PPCG_FLAG_OP_SRAD, 6946 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt), 6947 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6948 break; 6949 } 6950 6951 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571) 6952 sh_imm |= b1<<5; 6953 vassert(sh_imm < 64); 6954 DIP("sradi%s r%u,r%u,%u\n", 6955 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 6956 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) ); 6957 6958 set_XER_CA( ty, PPCG_FLAG_OP_SRADI, 6959 mkexpr(rA), 6960 getIReg(rS_addr), 6961 mkU64(sh_imm), 6962 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6963 break; 6964 6965 case 0x21B: // srd (Shift Right DWord, PPC64 p574) 6966 DIP("srd%s r%u,r%u,r%u\n", 6967 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6968 /* rA = rS >>u rB */ 6969 /* ppc semantics are: 6970 srw(x,y) = (x >>u (y & 63)) -- primary result 6971 & ~((y << 57) >>s 63) -- make result 0 6972 for y in 64 .. 127 6973 */ 6974 assign( rA, 6975 binop( 6976 Iop_And64, 6977 binop( Iop_Shr64, 6978 mkexpr(rS), 6979 unop( Iop_64to8, 6980 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6981 unop( Iop_Not64, 6982 binop( Iop_Sar64, 6983 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6984 mkU8(63)))) ); 6985 break; 6986 6987 default: 6988 vex_printf("dis_int_shift(ppc)(opc2)\n"); 6989 return False; 6990 } 6991 } else { 6992 vex_printf("dis_int_shift(ppc)(opc1)\n"); 6993 return False; 6994 } 6995 6996 putIReg( rA_addr, mkexpr(rA) ); 6997 6998 if (flag_rC) { 6999 set_CR0( mkexpr(rA) ); 7000 } 7001 return True; 7002 } 7003 7004 7005 7006 /* 7007 Integer Load/Store Reverse Instructions 7008 */ 7009 /* Generates code to swap the byte order in an Ity_I32. */ 7010 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t ) 7011 { 7012 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 7013 return 7014 binop(Iop_Or32, 7015 binop(Iop_Shl32, mkexpr(t), mkU8(24)), 7016 binop(Iop_Or32, 7017 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 7018 mkU32(0x00FF0000)), 7019 binop(Iop_Or32, 7020 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 7021 mkU32(0x0000FF00)), 7022 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)), 7023 mkU32(0x000000FF) ) 7024 ))); 7025 } 7026 7027 /* Generates code to swap the byte order in the lower half of an Ity_I32, 7028 and zeroes the upper half. */ 7029 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t ) 7030 { 7031 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 7032 return 7033 binop(Iop_Or32, 7034 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 7035 mkU32(0x0000FF00)), 7036 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 7037 mkU32(0x000000FF)) 7038 ); 7039 } 7040 7041 static Bool dis_int_ldst_rev ( UInt theInstr ) 7042 { 7043 /* X-Form */ 7044 UChar opc1 = ifieldOPC(theInstr); 7045 UChar rD_addr = ifieldRegDS(theInstr); 7046 UChar rS_addr = rD_addr; 7047 UChar rA_addr = ifieldRegA(theInstr); 7048 UChar rB_addr = ifieldRegB(theInstr); 7049 UInt opc2 = ifieldOPClo10(theInstr); 7050 UChar b0 = ifieldBIT0(theInstr); 7051 7052 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7053 IRTemp EA = newTemp(ty); 7054 IRTemp w1 = newTemp(Ity_I32); 7055 IRTemp w2 = newTemp(Ity_I32); 7056 7057 if (opc1 != 0x1F || b0 != 0) { 7058 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n"); 7059 return False; 7060 } 7061 7062 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7063 7064 switch (opc2) { 7065 7066 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449) 7067 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7068 assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) ); 7069 assign( w2, gen_byterev16(w1) ); 7070 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 7071 /* Signed */False) ); 7072 break; 7073 7074 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459) 7075 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7076 assign( w1, load(Ity_I32, mkexpr(EA)) ); 7077 assign( w2, gen_byterev32(w1) ); 7078 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 7079 /* Signed */False) ); 7080 break; 7081 7082 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed) 7083 { 7084 IRExpr * nextAddr; 7085 IRTemp w3 = newTemp( Ity_I32 ); 7086 IRTemp w4 = newTemp( Ity_I32 ); 7087 DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 7088 assign( w1, load( Ity_I32, mkexpr( EA ) ) ); 7089 assign( w2, gen_byterev32( w1 ) ); 7090 nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 7091 ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) ); 7092 assign( w3, load( Ity_I32, nextAddr ) ); 7093 assign( w4, gen_byterev32( w3 ) ); 7094 if (host_endness == VexEndnessLE) 7095 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) ); 7096 else 7097 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) ); 7098 break; 7099 } 7100 7101 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523) 7102 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7103 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 7104 store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) ); 7105 break; 7106 7107 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531) 7108 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7109 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 7110 store( mkexpr(EA), gen_byterev32(w1) ); 7111 break; 7112 7113 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed) 7114 { 7115 IRTemp lo = newTemp(Ity_I32); 7116 IRTemp hi = newTemp(Ity_I32); 7117 IRTemp rS = newTemp(Ity_I64); 7118 assign( rS, getIReg( rS_addr ) ); 7119 DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 7120 assign(lo, unop(Iop_64HIto32, mkexpr(rS))); 7121 assign(hi, unop(Iop_64to32, mkexpr(rS))); 7122 store( mkexpr( EA ), 7123 binop( Iop_32HLto64, gen_byterev32( hi ), 7124 gen_byterev32( lo ) ) ); 7125 break; 7126 } 7127 7128 default: 7129 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n"); 7130 return False; 7131 } 7132 return True; 7133 } 7134 7135 7136 7137 /* 7138 Processor Control Instructions 7139 */ 7140 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr ) 7141 { 7142 UChar opc1 = ifieldOPC(theInstr); 7143 7144 /* X-Form */ 7145 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 7146 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 7147 UChar rD_addr = ifieldRegDS(theInstr); 7148 UInt b11to20 = IFIELD( theInstr, 11, 10 ); 7149 7150 /* XFX-Form */ 7151 UChar rS_addr = rD_addr; 7152 UInt SPR = b11to20; 7153 UInt TBR = b11to20; 7154 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) ); 7155 UInt CRM = IFIELD( theInstr, 12, 8 ); 7156 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 7157 7158 UInt opc2 = ifieldOPClo10(theInstr); 7159 UChar b0 = ifieldBIT0(theInstr); 7160 7161 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7162 IRTemp rS = newTemp(ty); 7163 assign( rS, getIReg(rS_addr) ); 7164 7165 /* Reorder SPR field as per PPC32 p470 */ 7166 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); 7167 /* Reorder TBR field as per PPC32 p475 */ 7168 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31); 7169 7170 /* b0 = 0, inst is treated as floating point inst for reservation purposes 7171 * b0 = 1, inst is treated as vector inst for reservation purposes 7172 */ 7173 if (opc1 != 0x1F) { 7174 vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0); 7175 return False; 7176 } 7177 7178 switch (opc2) { 7179 /* X-Form */ 7180 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466) 7181 if (b21to22 != 0 || b11to20 != 0) { 7182 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n"); 7183 return False; 7184 } 7185 DIP("mcrxr crf%d\n", crfD); 7186 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */ 7187 putGST_field( PPC_GST_CR, 7188 getGST_field( PPC_GST_XER, 7 ), 7189 crfD ); 7190 7191 // Clear XER[0-3] 7192 putXER_SO( mkU8(0) ); 7193 putXER_OV( mkU8(0) ); 7194 putXER_CA( mkU8(0) ); 7195 break; 7196 } 7197 7198 case 0x013: 7199 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467) 7200 // b20==1 & b11==0: mfocrf (Move from One CR Field) 7201 // However it seems that the 'mfcr' behaviour is an acceptable 7202 // implementation of mfocr (from the 2.02 arch spec) 7203 if (b11to20 == 0) { 7204 DIP("mfcr r%u\n", rD_addr); 7205 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 7206 /* Signed */False) ); 7207 break; 7208 } 7209 if (b20 == 1 && b11 == 0) { 7210 DIP("mfocrf r%u,%u\n", rD_addr, CRM); 7211 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 7212 /* Signed */False) ); 7213 break; 7214 } 7215 /* not decodable */ 7216 return False; 7217 7218 /* XFX-Form */ 7219 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470) 7220 7221 switch (SPR) { // Choose a register... 7222 case 0x1: 7223 DIP("mfxer r%u\n", rD_addr); 7224 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ), 7225 /* Signed */False) ); 7226 break; 7227 case 0x8: 7228 DIP("mflr r%u\n", rD_addr); 7229 putIReg( rD_addr, getGST( PPC_GST_LR ) ); 7230 break; 7231 case 0x9: 7232 DIP("mfctr r%u\n", rD_addr); 7233 putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 7234 break; 7235 case 0x80: // 128 7236 DIP("mfspr r%u (TFHAR)\n", rD_addr); 7237 putIReg( rD_addr, getGST( PPC_GST_TFHAR) ); 7238 break; 7239 case 0x81: // 129 7240 DIP("mfspr r%u (TFIAR)\n", rD_addr); 7241 putIReg( rD_addr, getGST( PPC_GST_TFIAR) ); 7242 break; 7243 case 0x82: // 130 7244 DIP("mfspr r%u (TEXASR)\n", rD_addr); 7245 putIReg( rD_addr, getGST( PPC_GST_TEXASR) ); 7246 break; 7247 case 0x83: // 131 7248 DIP("mfspr r%u (TEXASRU)\n", rD_addr); 7249 putIReg( rD_addr, getGST( PPC_GST_TEXASRU) ); 7250 break; 7251 case 0x9F: // 159 7252 DIP("mfspr r%u (PSPB)\n", rD_addr); 7253 putIReg( rD_addr, getGST( PPC_GST_PSPB) ); 7254 break; 7255 case 0x380: // 896 7256 DIP("mfspr r%u (PPR)\n", rD_addr); 7257 putIReg( rD_addr, getGST( PPC_GST_PPR) ); 7258 break; 7259 case 0x382: // 898 7260 DIP("mfspr r%u (PPR)32\n", rD_addr); 7261 putIReg( rD_addr, getGST( PPC_GST_PPR32) ); 7262 break; 7263 case 0x100: 7264 DIP("mfvrsave r%u\n", rD_addr); 7265 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ), 7266 /* Signed */False) ); 7267 break; 7268 7269 case 0x103: 7270 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr); 7271 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) ); 7272 break; 7273 7274 /* Even a lowly PPC7400 can run the associated helper, so no 7275 obvious need for feature testing at this point. */ 7276 case 268 /* 0x10C */: 7277 case 269 /* 0x10D */: { 7278 UInt arg = SPR==268 ? 0 : 1; 7279 IRTemp val = newTemp(Ity_I32); 7280 IRExpr** args = mkIRExprVec_1( mkU32(arg) ); 7281 IRDirty* d = unsafeIRDirty_1_N( 7282 val, 7283 0/*regparms*/, 7284 "ppc32g_dirtyhelper_MFSPR_268_269", 7285 fnptr_to_fnentry 7286 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269), 7287 args 7288 ); 7289 /* execute the dirty call, dumping the result in val. */ 7290 stmt( IRStmt_Dirty(d) ); 7291 putIReg( rD_addr, 7292 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 7293 DIP("mfspr r%u,%u", rD_addr, SPR); 7294 break; 7295 } 7296 7297 /* Again, runs natively on PPC7400 (7447, really). Not 7298 bothering with a feature test. */ 7299 case 287: /* 0x11F */ { 7300 IRTemp val = newTemp(Ity_I32); 7301 IRExpr** args = mkIRExprVec_0(); 7302 IRDirty* d = unsafeIRDirty_1_N( 7303 val, 7304 0/*regparms*/, 7305 "ppc32g_dirtyhelper_MFSPR_287", 7306 fnptr_to_fnentry 7307 (vbi, &ppc32g_dirtyhelper_MFSPR_287), 7308 args 7309 ); 7310 /* execute the dirty call, dumping the result in val. */ 7311 stmt( IRStmt_Dirty(d) ); 7312 putIReg( rD_addr, 7313 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 7314 DIP("mfspr r%u,%u", rD_addr, SPR); 7315 break; 7316 } 7317 7318 default: 7319 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR); 7320 return False; 7321 } 7322 break; 7323 7324 case 0x173: { // mftb (Move from Time Base, PPC32 p475) 7325 IRTemp val = newTemp(Ity_I64); 7326 IRExpr** args = mkIRExprVec_0(); 7327 IRDirty* d = unsafeIRDirty_1_N( 7328 val, 7329 0/*regparms*/, 7330 "ppcg_dirtyhelper_MFTB", 7331 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB), 7332 args ); 7333 /* execute the dirty call, dumping the result in val. */ 7334 stmt( IRStmt_Dirty(d) ); 7335 7336 switch (TBR) { 7337 case 269: 7338 DIP("mftbu r%u", rD_addr); 7339 putIReg( rD_addr, 7340 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)), 7341 /* Signed */False) ); 7342 break; 7343 case 268: 7344 DIP("mftb r%u", rD_addr); 7345 putIReg( rD_addr, (mode64) ? mkexpr(val) : 7346 unop(Iop_64to32, mkexpr(val)) ); 7347 break; 7348 default: 7349 return False; /* illegal instruction */ 7350 } 7351 break; 7352 } 7353 7354 case 0x090: { 7355 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477) 7356 // b20==1: mtocrf (Move to One Cond Reg Field) 7357 Int cr; 7358 UChar shft; 7359 if (b11 != 0) 7360 return False; 7361 if (b20 == 1) { 7362 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if > 7363 1 field is written. It seems more robust to decline to 7364 decode the insn if so. */ 7365 switch (CRM) { 7366 case 0x01: case 0x02: case 0x04: case 0x08: 7367 case 0x10: case 0x20: case 0x40: case 0x80: 7368 break; 7369 default: 7370 return False; 7371 } 7372 } 7373 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf", 7374 CRM, rS_addr); 7375 /* Write to each field specified by CRM */ 7376 for (cr = 0; cr < 8; cr++) { 7377 if ((CRM & (1 << (7-cr))) == 0) 7378 continue; 7379 shft = 4*(7-cr); 7380 putGST_field( PPC_GST_CR, 7381 binop(Iop_Shr32, 7382 mkNarrowTo32(ty, mkexpr(rS)), 7383 mkU8(shft)), cr ); 7384 } 7385 break; 7386 } 7387 7388 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483) 7389 7390 switch (SPR) { // Choose a register... 7391 case 0x1: 7392 DIP("mtxer r%u\n", rS_addr); 7393 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) ); 7394 break; 7395 case 0x8: 7396 DIP("mtlr r%u\n", rS_addr); 7397 putGST( PPC_GST_LR, mkexpr(rS) ); 7398 break; 7399 case 0x9: 7400 DIP("mtctr r%u\n", rS_addr); 7401 putGST( PPC_GST_CTR, mkexpr(rS) ); 7402 break; 7403 case 0x100: 7404 DIP("mtvrsave r%u\n", rS_addr); 7405 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) ); 7406 break; 7407 case 0x80: // 128 7408 DIP("mtspr r%u (TFHAR)\n", rS_addr); 7409 putGST( PPC_GST_TFHAR, mkexpr(rS) ); 7410 break; 7411 case 0x81: // 129 7412 DIP("mtspr r%u (TFIAR)\n", rS_addr); 7413 putGST( PPC_GST_TFIAR, mkexpr(rS) ); 7414 break; 7415 case 0x82: // 130 7416 DIP("mtspr r%u (TEXASR)\n", rS_addr); 7417 putGST( PPC_GST_TEXASR, mkexpr(rS) ); 7418 break; 7419 case 0x9F: // 159 7420 DIP("mtspr r%u (PSPB)\n", rS_addr); 7421 putGST( PPC_GST_PSPB, mkexpr(rS) ); 7422 break; 7423 case 0x380: // 896 7424 DIP("mtspr r%u (PPR)\n", rS_addr); 7425 putGST( PPC_GST_PPR, mkexpr(rS) ); 7426 break; 7427 case 0x382: // 898 7428 DIP("mtspr r%u (PPR32)\n", rS_addr); 7429 putGST( PPC_GST_PPR32, mkexpr(rS) ); 7430 break; 7431 default: 7432 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR); 7433 return False; 7434 } 7435 break; 7436 7437 case 0x33: // mfvsrd 7438 { 7439 UChar XS = ifieldRegXS( theInstr ); 7440 UChar rA_addr = ifieldRegA(theInstr); 7441 IRExpr * high64; 7442 IRTemp vS = newTemp( Ity_V128 ); 7443 DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS); 7444 7445 /* XS = SX || S 7446 * For SX=0, mfvsrd is treated as a Floating-Point 7447 * instruction in terms of resource availability. 7448 * For SX=1, mfvsrd is treated as a Vector instruction in 7449 * terms of resource availability. 7450 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7451 */ 7452 assign( vS, getVSReg( XS ) ); 7453 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 7454 putIReg( rA_addr, (mode64) ? high64 : 7455 unop( Iop_64to32, high64 ) ); 7456 break; 7457 } 7458 7459 case 0x73: // mfvsrwz 7460 { 7461 UChar XS = ifieldRegXS( theInstr ); 7462 UChar rA_addr = ifieldRegA(theInstr); 7463 IRExpr * high64; 7464 IRTemp vS = newTemp( Ity_V128 ); 7465 DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS); 7466 /* XS = SX || S 7467 * For SX=0, mfvsrwz is treated as a Floating-Point 7468 * instruction in terms of resource availability. 7469 * For SX=1, mfvsrwz is treated as a Vector instruction in 7470 * terms of resource availability. 7471 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7472 */ 7473 7474 assign( vS, getVSReg( XS ) ); 7475 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 7476 /* move value to the destination setting the upper 32-bits to zero */ 7477 putIReg( rA_addr, (mode64) ? 7478 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) : 7479 unop( Iop_64to32, 7480 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) ); 7481 break; 7482 } 7483 7484 case 0xB3: // mtvsrd 7485 { 7486 UChar XT = ifieldRegXT( theInstr ); 7487 UChar rA_addr = ifieldRegA(theInstr); 7488 IRTemp rA = newTemp(ty); 7489 DIP("mtvsrd vsr%d,r%u\n", XT, rA_addr); 7490 /* XS = SX || S 7491 * For SX=0, mfvsrd is treated as a Floating-Point 7492 * instruction in terms of resource availability. 7493 * For SX=1, mfvsrd is treated as a Vector instruction in 7494 * terms of resource availability. 7495 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7496 */ 7497 assign( rA, getIReg(rA_addr) ); 7498 7499 if (mode64) 7500 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) ); 7501 else 7502 putVSReg( XT, binop( Iop_64HLtoV128, 7503 binop( Iop_32HLto64, 7504 mkU32( 0 ), 7505 mkexpr( rA ) ), 7506 mkU64( 0 ) ) ); 7507 break; 7508 } 7509 7510 case 0xD3: // mtvsrwa 7511 { 7512 UChar XT = ifieldRegXT( theInstr ); 7513 UChar rA_addr = ifieldRegA(theInstr); 7514 IRTemp rA = newTemp( Ity_I32 ); 7515 DIP("mtvsrwa vsr%d,r%u\n", XT, rA_addr); 7516 /* XS = SX || S 7517 * For SX=0, mtvsrwa is treated as a Floating-Point 7518 * instruction in terms of resource availability. 7519 * For SX=1, mtvsrwa is treated as a Vector instruction in 7520 * terms of resource availability. 7521 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7522 */ 7523 if (mode64) 7524 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 7525 else 7526 assign( rA, getIReg(rA_addr) ); 7527 7528 putVSReg( XT, binop( Iop_64HLtoV128, 7529 unop( Iop_32Sto64, mkexpr( rA ) ), 7530 mkU64( 0 ) ) ); 7531 break; 7532 } 7533 7534 case 0xF3: // mtvsrwz 7535 { 7536 UChar XT = ifieldRegXT( theInstr ); 7537 UChar rA_addr = ifieldRegA(theInstr); 7538 IRTemp rA = newTemp( Ity_I32 ); 7539 DIP("mtvsrwz vsr%d,r%u\n", rA_addr, XT); 7540 /* XS = SX || S 7541 * For SX=0, mtvsrwz is treated as a Floating-Point 7542 * instruction in terms of resource availability. 7543 * For SX=1, mtvsrwz is treated as a Vector instruction in 7544 * terms of resource availability. 7545 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7546 */ 7547 if (mode64) 7548 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 7549 else 7550 assign( rA, getIReg(rA_addr) ); 7551 7552 putVSReg( XT, binop( Iop_64HLtoV128, 7553 binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ), 7554 mkU64( 0 ) ) ); 7555 break; 7556 } 7557 7558 default: 7559 vex_printf("dis_proc_ctl(ppc)(opc2)\n"); 7560 return False; 7561 } 7562 return True; 7563 } 7564 7565 7566 /* 7567 Cache Management Instructions 7568 */ 7569 static Bool dis_cache_manage ( UInt theInstr, 7570 DisResult* dres, 7571 const VexArchInfo* guest_archinfo ) 7572 { 7573 /* X-Form */ 7574 UChar opc1 = ifieldOPC(theInstr); 7575 UChar b21to25 = ifieldRegDS(theInstr); 7576 UChar rA_addr = ifieldRegA(theInstr); 7577 UChar rB_addr = ifieldRegB(theInstr); 7578 UInt opc2 = ifieldOPClo10(theInstr); 7579 UChar b0 = ifieldBIT0(theInstr); 7580 UInt lineszB = guest_archinfo->ppc_icache_line_szB; 7581 Bool is_dcbzl = False; 7582 7583 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7584 7585 // Check for valid hint values for dcbt and dcbtst as currently described in 7586 // ISA 2.07. If valid, then we simply set b21to25 to zero since we have no 7587 // means of modeling the hint anyway. 7588 if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) { 7589 if (b21to25 == 0x10 || b21to25 < 0x10) 7590 b21to25 = 0; 7591 } 7592 if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11) 7593 b21to25 = 0; 7594 7595 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz 7596 if (b21to25 == 1) { 7597 is_dcbzl = True; 7598 b21to25 = 0; 7599 if (!(guest_archinfo->ppc_dcbzl_szB)) { 7600 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n"); 7601 return False; 7602 } 7603 } 7604 } 7605 7606 if (opc1 != 0x1F || b0 != 0) { 7607 if (0) vex_printf("dis_cache_manage %d %d\n", 7608 opc1, b0); 7609 vex_printf("dis_cache_manage(ppc)(opc1|b0)\n"); 7610 return False; 7611 } 7612 7613 /* stay sane .. */ 7614 vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128); 7615 7616 switch (opc2) { 7617 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380) 7618 //zz vassert(0); /* AWAITING TEST CASE */ 7619 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr); 7620 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n"); 7621 //zz break; 7622 7623 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382) 7624 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr); 7625 /* nop as far as vex is concerned */ 7626 break; 7627 7628 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384) 7629 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr); 7630 /* nop as far as vex is concerned */ 7631 break; 7632 7633 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385) 7634 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr); 7635 /* nop as far as vex is concerned */ 7636 break; 7637 7638 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386) 7639 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr); 7640 /* nop as far as vex is concerned */ 7641 break; 7642 7643 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387) 7644 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264) 7645 /* Clear all bytes in cache block at (rA|0) + rB. */ 7646 IRTemp EA = newTemp(ty); 7647 IRTemp addr = newTemp(ty); 7648 IRExpr* irx_addr; 7649 UInt i; 7650 UInt clearszB; 7651 if (is_dcbzl) { 7652 clearszB = guest_archinfo->ppc_dcbzl_szB; 7653 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr); 7654 } 7655 else { 7656 clearszB = guest_archinfo->ppc_dcbz_szB; 7657 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr); 7658 } 7659 7660 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7661 7662 if (mode64) { 7663 /* Round EA down to the start of the containing block. */ 7664 assign( addr, binop( Iop_And64, 7665 mkexpr(EA), 7666 mkU64( ~((ULong)clearszB-1) )) ); 7667 7668 for (i = 0; i < clearszB / 8; i++) { 7669 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) ); 7670 store( irx_addr, mkU64(0) ); 7671 } 7672 } else { 7673 /* Round EA down to the start of the containing block. */ 7674 assign( addr, binop( Iop_And32, 7675 mkexpr(EA), 7676 mkU32( ~(clearszB-1) )) ); 7677 7678 for (i = 0; i < clearszB / 4; i++) { 7679 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) ); 7680 store( irx_addr, mkU32(0) ); 7681 } 7682 } 7683 break; 7684 } 7685 7686 case 0x3D6: { 7687 // icbi (Instruction Cache Block Invalidate, PPC32 p431) 7688 /* Invalidate all translations containing code from the cache 7689 block at (rA|0) + rB. */ 7690 IRTemp EA = newTemp(ty); 7691 IRTemp addr = newTemp(ty); 7692 DIP("icbi r%u,r%u\n", rA_addr, rB_addr); 7693 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7694 7695 /* Round EA down to the start of the containing block. */ 7696 assign( addr, binop( mkSzOp(ty, Iop_And8), 7697 mkexpr(EA), 7698 mkSzImm(ty, ~(((ULong)lineszB)-1) )) ); 7699 putGST( PPC_GST_CMSTART, mkexpr(addr) ); 7700 putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) ); 7701 7702 /* be paranoid ... */ 7703 stmt( IRStmt_MBE(Imbe_Fence) ); 7704 7705 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr())); 7706 dres->jk_StopHere = Ijk_InvalICache; 7707 dres->whatNext = Dis_StopHere; 7708 break; 7709 } 7710 7711 default: 7712 vex_printf("dis_cache_manage(ppc)(opc2)\n"); 7713 return False; 7714 } 7715 return True; 7716 } 7717 7718 7719 /*------------------------------------------------------------*/ 7720 /*--- Floating Point Helpers ---*/ 7721 /*------------------------------------------------------------*/ 7722 7723 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */ 7724 /* Produces a value in 0 .. 3, which is encoded as per the type 7725 IRRoundingMode. PPCRoundingMode encoding is different to 7726 IRRoundingMode, so need to map it. 7727 */ 7728 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void ) 7729 { 7730 /* 7731 rounding mode | PPC | IR 7732 ------------------------ 7733 to nearest | 00 | 00 7734 to zero | 01 | 11 7735 to +infinity | 10 | 10 7736 to -infinity | 11 | 01 7737 */ 7738 IRTemp rm_PPC32 = newTemp(Ity_I32); 7739 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) ); 7740 7741 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 7742 return binop( Iop_Xor32, 7743 mkexpr(rm_PPC32), 7744 binop( Iop_And32, 7745 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)), 7746 mkU32(2) )); 7747 } 7748 7749 /* The DFP IR rounding modes were chosen such that the existing PPC to IR 7750 * mapping would still work with the extended three bit DFP rounding 7751 * mode designator. 7752 7753 * rounding mode | PPC | IR 7754 * ----------------------------------------------- 7755 * to nearest, ties to even | 000 | 000 7756 * to zero | 001 | 011 7757 * to +infinity | 010 | 010 7758 * to -infinity | 011 | 001 7759 * to nearest, ties away from 0 | 100 | 100 7760 * to nearest, ties toward 0 | 101 | 111 7761 * to away from 0 | 110 | 110 7762 * to prepare for shorter precision | 111 | 101 7763 */ 7764 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void ) 7765 { 7766 IRTemp rm_PPC32 = newTemp( Ity_I32 ); 7767 assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) ); 7768 7769 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 7770 return binop( Iop_Xor32, 7771 mkexpr( rm_PPC32 ), 7772 binop( Iop_And32, 7773 binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ), 7774 mkU32( 2 ) ) ); 7775 } 7776 7777 #define NANmaskSingle 0x7F800000 7778 #define NANmaskDouble 0x7FF00000 7779 7780 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask ) 7781 { 7782 IRTemp exp_zero = newTemp(Ity_I8); 7783 IRTemp frac_mask = newTemp(Ity_I32); 7784 IRTemp frac_not_zero = newTemp(Ity_I8); 7785 7786 /* Check if the result is QNAN or SNAN and not +infinity or -infinity. 7787 * The input value is always 64-bits, for single precision values, the 7788 * lower 32 bits must be zero. 7789 * 7790 * Single Pricision 7791 * [62:54] exponent field is equal to 0xFF for NAN and Infinity. 7792 * [53:32] fraction field is zero for Infinity and non-zero for NAN 7793 * [31:0] unused for single precision representation 7794 * 7795 * Double Pricision 7796 * [62:51] exponent field is equal to 0xFF for NAN and Infinity. 7797 * [50:0] fraction field is zero for Infinity and non-zero for NAN 7798 * 7799 * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise. 7800 */ 7801 assign( frac_mask, unop( Iop_Not32, 7802 binop( Iop_Or32, 7803 mkU32( 0x80000000ULL ), Hi32Mask) ) ); 7804 7805 assign( exp_zero, 7806 unop( Iop_1Sto8, 7807 binop( Iop_CmpEQ32, 7808 binop( Iop_And32, 7809 unop( Iop_64HIto32, 7810 unop( Iop_ReinterpF64asI64, 7811 value ) ), 7812 Hi32Mask ), 7813 Hi32Mask ) ) ); 7814 assign( frac_not_zero, 7815 binop( Iop_Or8, 7816 unop( Iop_1Sto8, 7817 binop( Iop_CmpNE32, 7818 binop( Iop_And32, 7819 unop( Iop_64HIto32, 7820 unop( Iop_ReinterpF64asI64, 7821 value ) ), 7822 mkexpr( frac_mask ) ), 7823 mkU32( 0x0 ) ) ), 7824 unop( Iop_1Sto8, 7825 binop( Iop_CmpNE32, 7826 binop( Iop_And32, 7827 unop( Iop_64to32, 7828 unop( Iop_ReinterpF64asI64, 7829 value ) ), 7830 mkU32( 0xFFFFFFFF ) ), 7831 mkU32( 0x0 ) ) ) ) ); 7832 return unop( Iop_8Sto32, 7833 binop( Iop_And8, 7834 mkexpr( exp_zero ), 7835 mkexpr( frac_not_zero ) ) ); 7836 } 7837 7838 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask ) 7839 { 7840 /* This function will only complement the 64-bit floating point value if it 7841 * is not Nan. NaN is not a signed value. Need to do computations using 7842 * 32-bit operands to ensure it will run in 32-bit mode. 7843 */ 7844 return binop( Iop_32HLto64, 7845 binop( Iop_Or32, 7846 binop( Iop_And32, 7847 nan_mask, 7848 unop( Iop_64HIto32, 7849 unop( Iop_ReinterpF64asI64, 7850 value ) ) ), 7851 binop( Iop_And32, 7852 unop( Iop_Not32, 7853 nan_mask ), 7854 unop( Iop_64HIto32, 7855 unop( Iop_ReinterpF64asI64, 7856 unop( Iop_NegF64, 7857 value ) ) ) ) ), 7858 unop( Iop_64to32, 7859 unop( Iop_ReinterpF64asI64, value ) ) ); 7860 } 7861 7862 /*------------------------------------------------------------*/ 7863 /*--- Floating Point Instruction Translation ---*/ 7864 /*------------------------------------------------------------*/ 7865 7866 /* 7867 Floating Point Load Instructions 7868 */ 7869 static Bool dis_fp_load ( UInt theInstr ) 7870 { 7871 /* X-Form, D-Form */ 7872 UChar opc1 = ifieldOPC(theInstr); 7873 UChar frD_addr = ifieldRegDS(theInstr); 7874 UChar rA_addr = ifieldRegA(theInstr); 7875 UChar rB_addr = ifieldRegB(theInstr); 7876 UInt opc2 = ifieldOPClo10(theInstr); 7877 UChar b0 = ifieldBIT0(theInstr); 7878 UInt uimm16 = ifieldUIMM16(theInstr); 7879 7880 Int simm16 = extend_s_16to32(uimm16); 7881 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7882 IRTemp EA = newTemp(ty); 7883 IRTemp rA = newTemp(ty); 7884 IRTemp rB = newTemp(ty); 7885 IRTemp iHi = newTemp(Ity_I32); 7886 IRTemp iLo = newTemp(Ity_I32); 7887 7888 assign( rA, getIReg(rA_addr) ); 7889 assign( rB, getIReg(rB_addr) ); 7890 7891 /* These are completely straightforward from a rounding and status 7892 bits perspective: no rounding involved and no funny status or CR 7893 bits affected. */ 7894 7895 switch (opc1) { 7896 case 0x30: // lfs (Load Float Single, PPC32 p441) 7897 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7898 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7899 putFReg( frD_addr, 7900 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7901 break; 7902 7903 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442) 7904 if (rA_addr == 0) 7905 return False; 7906 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7907 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7908 putFReg( frD_addr, 7909 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7910 putIReg( rA_addr, mkexpr(EA) ); 7911 break; 7912 7913 case 0x32: // lfd (Load Float Double, PPC32 p437) 7914 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7915 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7916 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7917 break; 7918 7919 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438) 7920 if (rA_addr == 0) 7921 return False; 7922 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7923 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7924 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7925 putIReg( rA_addr, mkexpr(EA) ); 7926 break; 7927 7928 case 0x1F: 7929 if (b0 != 0) { 7930 vex_printf("dis_fp_load(ppc)(instr,b0)\n"); 7931 return False; 7932 } 7933 7934 switch(opc2) { 7935 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444) 7936 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7937 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7938 putFReg( frD_addr, unop( Iop_F32toF64, 7939 load(Ity_F32, mkexpr(EA))) ); 7940 break; 7941 7942 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443) 7943 if (rA_addr == 0) 7944 return False; 7945 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7946 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7947 putFReg( frD_addr, 7948 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) ); 7949 putIReg( rA_addr, mkexpr(EA) ); 7950 break; 7951 7952 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440) 7953 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7954 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7955 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7956 break; 7957 7958 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439) 7959 if (rA_addr == 0) 7960 return False; 7961 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7962 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7963 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) ); 7964 putIReg( rA_addr, mkexpr(EA) ); 7965 break; 7966 7967 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120) 7968 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7969 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7970 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 7971 assign( iHi, binop(Iop_Sub32, 7972 mkU32(0), 7973 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) ); 7974 putFReg( frD_addr, unop(Iop_ReinterpI64asF64, 7975 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) ); 7976 break; 7977 7978 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed 7979 { 7980 IRTemp dw = newTemp( Ity_I64 ); 7981 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7982 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7983 assign( iLo, load(Ity_I32, mkexpr(EA)) ); 7984 assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) ); 7985 putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) ); 7986 break; 7987 } 7988 7989 default: 7990 vex_printf("dis_fp_load(ppc)(opc2)\n"); 7991 return False; 7992 } 7993 break; 7994 7995 default: 7996 vex_printf("dis_fp_load(ppc)(opc1)\n"); 7997 return False; 7998 } 7999 return True; 8000 } 8001 8002 8003 8004 /* 8005 Floating Point Store Instructions 8006 */ 8007 static Bool dis_fp_store ( UInt theInstr ) 8008 { 8009 /* X-Form, D-Form */ 8010 UChar opc1 = ifieldOPC(theInstr); 8011 UChar frS_addr = ifieldRegDS(theInstr); 8012 UChar rA_addr = ifieldRegA(theInstr); 8013 UChar rB_addr = ifieldRegB(theInstr); 8014 UInt opc2 = ifieldOPClo10(theInstr); 8015 UChar b0 = ifieldBIT0(theInstr); 8016 Int uimm16 = ifieldUIMM16(theInstr); 8017 8018 Int simm16 = extend_s_16to32(uimm16); 8019 IRTemp frS = newTemp(Ity_F64); 8020 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8021 IRTemp EA = newTemp(ty); 8022 IRTemp rA = newTemp(ty); 8023 IRTemp rB = newTemp(ty); 8024 8025 assign( frS, getFReg(frS_addr) ); 8026 assign( rA, getIReg(rA_addr) ); 8027 assign( rB, getIReg(rB_addr) ); 8028 8029 /* These are straightforward from a status bits perspective: no 8030 funny status or CR bits affected. For single precision stores, 8031 the values are truncated and denormalised (not rounded) to turn 8032 them into single precision values. */ 8033 8034 switch (opc1) { 8035 8036 case 0x34: // stfs (Store Float Single, PPC32 p518) 8037 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 8038 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 8039 /* Use Iop_TruncF64asF32 to truncate and possible denormalise 8040 the value to be stored in the correct way, without any 8041 rounding. */ 8042 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 8043 break; 8044 8045 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519) 8046 if (rA_addr == 0) 8047 return False; 8048 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 8049 assign( EA, ea_rA_simm(rA_addr, simm16) ); 8050 /* See comment for stfs */ 8051 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 8052 putIReg( rA_addr, mkexpr(EA) ); 8053 break; 8054 8055 case 0x36: // stfd (Store Float Double, PPC32 p513) 8056 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 8057 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 8058 store( mkexpr(EA), mkexpr(frS) ); 8059 break; 8060 8061 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514) 8062 if (rA_addr == 0) 8063 return False; 8064 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 8065 assign( EA, ea_rA_simm(rA_addr, simm16) ); 8066 store( mkexpr(EA), mkexpr(frS) ); 8067 putIReg( rA_addr, mkexpr(EA) ); 8068 break; 8069 8070 case 0x1F: 8071 if (b0 != 0) { 8072 vex_printf("dis_fp_store(ppc)(instr,b0)\n"); 8073 return False; 8074 } 8075 switch(opc2) { 8076 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521) 8077 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 8078 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 8079 /* See note for stfs */ 8080 store( mkexpr(EA), 8081 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 8082 break; 8083 8084 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520) 8085 if (rA_addr == 0) 8086 return False; 8087 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 8088 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 8089 /* See note for stfs */ 8090 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) ); 8091 putIReg( rA_addr, mkexpr(EA) ); 8092 break; 8093 8094 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516) 8095 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 8096 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 8097 store( mkexpr(EA), mkexpr(frS) ); 8098 break; 8099 8100 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515) 8101 if (rA_addr == 0) 8102 return False; 8103 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 8104 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 8105 store( mkexpr(EA), mkexpr(frS) ); 8106 putIReg( rA_addr, mkexpr(EA) ); 8107 break; 8108 8109 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517) 8110 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 8111 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 8112 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 8113 store( mkexpr(EA), 8114 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) ); 8115 break; 8116 8117 default: 8118 vex_printf("dis_fp_store(ppc)(opc2)\n"); 8119 return False; 8120 } 8121 break; 8122 8123 default: 8124 vex_printf("dis_fp_store(ppc)(opc1)\n"); 8125 return False; 8126 } 8127 return True; 8128 } 8129 8130 8131 8132 /* 8133 Floating Point Arith Instructions 8134 */ 8135 static Bool dis_fp_arith (