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-2010 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 73 /* "Special" instructions. 74 75 This instruction decoder can decode four special instructions 76 which mean nothing natively (are no-ops as far as regs/mem are 77 concerned) but have meaning for supporting Valgrind. A special 78 instruction is flagged by a 16-byte preamble: 79 80 32-bit mode: 54001800 54006800 5400E800 54009800 81 (rlwinm 0,0,3,0,0; rlwinm 0,0,13,0,0; 82 rlwinm 0,0,29,0,0; rlwinm 0,0,19,0,0) 83 84 64-bit mode: 78001800 78006800 7800E802 78009802 85 (rotldi 0,0,3; rotldi 0,0,13; 86 rotldi 0,0,61; rotldi 0,0,51) 87 88 Following that, one of the following 3 are allowed 89 (standard interpretation in parentheses): 90 91 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 ) 92 7C421378 (or 2,2,2) %R3 = guest_NRADDR 93 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 94 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2 95 96 Any other bytes following the 16-byte preamble are illegal and 97 constitute a failure in instruction decoding. This all assumes 98 that the preamble will never occur except in specific code 99 fragments designed for Valgrind to catch. 100 */ 101 102 103 /* Translates PPC32/64 code to IR. */ 104 105 /* References 106 107 #define PPC32 108 "PowerPC Microprocessor Family: 109 The Programming Environments Manual for 32-Bit Microprocessors" 110 02/21/2000 111 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2 112 113 #define PPC64 114 "PowerPC Microprocessor Family: 115 Programming Environments Manual for 64-Bit Microprocessors" 116 06/10/2003 117 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797 118 119 #define AV 120 "PowerPC Microprocessor Family: 121 AltiVec(TM) Technology Programming Environments Manual" 122 07/10/2003 123 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D 124 */ 125 126 #include "libvex_basictypes.h" 127 #include "libvex_ir.h" 128 #include "libvex.h" 129 #include "libvex_guest_ppc32.h" 130 #include "libvex_guest_ppc64.h" 131 132 #include "main_util.h" 133 #include "main_globals.h" 134 #include "guest_generic_bb_to_IR.h" 135 #include "guest_ppc_defs.h" 136 137 138 /*------------------------------------------------------------*/ 139 /*--- Globals ---*/ 140 /*------------------------------------------------------------*/ 141 142 /* These are set at the start of the translation of an insn, right 143 down in disInstr_PPC, so that we don't have to pass them around 144 endlessly. They are all constant during the translation of any 145 given insn. */ 146 147 /* We need to know this to do sub-register accesses correctly. */ 148 static Bool host_is_bigendian; 149 150 /* Pointer to the guest code area. */ 151 static UChar* guest_code; 152 153 /* The guest address corresponding to guest_code[0]. */ 154 static Addr64 guest_CIA_bbstart; 155 156 /* The guest address for the instruction currently being 157 translated. */ 158 static Addr64 guest_CIA_curr_instr; 159 160 /* The IRSB* into which we're generating code. */ 161 static IRSB* irsb; 162 163 /* Is our guest binary 32 or 64bit? Set at each call to 164 disInstr_PPC below. */ 165 static Bool mode64 = False; 166 167 // Given a pointer to a function as obtained by "& functionname" in C, 168 // produce a pointer to the actual entry point for the function. For 169 // most platforms it's the identity function. Unfortunately, on 170 // ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and 171 // ppc64-aix5. 172 static void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f ) 173 { 174 if (vbi->host_ppc_calls_use_fndescrs) { 175 /* f is a pointer to a 3-word function descriptor, of which the 176 first word is the entry address. */ 177 /* note, this is correct even with cross-jitting, since this is 178 purely a host issue, not a guest one. */ 179 HWord* fdescr = (HWord*)f; 180 return (void*)(fdescr[0]); 181 } else { 182 /* Simple; "& f" points directly at the code for f. */ 183 return f; 184 } 185 } 186 187 188 /*------------------------------------------------------------*/ 189 /*--- Debugging output ---*/ 190 /*------------------------------------------------------------*/ 191 192 #define DIP(format, args...) \ 193 if (vex_traceflags & VEX_TRACE_FE) \ 194 vex_printf(format, ## args) 195 196 #define DIS(buf, format, args...) \ 197 if (vex_traceflags & VEX_TRACE_FE) \ 198 vex_sprintf(buf, format, ## args) 199 200 201 /*------------------------------------------------------------*/ 202 /*--- Offsets of various parts of the ppc32/64 guest state ---*/ 203 /*------------------------------------------------------------*/ 204 205 #define offsetofPPCGuestState(_x) \ 206 (mode64 ? offsetof(VexGuestPPC64State, _x) : \ 207 offsetof(VexGuestPPC32State, _x)) 208 209 #define OFFB_CIA offsetofPPCGuestState(guest_CIA) 210 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL) 211 #define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO) 212 #define OFFB_LR offsetofPPCGuestState(guest_LR) 213 #define OFFB_CTR offsetofPPCGuestState(guest_CTR) 214 #define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO) 215 #define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV) 216 #define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA) 217 #define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC) 218 #define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND) 219 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE) 220 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR) 221 #define OFFB_EMWARN offsetofPPCGuestState(guest_EMWARN) 222 #define OFFB_TISTART offsetofPPCGuestState(guest_TISTART) 223 #define OFFB_TILEN offsetofPPCGuestState(guest_TILEN) 224 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) 225 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2) 226 227 228 /*------------------------------------------------------------*/ 229 /*--- Extract instruction fields --- */ 230 /*------------------------------------------------------------*/ 231 232 /* Extract field from insn, given idx (zero = lsb) and field length */ 233 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1)) 234 235 /* Extract primary opcode, instr[31:26] */ 236 static UChar ifieldOPC( UInt instr ) { 237 return toUChar( IFIELD( instr, 26, 6 ) ); 238 } 239 240 /* Extract 10-bit secondary opcode, instr[10:1] */ 241 static UInt ifieldOPClo10 ( UInt instr) { 242 return IFIELD( instr, 1, 10 ); 243 } 244 245 /* Extract 9-bit secondary opcode, instr[9:1] */ 246 static UInt ifieldOPClo9 ( UInt instr) { 247 return IFIELD( instr, 1, 9 ); 248 } 249 250 /* Extract 5-bit secondary opcode, instr[5:1] */ 251 static UInt ifieldOPClo5 ( UInt instr) { 252 return IFIELD( instr, 1, 5 ); 253 } 254 255 /* Extract RD (destination register) field, instr[25:21] */ 256 static UChar ifieldRegDS( UInt instr ) { 257 return toUChar( IFIELD( instr, 21, 5 ) ); 258 } 259 260 /* Extract RA (1st source register) field, instr[20:16] */ 261 static UChar ifieldRegA ( UInt instr ) { 262 return toUChar( IFIELD( instr, 16, 5 ) ); 263 } 264 265 /* Extract RB (2nd source register) field, instr[15:11] */ 266 static UChar ifieldRegB ( UInt instr ) { 267 return toUChar( IFIELD( instr, 11, 5 ) ); 268 } 269 270 /* Extract RC (3rd source register) field, instr[10:6] */ 271 static UChar ifieldRegC ( UInt instr ) { 272 return toUChar( IFIELD( instr, 6, 5 ) ); 273 } 274 275 /* Extract 2nd lowest bit, instr[1] */ 276 static UChar ifieldBIT10 ( UInt instr ) { 277 return toUChar( IFIELD( instr, 10, 1 ) ); 278 } 279 280 /* Extract 2nd lowest bit, instr[1] */ 281 static UChar ifieldBIT1 ( UInt instr ) { 282 return toUChar( IFIELD( instr, 1, 1 ) ); 283 } 284 285 /* Extract lowest bit, instr[0] */ 286 static UChar ifieldBIT0 ( UInt instr ) { 287 return toUChar( instr & 0x1 ); 288 } 289 290 /* Extract unsigned bottom half, instr[15:0] */ 291 static UInt ifieldUIMM16 ( UInt instr ) { 292 return instr & 0xFFFF; 293 } 294 295 /* Extract unsigned bottom 26 bits, instr[25:0] */ 296 static UInt ifieldUIMM26 ( UInt instr ) { 297 return instr & 0x3FFFFFF; 298 } 299 300 301 /*------------------------------------------------------------*/ 302 /*--- Guest-state identifiers ---*/ 303 /*------------------------------------------------------------*/ 304 305 typedef enum { 306 PPC_GST_CIA, // Current Instruction Address 307 PPC_GST_LR, // Link Register 308 PPC_GST_CTR, // Count Register 309 PPC_GST_XER, // Overflow, carry flags, byte count 310 PPC_GST_CR, // Condition Register 311 PPC_GST_FPSCR, // Floating Point Status/Control Register 312 PPC_GST_VRSAVE, // Vector Save/Restore Register 313 PPC_GST_VSCR, // Vector Status and Control Register 314 PPC_GST_EMWARN, // Emulation warnings 315 PPC_GST_TISTART,// For icbi: start of area to invalidate 316 PPC_GST_TILEN, // For icbi: length of area to invalidate 317 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn 318 PPC_GST_SPRG3_RO, // SPRG3 319 PPC_GST_MAX 320 } PPC_GST; 321 322 #define MASK_FPSCR_RN 0x3 323 #define MASK_FPSCR_FPRF 0x1F000 324 #define MASK_VSCR_VALID 0x00010001 325 326 327 /*------------------------------------------------------------*/ 328 /*--- FP Helpers ---*/ 329 /*------------------------------------------------------------*/ 330 331 /* Produce the 32-bit pattern corresponding to the supplied 332 float. */ 333 static UInt float_to_bits ( Float f ) 334 { 335 union { UInt i; Float f; } u; 336 vassert(4 == sizeof(UInt)); 337 vassert(4 == sizeof(Float)); 338 vassert(4 == sizeof(u)); 339 u.f = f; 340 return u.i; 341 } 342 343 344 /*------------------------------------------------------------*/ 345 /*--- Misc Helpers ---*/ 346 /*------------------------------------------------------------*/ 347 348 /* Generate mask with 1's from 'begin' through 'end', 349 wrapping if begin > end. 350 begin->end works from right to left, 0=lsb 351 */ 352 static UInt MASK32( UInt begin, UInt end ) 353 { 354 UInt m1, m2, mask; 355 vassert(begin < 32); 356 vassert(end < 32); 357 m1 = ((UInt)(-1)) << begin; 358 m2 = ((UInt)(-1)) << end << 1; 359 mask = m1 ^ m2; 360 if (begin > end) mask = ~mask; // wrap mask 361 return mask; 362 } 363 364 /* ditto for 64bit mask */ 365 static ULong MASK64( UInt begin, UInt end ) 366 { 367 ULong m1, m2, mask; 368 vassert(begin < 64); 369 vassert(end < 64); 370 m1 = ((ULong)(-1)) << begin; 371 m2 = ((ULong)(-1)) << end << 1; 372 mask = m1 ^ m2; 373 if (begin > end) mask = ~mask; // wrap mask 374 return mask; 375 } 376 377 static Addr64 nextInsnAddr( void ) 378 { 379 return guest_CIA_curr_instr + 4; 380 } 381 382 383 /*------------------------------------------------------------*/ 384 /*--- Helper bits and pieces for deconstructing the ---*/ 385 /*--- ppc32/64 insn stream. ---*/ 386 /*------------------------------------------------------------*/ 387 388 /* Add a statement to the list held by "irsb". */ 389 static void stmt ( IRStmt* st ) 390 { 391 addStmtToIRSB( irsb, st ); 392 } 393 394 /* Generate a new temporary of the given type. */ 395 static IRTemp newTemp ( IRType ty ) 396 { 397 vassert(isPlausibleIRType(ty)); 398 return newIRTemp( irsb->tyenv, ty ); 399 } 400 401 /* Various simple conversions */ 402 403 static UChar extend_s_5to8 ( UChar x ) 404 { 405 return toUChar((((Int)x) << 27) >> 27); 406 } 407 408 static UInt extend_s_8to32( UChar x ) 409 { 410 return (UInt)((((Int)x) << 24) >> 24); 411 } 412 413 static UInt extend_s_16to32 ( UInt x ) 414 { 415 return (UInt)((((Int)x) << 16) >> 16); 416 } 417 418 static ULong extend_s_16to64 ( UInt x ) 419 { 420 return (ULong)((((Long)x) << 48) >> 48); 421 } 422 423 static ULong extend_s_26to64 ( UInt x ) 424 { 425 return (ULong)((((Long)x) << 38) >> 38); 426 } 427 428 static ULong extend_s_32to64 ( UInt x ) 429 { 430 return (ULong)((((Long)x) << 32) >> 32); 431 } 432 433 /* Do a big-endian load of a 32-bit word, regardless of the endianness 434 of the underlying host. */ 435 static UInt getUIntBigendianly ( UChar* p ) 436 { 437 UInt w = 0; 438 w = (w << 8) | p[0]; 439 w = (w << 8) | p[1]; 440 w = (w << 8) | p[2]; 441 w = (w << 8) | p[3]; 442 return w; 443 } 444 445 446 /*------------------------------------------------------------*/ 447 /*--- Helpers for constructing IR. ---*/ 448 /*------------------------------------------------------------*/ 449 450 static void assign ( IRTemp dst, IRExpr* e ) 451 { 452 stmt( IRStmt_WrTmp(dst, e) ); 453 } 454 455 /* This generates a normal (non store-conditional) store. */ 456 static void storeBE ( IRExpr* addr, IRExpr* data ) 457 { 458 IRType tyA = typeOfIRExpr(irsb->tyenv, addr); 459 vassert(tyA == Ity_I32 || tyA == Ity_I64); 460 stmt( IRStmt_Store(Iend_BE, addr, data) ); 461 } 462 463 static IRExpr* unop ( IROp op, IRExpr* a ) 464 { 465 return IRExpr_Unop(op, a); 466 } 467 468 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 469 { 470 return IRExpr_Binop(op, a1, a2); 471 } 472 473 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 474 { 475 return IRExpr_Triop(op, a1, a2, a3); 476 } 477 478 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2, 479 IRExpr* a3, IRExpr* a4 ) 480 { 481 return IRExpr_Qop(op, a1, a2, a3, a4); 482 } 483 484 static IRExpr* mkexpr ( IRTemp tmp ) 485 { 486 return IRExpr_RdTmp(tmp); 487 } 488 489 static IRExpr* mkU8 ( UChar i ) 490 { 491 return IRExpr_Const(IRConst_U8(i)); 492 } 493 494 static IRExpr* mkU16 ( UInt i ) 495 { 496 return IRExpr_Const(IRConst_U16(i)); 497 } 498 499 static IRExpr* mkU32 ( UInt i ) 500 { 501 return IRExpr_Const(IRConst_U32(i)); 502 } 503 504 static IRExpr* mkU64 ( ULong i ) 505 { 506 return IRExpr_Const(IRConst_U64(i)); 507 } 508 509 /* This generates a normal (non load-linked) load. */ 510 static IRExpr* loadBE ( IRType ty, IRExpr* addr ) 511 { 512 return IRExpr_Load(Iend_BE, ty, addr); 513 } 514 515 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 ) 516 { 517 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 518 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 519 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1), 520 unop(Iop_1Uto32, arg2))); 521 } 522 523 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 ) 524 { 525 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 526 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 527 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1), 528 unop(Iop_1Uto32, arg2))); 529 } 530 531 /* expand V128_8Ux16 to 2x V128_16Ux8's */ 532 static void expand8Ux16( IRExpr* vIn, 533 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 534 { 535 IRTemp ones8x16 = newTemp(Ity_V128); 536 537 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 538 vassert(vEvn && *vEvn == IRTemp_INVALID); 539 vassert(vOdd && *vOdd == IRTemp_INVALID); 540 *vEvn = newTemp(Ity_V128); 541 *vOdd = newTemp(Ity_V128); 542 543 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 544 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) ); 545 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 546 binop(Iop_ShrV128, vIn, mkU8(8))) ); 547 } 548 549 /* expand V128_8Sx16 to 2x V128_16Sx8's */ 550 static void expand8Sx16( IRExpr* vIn, 551 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 552 { 553 IRTemp ones8x16 = newTemp(Ity_V128); 554 555 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 556 vassert(vEvn && *vEvn == IRTemp_INVALID); 557 vassert(vOdd && *vOdd == IRTemp_INVALID); 558 *vEvn = newTemp(Ity_V128); 559 *vOdd = newTemp(Ity_V128); 560 561 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 562 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) ); 563 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 564 binop(Iop_ShrV128, vIn, mkU8(8))) ); 565 } 566 567 /* expand V128_16Uto8 to 2x V128_32Ux4's */ 568 static void expand16Ux8( IRExpr* vIn, 569 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 570 { 571 IRTemp ones16x8 = newTemp(Ity_V128); 572 573 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 574 vassert(vEvn && *vEvn == IRTemp_INVALID); 575 vassert(vOdd && *vOdd == IRTemp_INVALID); 576 *vEvn = newTemp(Ity_V128); 577 *vOdd = newTemp(Ity_V128); 578 579 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 580 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) ); 581 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 582 binop(Iop_ShrV128, vIn, mkU8(16))) ); 583 } 584 585 /* expand V128_16Sto8 to 2x V128_32Sx4's */ 586 static void expand16Sx8( IRExpr* vIn, 587 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 588 { 589 IRTemp ones16x8 = newTemp(Ity_V128); 590 591 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 592 vassert(vEvn && *vEvn == IRTemp_INVALID); 593 vassert(vOdd && *vOdd == IRTemp_INVALID); 594 *vEvn = newTemp(Ity_V128); 595 *vOdd = newTemp(Ity_V128); 596 597 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 598 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) ); 599 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 600 binop(Iop_ShrV128, vIn, mkU8(16))) ); 601 } 602 603 /* break V128 to 4xI32's, then sign-extend to I64's */ 604 static void breakV128to4x64S( IRExpr* t128, 605 /*OUTs*/ 606 IRTemp* t3, IRTemp* t2, 607 IRTemp* t1, IRTemp* t0 ) 608 { 609 IRTemp hi64 = newTemp(Ity_I64); 610 IRTemp lo64 = newTemp(Ity_I64); 611 612 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 613 vassert(t0 && *t0 == IRTemp_INVALID); 614 vassert(t1 && *t1 == IRTemp_INVALID); 615 vassert(t2 && *t2 == IRTemp_INVALID); 616 vassert(t3 && *t3 == IRTemp_INVALID); 617 *t0 = newTemp(Ity_I64); 618 *t1 = newTemp(Ity_I64); 619 *t2 = newTemp(Ity_I64); 620 *t3 = newTemp(Ity_I64); 621 622 assign( hi64, unop(Iop_V128HIto64, t128) ); 623 assign( lo64, unop(Iop_V128to64, t128) ); 624 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 625 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) ); 626 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 627 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) ); 628 } 629 630 /* break V128 to 4xI32's, then zero-extend to I64's */ 631 static void breakV128to4x64U ( IRExpr* t128, 632 /*OUTs*/ 633 IRTemp* t3, IRTemp* t2, 634 IRTemp* t1, IRTemp* t0 ) 635 { 636 IRTemp hi64 = newTemp(Ity_I64); 637 IRTemp lo64 = newTemp(Ity_I64); 638 639 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 640 vassert(t0 && *t0 == IRTemp_INVALID); 641 vassert(t1 && *t1 == IRTemp_INVALID); 642 vassert(t2 && *t2 == IRTemp_INVALID); 643 vassert(t3 && *t3 == IRTemp_INVALID); 644 *t0 = newTemp(Ity_I64); 645 *t1 = newTemp(Ity_I64); 646 *t2 = newTemp(Ity_I64); 647 *t3 = newTemp(Ity_I64); 648 649 assign( hi64, unop(Iop_V128HIto64, t128) ); 650 assign( lo64, unop(Iop_V128to64, t128) ); 651 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 652 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) ); 653 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 654 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) ); 655 } 656 657 /* Signed saturating narrow 64S to 32 */ 658 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 ) 659 { 660 IRTemp hi32 = newTemp(Ity_I32); 661 IRTemp lo32 = newTemp(Ity_I32); 662 663 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 664 665 assign( hi32, unop(Iop_64HIto32, t64)); 666 assign( lo32, unop(Iop_64to32, t64)); 667 668 return IRExpr_Mux0X( 669 /* if (hi32 == (lo32 >>s 31)) */ 670 unop(Iop_1Uto8, 671 binop(Iop_CmpEQ32, mkexpr(hi32), 672 binop( Iop_Sar32, mkexpr(lo32), mkU8(31)))), 673 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */ 674 binop(Iop_Add32, mkU32(0x7FFFFFFF), 675 binop(Iop_Shr32, mkexpr(hi32), mkU8(31))), 676 /* then: within signed-32 range: lo half good enough */ 677 mkexpr(lo32) ); 678 } 679 680 /* Unsigned saturating narrow 64S to 32 */ 681 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 ) 682 { 683 IRTemp hi32 = newTemp(Ity_I32); 684 IRTemp lo32 = newTemp(Ity_I32); 685 686 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 687 688 assign( hi32, unop(Iop_64HIto32, t64)); 689 assign( lo32, unop(Iop_64to32, t64)); 690 691 return IRExpr_Mux0X( 692 /* if (top 32 bits of t64 are 0) */ 693 unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0))), 694 /* else: positive saturate -> 0xFFFFFFFF */ 695 mkU32(0xFFFFFFFF), 696 /* then: within unsigned-32 range: lo half good enough */ 697 mkexpr(lo32) ); 698 } 699 700 /* Signed saturate narrow 64->32, combining to V128 */ 701 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2, 702 IRExpr* t1, IRExpr* t0 ) 703 { 704 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 705 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 706 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 707 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 708 return binop(Iop_64HLtoV128, 709 binop(Iop_32HLto64, 710 mkQNarrow64Sto32( t3 ), 711 mkQNarrow64Sto32( t2 )), 712 binop(Iop_32HLto64, 713 mkQNarrow64Sto32( t1 ), 714 mkQNarrow64Sto32( t0 ))); 715 } 716 717 /* Unsigned saturate narrow 64->32, combining to V128 */ 718 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2, 719 IRExpr* t1, IRExpr* t0 ) 720 { 721 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 722 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 723 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 724 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 725 return binop(Iop_64HLtoV128, 726 binop(Iop_32HLto64, 727 mkQNarrow64Uto32( t3 ), 728 mkQNarrow64Uto32( t2 )), 729 binop(Iop_32HLto64, 730 mkQNarrow64Uto32( t1 ), 731 mkQNarrow64Uto32( t0 ))); 732 } 733 734 /* Simulate irops Iop_MullOdd*, since we don't have them */ 735 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \ 736 binop(Iop_MullEven8Ux16, \ 737 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 738 binop(Iop_ShrV128, expr_vB, mkU8(8))) 739 740 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \ 741 binop(Iop_MullEven8Sx16, \ 742 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 743 binop(Iop_ShrV128, expr_vB, mkU8(8))) 744 745 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \ 746 binop(Iop_MullEven16Ux8, \ 747 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 748 binop(Iop_ShrV128, expr_vB, mkU8(16))) 749 750 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \ 751 binop(Iop_MullEven16Sx8, \ 752 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 753 binop(Iop_ShrV128, expr_vB, mkU8(16))) 754 755 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src ) 756 { 757 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 758 return unop(Iop_32Sto64, unop(Iop_64to32, src)); 759 } 760 761 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src ) 762 { 763 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 764 return unop(Iop_32Uto64, unop(Iop_64to32, src)); 765 } 766 767 static IROp mkSzOp ( IRType ty, IROp op8 ) 768 { 769 Int adj; 770 vassert(ty == Ity_I8 || ty == Ity_I16 || 771 ty == Ity_I32 || ty == Ity_I64); 772 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || 773 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 || 774 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 || 775 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || 776 op8 == Iop_Not8 ); 777 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3)); 778 return adj + op8; 779 } 780 781 /* Make sure we get valid 32 and 64bit addresses */ 782 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 783 { 784 vassert(ty == Ity_I32 || ty == Ity_I64); 785 return ( ty == Ity_I64 ? 786 (Addr64)addr : 787 (Addr64)extend_s_32to64( toUInt(addr) ) ); 788 } 789 790 /* sz, ULong -> IRExpr */ 791 static IRExpr* mkSzImm ( IRType ty, ULong imm64 ) 792 { 793 vassert(ty == Ity_I32 || ty == Ity_I64); 794 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64); 795 } 796 797 /* sz, ULong -> IRConst */ 798 static IRConst* mkSzConst ( IRType ty, ULong imm64 ) 799 { 800 vassert(ty == Ity_I32 || ty == Ity_I64); 801 return ( ty == Ity_I64 ? 802 IRConst_U64(imm64) : 803 IRConst_U32((UInt)imm64) ); 804 } 805 806 /* Sign extend imm16 -> IRExpr* */ 807 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 ) 808 { 809 vassert(ty == Ity_I32 || ty == Ity_I64); 810 return ( ty == Ity_I64 ? 811 mkU64(extend_s_16to64(imm16)) : 812 mkU32(extend_s_16to32(imm16)) ); 813 } 814 815 /* Sign extend imm32 -> IRExpr* */ 816 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 ) 817 { 818 vassert(ty == Ity_I32 || ty == Ity_I64); 819 return ( ty == Ity_I64 ? 820 mkU64(extend_s_32to64(imm32)) : 821 mkU32(imm32) ); 822 } 823 824 /* IR narrows I32/I64 -> I8/I16/I32 */ 825 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src ) 826 { 827 vassert(ty == Ity_I32 || ty == Ity_I64); 828 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 829 } 830 831 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src ) 832 { 833 vassert(ty == Ity_I32 || ty == Ity_I64); 834 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src); 835 } 836 837 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src ) 838 { 839 vassert(ty == Ity_I32 || ty == Ity_I64); 840 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 841 } 842 843 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */ 844 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined ) 845 { 846 IROp op; 847 vassert(ty == Ity_I32 || ty == Ity_I64); 848 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64; 849 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64; 850 return unop(op, src); 851 } 852 853 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined ) 854 { 855 IROp op; 856 vassert(ty == Ity_I32 || ty == Ity_I64); 857 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64; 858 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64; 859 return unop(op, src); 860 } 861 862 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined ) 863 { 864 vassert(ty == Ity_I32 || ty == Ity_I64); 865 if (ty == Ity_I32) 866 return src; 867 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 868 } 869 870 871 static Int integerGuestRegOffset ( UInt archreg ) 872 { 873 vassert(archreg < 32); 874 875 // jrs: probably not necessary; only matters if we reference sub-parts 876 // of the ppc registers, but that isn't the case 877 // later: this might affect Altivec though? 878 vassert(host_is_bigendian); 879 880 switch (archreg) { 881 case 0: return offsetofPPCGuestState(guest_GPR0); 882 case 1: return offsetofPPCGuestState(guest_GPR1); 883 case 2: return offsetofPPCGuestState(guest_GPR2); 884 case 3: return offsetofPPCGuestState(guest_GPR3); 885 case 4: return offsetofPPCGuestState(guest_GPR4); 886 case 5: return offsetofPPCGuestState(guest_GPR5); 887 case 6: return offsetofPPCGuestState(guest_GPR6); 888 case 7: return offsetofPPCGuestState(guest_GPR7); 889 case 8: return offsetofPPCGuestState(guest_GPR8); 890 case 9: return offsetofPPCGuestState(guest_GPR9); 891 case 10: return offsetofPPCGuestState(guest_GPR10); 892 case 11: return offsetofPPCGuestState(guest_GPR11); 893 case 12: return offsetofPPCGuestState(guest_GPR12); 894 case 13: return offsetofPPCGuestState(guest_GPR13); 895 case 14: return offsetofPPCGuestState(guest_GPR14); 896 case 15: return offsetofPPCGuestState(guest_GPR15); 897 case 16: return offsetofPPCGuestState(guest_GPR16); 898 case 17: return offsetofPPCGuestState(guest_GPR17); 899 case 18: return offsetofPPCGuestState(guest_GPR18); 900 case 19: return offsetofPPCGuestState(guest_GPR19); 901 case 20: return offsetofPPCGuestState(guest_GPR20); 902 case 21: return offsetofPPCGuestState(guest_GPR21); 903 case 22: return offsetofPPCGuestState(guest_GPR22); 904 case 23: return offsetofPPCGuestState(guest_GPR23); 905 case 24: return offsetofPPCGuestState(guest_GPR24); 906 case 25: return offsetofPPCGuestState(guest_GPR25); 907 case 26: return offsetofPPCGuestState(guest_GPR26); 908 case 27: return offsetofPPCGuestState(guest_GPR27); 909 case 28: return offsetofPPCGuestState(guest_GPR28); 910 case 29: return offsetofPPCGuestState(guest_GPR29); 911 case 30: return offsetofPPCGuestState(guest_GPR30); 912 case 31: return offsetofPPCGuestState(guest_GPR31); 913 default: break; 914 } 915 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/ 916 } 917 918 static IRExpr* getIReg ( UInt archreg ) 919 { 920 IRType ty = mode64 ? Ity_I64 : Ity_I32; 921 vassert(archreg < 32); 922 return IRExpr_Get( integerGuestRegOffset(archreg), ty ); 923 } 924 925 /* Ditto, but write to a reg instead. */ 926 static void putIReg ( UInt archreg, IRExpr* e ) 927 { 928 IRType ty = mode64 ? Ity_I64 : Ity_I32; 929 vassert(archreg < 32); 930 vassert(typeOfIRExpr(irsb->tyenv, e) == ty ); 931 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) ); 932 } 933 934 935 static Int floatGuestRegOffset ( UInt archreg ) 936 { 937 vassert(archreg < 32); 938 939 switch (archreg) { 940 case 0: return offsetofPPCGuestState(guest_FPR0); 941 case 1: return offsetofPPCGuestState(guest_FPR1); 942 case 2: return offsetofPPCGuestState(guest_FPR2); 943 case 3: return offsetofPPCGuestState(guest_FPR3); 944 case 4: return offsetofPPCGuestState(guest_FPR4); 945 case 5: return offsetofPPCGuestState(guest_FPR5); 946 case 6: return offsetofPPCGuestState(guest_FPR6); 947 case 7: return offsetofPPCGuestState(guest_FPR7); 948 case 8: return offsetofPPCGuestState(guest_FPR8); 949 case 9: return offsetofPPCGuestState(guest_FPR9); 950 case 10: return offsetofPPCGuestState(guest_FPR10); 951 case 11: return offsetofPPCGuestState(guest_FPR11); 952 case 12: return offsetofPPCGuestState(guest_FPR12); 953 case 13: return offsetofPPCGuestState(guest_FPR13); 954 case 14: return offsetofPPCGuestState(guest_FPR14); 955 case 15: return offsetofPPCGuestState(guest_FPR15); 956 case 16: return offsetofPPCGuestState(guest_FPR16); 957 case 17: return offsetofPPCGuestState(guest_FPR17); 958 case 18: return offsetofPPCGuestState(guest_FPR18); 959 case 19: return offsetofPPCGuestState(guest_FPR19); 960 case 20: return offsetofPPCGuestState(guest_FPR20); 961 case 21: return offsetofPPCGuestState(guest_FPR21); 962 case 22: return offsetofPPCGuestState(guest_FPR22); 963 case 23: return offsetofPPCGuestState(guest_FPR23); 964 case 24: return offsetofPPCGuestState(guest_FPR24); 965 case 25: return offsetofPPCGuestState(guest_FPR25); 966 case 26: return offsetofPPCGuestState(guest_FPR26); 967 case 27: return offsetofPPCGuestState(guest_FPR27); 968 case 28: return offsetofPPCGuestState(guest_FPR28); 969 case 29: return offsetofPPCGuestState(guest_FPR29); 970 case 30: return offsetofPPCGuestState(guest_FPR30); 971 case 31: return offsetofPPCGuestState(guest_FPR31); 972 default: break; 973 } 974 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/ 975 } 976 977 static IRExpr* getFReg ( UInt archreg ) 978 { 979 vassert(archreg < 32); 980 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 ); 981 } 982 983 /* Ditto, but write to a reg instead. */ 984 static void putFReg ( UInt archreg, IRExpr* e ) 985 { 986 vassert(archreg < 32); 987 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 988 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) ); 989 } 990 991 992 static Int vectorGuestRegOffset ( UInt archreg ) 993 { 994 vassert(archreg < 32); 995 996 switch (archreg) { 997 case 0: return offsetofPPCGuestState(guest_VR0); 998 case 1: return offsetofPPCGuestState(guest_VR1); 999 case 2: return offsetofPPCGuestState(guest_VR2); 1000 case 3: return offsetofPPCGuestState(guest_VR3); 1001 case 4: return offsetofPPCGuestState(guest_VR4); 1002 case 5: return offsetofPPCGuestState(guest_VR5); 1003 case 6: return offsetofPPCGuestState(guest_VR6); 1004 case 7: return offsetofPPCGuestState(guest_VR7); 1005 case 8: return offsetofPPCGuestState(guest_VR8); 1006 case 9: return offsetofPPCGuestState(guest_VR9); 1007 case 10: return offsetofPPCGuestState(guest_VR10); 1008 case 11: return offsetofPPCGuestState(guest_VR11); 1009 case 12: return offsetofPPCGuestState(guest_VR12); 1010 case 13: return offsetofPPCGuestState(guest_VR13); 1011 case 14: return offsetofPPCGuestState(guest_VR14); 1012 case 15: return offsetofPPCGuestState(guest_VR15); 1013 case 16: return offsetofPPCGuestState(guest_VR16); 1014 case 17: return offsetofPPCGuestState(guest_VR17); 1015 case 18: return offsetofPPCGuestState(guest_VR18); 1016 case 19: return offsetofPPCGuestState(guest_VR19); 1017 case 20: return offsetofPPCGuestState(guest_VR20); 1018 case 21: return offsetofPPCGuestState(guest_VR21); 1019 case 22: return offsetofPPCGuestState(guest_VR22); 1020 case 23: return offsetofPPCGuestState(guest_VR23); 1021 case 24: return offsetofPPCGuestState(guest_VR24); 1022 case 25: return offsetofPPCGuestState(guest_VR25); 1023 case 26: return offsetofPPCGuestState(guest_VR26); 1024 case 27: return offsetofPPCGuestState(guest_VR27); 1025 case 28: return offsetofPPCGuestState(guest_VR28); 1026 case 29: return offsetofPPCGuestState(guest_VR29); 1027 case 30: return offsetofPPCGuestState(guest_VR30); 1028 case 31: return offsetofPPCGuestState(guest_VR31); 1029 default: break; 1030 } 1031 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/ 1032 } 1033 1034 static IRExpr* getVReg ( UInt archreg ) 1035 { 1036 vassert(archreg < 32); 1037 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 ); 1038 } 1039 1040 /* Ditto, but write to a reg instead. */ 1041 static void putVReg ( UInt archreg, IRExpr* e ) 1042 { 1043 vassert(archreg < 32); 1044 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1045 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1046 } 1047 1048 static Int guestCR321offset ( UInt cr ) 1049 { 1050 switch (cr) { 1051 case 0: return offsetofPPCGuestState(guest_CR0_321 ); 1052 case 1: return offsetofPPCGuestState(guest_CR1_321 ); 1053 case 2: return offsetofPPCGuestState(guest_CR2_321 ); 1054 case 3: return offsetofPPCGuestState(guest_CR3_321 ); 1055 case 4: return offsetofPPCGuestState(guest_CR4_321 ); 1056 case 5: return offsetofPPCGuestState(guest_CR5_321 ); 1057 case 6: return offsetofPPCGuestState(guest_CR6_321 ); 1058 case 7: return offsetofPPCGuestState(guest_CR7_321 ); 1059 default: vpanic("guestCR321offset(ppc)"); 1060 } 1061 } 1062 1063 static Int guestCR0offset ( UInt cr ) 1064 { 1065 switch (cr) { 1066 case 0: return offsetofPPCGuestState(guest_CR0_0 ); 1067 case 1: return offsetofPPCGuestState(guest_CR1_0 ); 1068 case 2: return offsetofPPCGuestState(guest_CR2_0 ); 1069 case 3: return offsetofPPCGuestState(guest_CR3_0 ); 1070 case 4: return offsetofPPCGuestState(guest_CR4_0 ); 1071 case 5: return offsetofPPCGuestState(guest_CR5_0 ); 1072 case 6: return offsetofPPCGuestState(guest_CR6_0 ); 1073 case 7: return offsetofPPCGuestState(guest_CR7_0 ); 1074 default: vpanic("guestCR3offset(ppc)"); 1075 } 1076 } 1077 1078 // ROTL(src32/64, rot_amt5/6) 1079 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src, 1080 IRExpr* rot_amt ) 1081 { 1082 IRExpr *mask, *rot; 1083 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8); 1084 1085 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) { 1086 // rot = (src << rot_amt) | (src >> (64-rot_amt)) 1087 mask = binop(Iop_And8, rot_amt, mkU8(63)); 1088 rot = binop(Iop_Or64, 1089 binop(Iop_Shl64, src, mask), 1090 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask))); 1091 } else { 1092 // rot = (src << rot_amt) | (src >> (32-rot_amt)) 1093 mask = binop(Iop_And8, rot_amt, mkU8(31)); 1094 rot = binop(Iop_Or32, 1095 binop(Iop_Shl32, src, mask), 1096 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask))); 1097 } 1098 /* Note: the MuxOX is not merely an optimisation; it's needed 1099 because otherwise the Shr is a shift by the word size when 1100 mask denotes zero. For rotates by immediates, a lot of 1101 this junk gets folded out. */ 1102 return IRExpr_Mux0X( mask, /* zero rotate */ src, 1103 /* non-zero rotate */ rot ); 1104 } 1105 1106 /* Standard effective address calc: (rA + rB) */ 1107 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB ) 1108 { 1109 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1110 vassert(rA < 32); 1111 vassert(rB < 32); 1112 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB)); 1113 } 1114 1115 /* Standard effective address calc: (rA + simm) */ 1116 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 ) 1117 { 1118 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1119 vassert(rA < 32); 1120 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), 1121 mkSzExtendS16(ty, simm16)); 1122 } 1123 1124 /* Standard effective address calc: (rA|0) */ 1125 static IRExpr* ea_rAor0 ( UInt rA ) 1126 { 1127 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1128 vassert(rA < 32); 1129 if (rA == 0) { 1130 return mkSzImm(ty, 0); 1131 } else { 1132 return getIReg(rA); 1133 } 1134 } 1135 1136 /* Standard effective address calc: (rA|0) + rB */ 1137 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB ) 1138 { 1139 vassert(rA < 32); 1140 vassert(rB < 32); 1141 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB ); 1142 } 1143 1144 /* Standard effective address calc: (rA|0) + simm16 */ 1145 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 ) 1146 { 1147 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1148 vassert(rA < 32); 1149 if (rA == 0) { 1150 return mkSzExtendS16(ty, simm16); 1151 } else { 1152 return ea_rA_simm( rA, simm16 ); 1153 } 1154 } 1155 1156 1157 /* Align effective address */ 1158 static IRExpr* addr_align( IRExpr* addr, UChar align ) 1159 { 1160 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1161 Long mask; 1162 switch (align) { 1163 case 1: return addr; // byte aligned 1164 case 2: mask = ((Long)-1) << 1; break; // half-word aligned 1165 case 4: mask = ((Long)-1) << 2; break; // word aligned 1166 case 16: mask = ((Long)-1) << 4; break; // quad-word aligned 1167 default: 1168 vex_printf("addr_align: align = %u\n", align); 1169 vpanic("addr_align(ppc)"); 1170 } 1171 1172 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty); 1173 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) ); 1174 } 1175 1176 1177 /* Exit the trace if ADDR (intended to be a guest memory address) is 1178 not ALIGN-aligned, generating a request for a SIGBUS followed by a 1179 restart of the current insn. */ 1180 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align ) 1181 { 1182 vassert(align == 4 || align == 8); 1183 if (mode64) { 1184 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64); 1185 stmt( 1186 IRStmt_Exit( 1187 binop(Iop_CmpNE64, 1188 binop(Iop_And64, mkexpr(addr), mkU64(align-1)), 1189 mkU64(0)), 1190 Ijk_SigBUS, 1191 IRConst_U64( guest_CIA_curr_instr ) 1192 ) 1193 ); 1194 } else { 1195 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32); 1196 stmt( 1197 IRStmt_Exit( 1198 binop(Iop_CmpNE32, 1199 binop(Iop_And32, mkexpr(addr), mkU32(align-1)), 1200 mkU32(0)), 1201 Ijk_SigBUS, 1202 IRConst_U32( guest_CIA_curr_instr ) 1203 ) 1204 ); 1205 } 1206 } 1207 1208 1209 /* Generate AbiHints which mark points at which the ELF or PowerOpen 1210 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some 1211 N) becomes undefined. That is at function calls and returns. ELF 1212 ppc32 doesn't have this "feature" (how fortunate for it). nia is 1213 the address of the next instruction to be executed. 1214 */ 1215 static void make_redzone_AbiHint ( VexAbiInfo* vbi, 1216 IRTemp nia, HChar* who ) 1217 { 1218 Int szB = vbi->guest_stack_redzone_size; 1219 if (0) vex_printf("AbiHint: %s\n", who); 1220 vassert(szB >= 0); 1221 if (szB > 0) { 1222 if (mode64) { 1223 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64); 1224 stmt( IRStmt_AbiHint( 1225 binop(Iop_Sub64, getIReg(1), mkU64(szB)), 1226 szB, 1227 mkexpr(nia) 1228 )); 1229 } else { 1230 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32); 1231 stmt( IRStmt_AbiHint( 1232 binop(Iop_Sub32, getIReg(1), mkU32(szB)), 1233 szB, 1234 mkexpr(nia) 1235 )); 1236 } 1237 } 1238 } 1239 1240 1241 /*------------------------------------------------------------*/ 1242 /*--- Helpers for condition codes. ---*/ 1243 /*------------------------------------------------------------*/ 1244 1245 /* Condition register layout. 1246 1247 In the hardware, CR is laid out like this. The leftmost end is the 1248 most significant bit in the register; however the IBM documentation 1249 numbers the bits backwards for some reason. 1250 1251 CR0 CR1 .......... CR6 CR7 1252 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 1253 31 28 3 0 (normal bit numbering) 1254 1255 Each CR field is 4 bits: [<,>,==,SO] 1256 1257 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. 1258 1259 Indexing from BI to guest state: 1260 1261 let n = BI / 4 1262 off = BI % 4 1263 this references CR n: 1264 1265 off==0 -> guest_CRn_321 >> 3 1266 off==1 -> guest_CRn_321 >> 2 1267 off==2 -> guest_CRn_321 >> 1 1268 off==3 -> guest_CRn_SO 1269 1270 Bear in mind the only significant bit in guest_CRn_SO is bit 0 1271 (normal notation) and in guest_CRn_321 the significant bits are 1272 3, 2 and 1 (normal notation). 1273 */ 1274 1275 static void putCR321 ( UInt cr, IRExpr* e ) 1276 { 1277 vassert(cr < 8); 1278 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1279 stmt( IRStmt_Put(guestCR321offset(cr), e) ); 1280 } 1281 1282 static void putCR0 ( UInt cr, IRExpr* e ) 1283 { 1284 vassert(cr < 8); 1285 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1286 stmt( IRStmt_Put(guestCR0offset(cr), e) ); 1287 } 1288 1289 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) 1290 { 1291 vassert(cr < 8); 1292 return IRExpr_Get(guestCR0offset(cr), Ity_I8); 1293 } 1294 1295 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) 1296 { 1297 vassert(cr < 8); 1298 return IRExpr_Get(guestCR321offset(cr), Ity_I8); 1299 } 1300 1301 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1302 return it at the bottom of an I32; the top 31 bits are guaranteed 1303 to be zero. */ 1304 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi ) 1305 { 1306 UInt n = bi / 4; 1307 UInt off = bi % 4; 1308 vassert(bi < 32); 1309 if (off == 3) { 1310 /* Fetch the SO bit for this CR field */ 1311 /* Note: And32 is redundant paranoia iff guest state only has 0 1312 or 1 in that slot. */ 1313 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1314 } else { 1315 /* Fetch the <, > or == bit for this CR field */ 1316 return binop( Iop_And32, 1317 binop( Iop_Shr32, 1318 unop(Iop_8Uto32, getCR321(n)), 1319 mkU8(toUChar(3-off)) ), 1320 mkU32(1) ); 1321 } 1322 } 1323 1324 /* Dually, write the least significant bit of BIT to the specified CR 1325 bit. Indexing as per getCRbit. */ 1326 static void putCRbit ( UInt bi, IRExpr* bit ) 1327 { 1328 UInt n, off; 1329 IRExpr* safe; 1330 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32); 1331 safe = binop(Iop_And32, bit, mkU32(1)); 1332 n = bi / 4; 1333 off = bi % 4; 1334 vassert(bi < 32); 1335 if (off == 3) { 1336 /* This is the SO bit for this CR field */ 1337 putCR0(n, unop(Iop_32to8, safe)); 1338 } else { 1339 off = 3 - off; 1340 vassert(off == 1 || off == 2 || off == 3); 1341 putCR321( 1342 n, 1343 unop( Iop_32to8, 1344 binop( Iop_Or32, 1345 /* old value with field masked out */ 1346 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)), 1347 mkU32(~(1 << off))), 1348 /* new value in the right place */ 1349 binop(Iop_Shl32, safe, mkU8(toUChar(off))) 1350 ) 1351 ) 1352 ); 1353 } 1354 } 1355 1356 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1357 return it somewhere in an I32; it does not matter where, but 1358 whichever bit it is, all other bits are guaranteed to be zero. In 1359 other words, the I32-typed expression will be zero if the bit is 1360 zero and nonzero if the bit is 1. Write into *where the index 1361 of where the bit will be. */ 1362 1363 static 1364 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ) 1365 { 1366 UInt n = bi / 4; 1367 UInt off = bi % 4; 1368 vassert(bi < 32); 1369 if (off == 3) { 1370 /* Fetch the SO bit for this CR field */ 1371 /* Note: And32 is redundant paranoia iff guest state only has 0 1372 or 1 in that slot. */ 1373 *where = 0; 1374 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1375 } else { 1376 /* Fetch the <, > or == bit for this CR field */ 1377 *where = 3-off; 1378 return binop( Iop_And32, 1379 unop(Iop_8Uto32, getCR321(n)), 1380 mkU32(1 << (3-off)) ); 1381 } 1382 } 1383 1384 /* Set the CR0 flags following an arithmetic operation. 1385 (Condition Register CR0 Field Definition, PPC32 p60) 1386 */ 1387 static IRExpr* getXER_SO ( void ); 1388 static void set_CR0 ( IRExpr* result ) 1389 { 1390 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 || 1391 typeOfIRExpr(irsb->tyenv,result) == Ity_I64); 1392 if (mode64) { 1393 putCR321( 0, unop(Iop_64to8, 1394 binop(Iop_CmpORD64S, result, mkU64(0))) ); 1395 } else { 1396 putCR321( 0, unop(Iop_32to8, 1397 binop(Iop_CmpORD32S, result, mkU32(0))) ); 1398 } 1399 putCR0( 0, getXER_SO() ); 1400 } 1401 1402 1403 /* Set the CR6 flags following an AltiVec compare operation. */ 1404 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) 1405 { 1406 /* CR6[0:3] = {all_ones, 0, all_zeros, 0} 1407 all_ones = (v[0] && v[1] && v[2] && v[3]) 1408 all_zeros = ~(v[0] || v[1] || v[2] || v[3]) 1409 */ 1410 IRTemp v0 = newTemp(Ity_V128); 1411 IRTemp v1 = newTemp(Ity_V128); 1412 IRTemp v2 = newTemp(Ity_V128); 1413 IRTemp v3 = newTemp(Ity_V128); 1414 IRTemp rOnes = newTemp(Ity_I8); 1415 IRTemp rZeros = newTemp(Ity_I8); 1416 1417 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128); 1418 1419 assign( v0, result ); 1420 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); 1421 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); 1422 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); 1423 1424 assign( rZeros, unop(Iop_1Uto8, 1425 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1426 unop(Iop_Not32, 1427 unop(Iop_V128to32, 1428 binop(Iop_OrV128, 1429 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), 1430 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) 1431 ))) ); 1432 1433 if (test_all_ones) { 1434 assign( rOnes, unop(Iop_1Uto8, 1435 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1436 unop(Iop_V128to32, 1437 binop(Iop_AndV128, 1438 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), 1439 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))) 1440 ))) ); 1441 putCR321( 6, binop(Iop_Or8, 1442 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), 1443 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); 1444 } else { 1445 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); 1446 } 1447 putCR0( 6, mkU8(0) ); 1448 } 1449 1450 1451 1452 /*------------------------------------------------------------*/ 1453 /*--- Helpers for XER flags. ---*/ 1454 /*------------------------------------------------------------*/ 1455 1456 static void putXER_SO ( IRExpr* e ) 1457 { 1458 IRExpr* so; 1459 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1460 so = binop(Iop_And8, e, mkU8(1)); 1461 stmt( IRStmt_Put( OFFB_XER_SO, so ) ); 1462 } 1463 1464 static void putXER_OV ( IRExpr* e ) 1465 { 1466 IRExpr* ov; 1467 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1468 ov = binop(Iop_And8, e, mkU8(1)); 1469 stmt( IRStmt_Put( OFFB_XER_OV, ov ) ); 1470 } 1471 1472 static void putXER_CA ( IRExpr* e ) 1473 { 1474 IRExpr* ca; 1475 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1476 ca = binop(Iop_And8, e, mkU8(1)); 1477 stmt( IRStmt_Put( OFFB_XER_CA, ca ) ); 1478 } 1479 1480 static void putXER_BC ( IRExpr* e ) 1481 { 1482 IRExpr* bc; 1483 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1484 bc = binop(Iop_And8, e, mkU8(0x7F)); 1485 stmt( IRStmt_Put( OFFB_XER_BC, bc ) ); 1486 } 1487 1488 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) 1489 { 1490 return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); 1491 } 1492 1493 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void ) 1494 { 1495 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) ); 1496 } 1497 1498 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ) 1499 { 1500 return IRExpr_Get( OFFB_XER_OV, Ity_I8 ); 1501 } 1502 1503 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void ) 1504 { 1505 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) ); 1506 } 1507 1508 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void ) 1509 { 1510 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 ); 1511 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 1512 } 1513 1514 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ) 1515 { 1516 return IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 1517 } 1518 1519 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void ) 1520 { 1521 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 1522 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) ); 1523 } 1524 1525 1526 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and 1527 %XER.SO accordingly. */ 1528 1529 static void set_XER_OV_32( UInt op, IRExpr* res, 1530 IRExpr* argL, IRExpr* argR ) 1531 { 1532 IRTemp t64; 1533 IRExpr* xer_ov; 1534 vassert(op < PPCG_FLAG_OP_NUMBER); 1535 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 1536 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 1537 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 1538 1539 # define INT32_MIN 0x80000000 1540 1541 # define XOR2(_aa,_bb) \ 1542 binop(Iop_Xor32,(_aa),(_bb)) 1543 1544 # define XOR3(_cc,_dd,_ee) \ 1545 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee)) 1546 1547 # define AND3(_ff,_gg,_hh) \ 1548 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh)) 1549 1550 #define NOT(_jj) \ 1551 unop(Iop_Not32, (_jj)) 1552 1553 switch (op) { 1554 case /* 0 */ PPCG_FLAG_OP_ADD: 1555 case /* 1 */ PPCG_FLAG_OP_ADDE: 1556 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */ 1557 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 1558 xer_ov 1559 = AND3( XOR3(argL,argR,mkU32(-1)), 1560 XOR2(argL,res), 1561 mkU32(INT32_MIN) ); 1562 /* xer_ov can only be 0 or 1<<31 */ 1563 xer_ov 1564 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 1565 break; 1566 1567 case /* 2 */ PPCG_FLAG_OP_DIVW: 1568 /* (argL == INT32_MIN && argR == -1) || argR == 0 */ 1569 xer_ov 1570 = mkOR1( 1571 mkAND1( 1572 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)), 1573 binop(Iop_CmpEQ32, argR, mkU32(-1)) 1574 ), 1575 binop(Iop_CmpEQ32, argR, mkU32(0) ) 1576 ); 1577 xer_ov 1578 = unop(Iop_1Uto32, xer_ov); 1579 break; 1580 1581 case /* 3 */ PPCG_FLAG_OP_DIVWU: 1582 /* argR == 0 */ 1583 xer_ov 1584 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); 1585 break; 1586 1587 case /* 4 */ PPCG_FLAG_OP_MULLW: 1588 /* OV true if result can't be represented in 32 bits 1589 i.e sHi != sign extension of sLo */ 1590 t64 = newTemp(Ity_I64); 1591 assign( t64, binop(Iop_MullS32, argL, argR) ); 1592 xer_ov 1593 = binop( Iop_CmpNE32, 1594 unop(Iop_64HIto32, mkexpr(t64)), 1595 binop( Iop_Sar32, 1596 unop(Iop_64to32, mkexpr(t64)), 1597 mkU8(31)) 1598 ); 1599 xer_ov 1600 = unop(Iop_1Uto32, xer_ov); 1601 break; 1602 1603 case /* 5 */ PPCG_FLAG_OP_NEG: 1604 /* argL == INT32_MIN */ 1605 xer_ov 1606 = unop( Iop_1Uto32, 1607 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); 1608 break; 1609 1610 case /* 6 */ PPCG_FLAG_OP_SUBF: 1611 case /* 7 */ PPCG_FLAG_OP_SUBFC: 1612 case /* 8 */ PPCG_FLAG_OP_SUBFE: 1613 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */ 1614 xer_ov 1615 = AND3( XOR3(NOT(argL),argR,mkU32(-1)), 1616 XOR2(NOT(argL),res), 1617 mkU32(INT32_MIN) ); 1618 /* xer_ov can only be 0 or 1<<31 */ 1619 xer_ov 1620 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 1621 break; 1622 1623 default: 1624 vex_printf("set_XER_OV: op = %u\n", op); 1625 vpanic("set_XER_OV(ppc)"); 1626 } 1627 1628 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 1629 putXER_OV( unop(Iop_32to8, xer_ov) ); 1630 1631 /* Update the summary overflow */ 1632 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 1633 1634 # undef INT32_MIN 1635 # undef AND3 1636 # undef XOR3 1637 # undef XOR2 1638 # undef NOT 1639 } 1640 1641 static void set_XER_OV_64( UInt op, IRExpr* res, 1642 IRExpr* argL, IRExpr* argR ) 1643 { 1644 IRExpr* xer_ov; 1645 vassert(op < PPCG_FLAG_OP_NUMBER); 1646 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 1647 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 1648 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 1649 1650 # define INT64_MIN 0x8000000000000000ULL 1651 1652 # define XOR2(_aa,_bb) \ 1653 binop(Iop_Xor64,(_aa),(_bb)) 1654 1655 # define XOR3(_cc,_dd,_ee) \ 1656 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee)) 1657 1658 # define AND3(_ff,_gg,_hh) \ 1659 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh)) 1660 1661 #define NOT(_jj) \ 1662 unop(Iop_Not64, (_jj)) 1663 1664 switch (op) { 1665 case /* 0 */ PPCG_FLAG_OP_ADD: 1666 case /* 1 */ PPCG_FLAG_OP_ADDE: 1667 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */ 1668 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 1669 xer_ov 1670 = AND3( XOR3(argL,argR,mkU64(-1)), 1671 XOR2(argL,res), 1672 mkU64(INT64_MIN) ); 1673 /* xer_ov can only be 0 or 1<<63 */ 1674 xer_ov 1675 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 1676 break; 1677 1678 case /* 2 */ PPCG_FLAG_OP_DIVW: 1679 /* (argL == INT64_MIN && argR == -1) || argR == 0 */ 1680 xer_ov 1681 = mkOR1( 1682 mkAND1( 1683 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)), 1684 binop(Iop_CmpEQ64, argR, mkU64(-1)) 1685 ), 1686 binop(Iop_CmpEQ64, argR, mkU64(0) ) 1687 ); 1688 break; 1689 1690 case /* 3 */ PPCG_FLAG_OP_DIVWU: 1691 /* argR == 0 */ 1692 xer_ov 1693 = binop(Iop_CmpEQ64, argR, mkU64(0)); 1694 break; 1695 1696 case /* 4 */ PPCG_FLAG_OP_MULLW: { 1697 /* OV true if result can't be represented in 64 bits 1698 i.e sHi != sign extension of sLo */ 1699 xer_ov 1700 = binop( Iop_CmpNE32, 1701 unop(Iop_64HIto32, res), 1702 binop( Iop_Sar32, 1703 unop(Iop_64to32, res), 1704 mkU8(31)) 1705 ); 1706 break; 1707 } 1708 1709 case /* 5 */ PPCG_FLAG_OP_NEG: 1710 /* argL == INT64_MIN */ 1711 xer_ov 1712 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)); 1713 break; 1714 1715 case /* 6 */ PPCG_FLAG_OP_SUBF: 1716 case /* 7 */ PPCG_FLAG_OP_SUBFC: 1717 case /* 8 */ PPCG_FLAG_OP_SUBFE: 1718 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */ 1719 xer_ov 1720 = AND3( XOR3(NOT(argL),argR,mkU64(-1)), 1721 XOR2(NOT(argL),res), 1722 mkU64(INT64_MIN) ); 1723 /* xer_ov can only be 0 or 1<<63 */ 1724 xer_ov 1725 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 1726 break; 1727 1728 default: 1729 vex_printf("set_XER_OV: op = %u\n", op); 1730 vpanic("set_XER_OV(ppc64)"); 1731 } 1732 1733 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 1734 putXER_OV( unop(Iop_1Uto8, xer_ov) ); 1735 1736 /* Update the summary overflow */ 1737 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 1738 1739 # undef INT64_MIN 1740 # undef AND3 1741 # undef XOR3 1742 # undef XOR2 1743 # undef NOT 1744 } 1745 1746 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res, 1747 IRExpr* argL, IRExpr* argR ) 1748 { 1749 if (ty == Ity_I32) 1750 set_XER_OV_32( op, res, argL, argR ); 1751 else 1752 set_XER_OV_64( op, res, argL, argR ); 1753 } 1754 1755 1756 1757 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA 1758 value being OLDCA. Set %XER.CA accordingly. */ 1759 1760 static void set_XER_CA_32 ( UInt op, IRExpr* res, 1761 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 1762 { 1763 IRExpr* xer_ca; 1764 vassert(op < PPCG_FLAG_OP_NUMBER); 1765 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 1766 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 1767 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 1768 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32); 1769 1770 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 1771 seems reasonable given that it's always generated by 1772 getXER_CA32(), which masks it accordingly. In any case it being 1773 0 or 1 is an invariant of the ppc guest state representation; 1774 if it has any other value, that invariant has been violated. */ 1775 1776 switch (op) { 1777 case /* 0 */ PPCG_FLAG_OP_ADD: 1778 /* res <u argL */ 1779 xer_ca 1780 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); 1781 break; 1782 1783 case /* 1 */ PPCG_FLAG_OP_ADDE: 1784 /* res <u argL || (old_ca==1 && res==argL) */ 1785 xer_ca 1786 = mkOR1( 1787 binop(Iop_CmpLT32U, res, argL), 1788 mkAND1( 1789 binop(Iop_CmpEQ32, oldca, mkU32(1)), 1790 binop(Iop_CmpEQ32, res, argL) 1791 ) 1792 ); 1793 xer_ca 1794 = unop(Iop_1Uto32, xer_ca); 1795 break; 1796 1797 case /* 8 */ PPCG_FLAG_OP_SUBFE: 1798 /* res <u argR || (old_ca==1 && res==argR) */ 1799 xer_ca 1800 = mkOR1( 1801 binop(Iop_CmpLT32U, res, argR), 1802 mkAND1( 1803 binop(Iop_CmpEQ32, oldca, mkU32(1)), 1804 binop(Iop_CmpEQ32, res, argR) 1805 ) 1806 ); 1807 xer_ca 1808 = unop(Iop_1Uto32, xer_ca); 1809 break; 1810 1811 case /* 7 */ PPCG_FLAG_OP_SUBFC: 1812 case /* 9 */ PPCG_FLAG_OP_SUBFI: 1813 /* res <=u argR */ 1814 xer_ca 1815 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); 1816 break; 1817 1818 case /* 10 */ PPCG_FLAG_OP_SRAW: 1819 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 1820 If it is <= 31, behave like SRAWI; else XER.CA is the sign 1821 bit of argL. */ 1822 /* This term valid for shift amount < 32 only */ 1823 xer_ca 1824 = binop( 1825 Iop_And32, 1826 binop(Iop_Sar32, argL, mkU8(31)), 1827 binop( Iop_And32, 1828 argL, 1829 binop( Iop_Sub32, 1830 binop(Iop_Shl32, mkU32(1), 1831 unop(Iop_32to8,argR)), 1832 mkU32(1) ) 1833 ) 1834 ); 1835 xer_ca 1836 = IRExpr_Mux0X( 1837 /* shift amt > 31 ? */ 1838 unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)), 1839 /* no -- be like srawi */ 1840 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))), 1841 /* yes -- get sign bit of argL */ 1842 binop(Iop_Shr32, argL, mkU8(31)) 1843 ); 1844 break; 1845 1846 case /* 11 */ PPCG_FLAG_OP_SRAWI: 1847 /* xer_ca is 1 iff src was negative and bits_shifted_out != 1848 0. Since the shift amount is known to be in the range 1849 0 .. 31 inclusive the following seems viable: 1850 xer.ca == 1 iff the following is nonzero: 1851 (argL >>s 31) -- either all 0s or all 1s 1852 & (argL & (1<<argR)-1) -- the stuff shifted out */ 1853 xer_ca 1854 = binop( 1855 Iop_And32, 1856 binop(Iop_Sar32, argL, mkU8(31)), 1857 binop( Iop_And32, 1858 argL, 1859 binop( Iop_Sub32, 1860 binop(Iop_Shl32, mkU32(1), 1861 unop(Iop_32to8,argR)), 1862 mkU32(1) ) 1863 ) 1864 ); 1865 xer_ca 1866 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); 1867 break; 1868 1869 default: 1870 vex_printf("set_XER_CA: op = %u\n", op); 1871 vpanic("set_XER_CA(ppc)"); 1872 } 1873 1874 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 1875 putXER_CA( unop(Iop_32to8, xer_ca) ); 1876 } 1877 1878 static void set_XER_CA_64 ( UInt op, IRExpr* res, 1879 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 1880 { 1881 IRExpr* xer_ca; 1882 vassert(op < PPCG_FLAG_OP_NUMBER); 1883 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 1884 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 1885 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 1886 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64); 1887 1888 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 1889 seems reasonable given that it's always generated by 1890 getXER_CA32(), which masks it accordingly. In any case it being 1891 0 or 1 is an invariant of the ppc guest state representation; 1892 if it has any other value, that invariant has been violated. */ 1893 1894 switch (op) { 1895 case /* 0 */ PPCG_FLAG_OP_ADD: 1896 /* res <u argL */ 1897 xer_ca 1898 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL)); 1899 break; 1900 1901 case /* 1 */ PPCG_FLAG_OP_ADDE: 1902 /* res <u argL || (old_ca==1 && res==argL) */ 1903 xer_ca 1904 = mkOR1( 1905 binop(Iop_CmpLT64U, res, argL), 1906 mkAND1( 1907 binop(Iop_CmpEQ64, oldca, mkU64(1)), 1908 binop(Iop_CmpEQ64, res, argL) 1909 ) 1910 ); 1911 xer_ca 1912 = unop(Iop_1Uto32, xer_ca); 1913 break; 1914 1915 case /* 8 */ PPCG_FLAG_OP_SUBFE: 1916 /* res <u argR || (old_ca==1 && res==argR) */ 1917 xer_ca 1918 = mkOR1( 1919 binop(Iop_CmpLT64U, res, argR), 1920 mkAND1( 1921 binop(Iop_CmpEQ64, oldca, mkU64(1)), 1922 binop(Iop_CmpEQ64, res, argR) 1923 ) 1924 ); 1925 xer_ca 1926 = unop(Iop_1Uto32, xer_ca); 1927 break; 1928 1929 case /* 7 */ PPCG_FLAG_OP_SUBFC: 1930 case /* 9 */ PPCG_FLAG_OP_SUBFI: 1931 /* res <=u argR */ 1932 xer_ca 1933 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR)); 1934 break; 1935 1936 1937 case /* 10 */ PPCG_FLAG_OP_SRAW: 1938 /* The shift amount is guaranteed to be in 0 .. 31 inclusive. 1939 If it is <= 31, behave like SRAWI; else XER.CA is the sign 1940 bit of argL. */ 1941 /* This term valid for shift amount < 31 only */ 1942 1943 xer_ca 1944 = binop( 1945 Iop_And64, 1946 binop(Iop_Sar64, argL, mkU8(31)), 1947 binop( Iop_And64, 1948 argL, 1949 binop( Iop_Sub64, 1950 binop(Iop_Shl64, mkU64(1), 1951 unop(Iop_64to8,argR)), 1952 mkU64(1) ) 1953 ) 1954 ); 1955 xer_ca 1956 = IRExpr_Mux0X( 1957 /* shift amt > 31 ? */ 1958 unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(31), argR)), 1959 /* no -- be like srawi */ 1960 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))), 1961 /* yes -- get sign bit of argL */ 1962 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))) 1963 ); 1964 break; 1965 1966 case /* 11 */ PPCG_FLAG_OP_SRAWI: 1967 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 1968 Since the shift amount is known to be in the range 0 .. 31 1969 inclusive the following seems viable: 1970 xer.ca == 1 iff the following is nonzero: 1971 (argL >>s 31) -- either all 0s or all 1s 1972 & (argL & (1<<argR)-1) -- the stuff shifted out */ 1973 1974 xer_ca 1975 = binop( 1976 Iop_And64, 1977 binop(Iop_Sar64, argL, mkU8(31)), 1978 binop( Iop_And64, 1979 argL, 1980 binop( Iop_Sub64, 1981 binop(Iop_Shl64, mkU64(1), 1982 unop(Iop_64to8,argR)), 1983 mkU64(1) ) 1984 ) 1985 ); 1986 xer_ca 1987 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 1988 break; 1989 1990 1991 case /* 12 */ PPCG_FLAG_OP_SRAD: 1992 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 1993 If it is <= 63, behave like SRADI; else XER.CA is the sign 1994 bit of argL. */ 1995 /* This term valid for shift amount < 63 only */ 1996 1997 xer_ca 1998 = binop( 1999 Iop_And64, 2000 binop(Iop_Sar64, argL, mkU8(63)), 2001 binop( Iop_And64, 2002 argL, 2003 binop( Iop_Sub64, 2004 binop(Iop_Shl64, mkU64(1), 2005 unop(Iop_64to8,argR)), 2006 mkU64(1) ) 2007 ) 2008 ); 2009 xer_ca 2010 = IRExpr_Mux0X( 2011 /* shift amt > 63 ? */ 2012 unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)), 2013 /* no -- be like sradi */ 2014 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))), 2015 /* yes -- get sign bit of argL */ 2016 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))) 2017 ); 2018 break; 2019 2020 2021 case /* 13 */ PPCG_FLAG_OP_SRADI: 2022 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2023 Since the shift amount is known to be in the range 0 .. 63 2024 inclusive, the following seems viable: 2025 xer.ca == 1 iff the following is nonzero: 2026 (argL >>s 63) -- either all 0s or all 1s 2027 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2028 2029 xer_ca 2030 = binop( 2031 Iop_And64, 2032 binop(Iop_Sar64, argL, mkU8(63)), 2033 binop( Iop_And64, 2034 argL, 2035 binop( Iop_Sub64, 2036 binop(Iop_Shl64, mkU64(1), 2037 unop(Iop_64to8,argR)), 2038 mkU64(1) ) 2039 ) 2040 ); 2041 xer_ca 2042 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2043 break; 2044 2045 default: 2046 vex_printf("set_XER_CA: op = %u\n", op); 2047 vpanic("set_XER_CA(ppc64)"); 2048 } 2049 2050 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2051 putXER_CA( unop(Iop_32to8, xer_ca) ); 2052 } 2053 2054 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res, 2055 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2056 { 2057 if (ty == Ity_I32) 2058 set_XER_CA_32( op, res, argL, argR, oldca ); 2059 else 2060 set_XER_CA_64( op, res, argL, argR, oldca ); 2061 } 2062 2063 2064 2065 /*------------------------------------------------------------*/ 2066 /*--- Read/write to guest-state --- */ 2067 /*------------------------------------------------------------*/ 2068 2069 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg ) 2070 { 2071 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2072 switch (reg) { 2073 case PPC_GST_SPRG3_RO: 2074 return IRExpr_Get( OFFB_SPRG3_RO, ty ); 2075 2076 case PPC_GST_CIA: 2077 return IRExpr_Get( OFFB_CIA, ty ); 2078 2079 case PPC_GST_LR: 2080 return IRExpr_Get( OFFB_LR, ty ); 2081 2082 case PPC_GST_CTR: 2083 return IRExpr_Get( OFFB_CTR, ty ); 2084 2085 case PPC_GST_VRSAVE: 2086 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); 2087 2088 case PPC_GST_VSCR: 2089 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ), 2090 mkU32(MASK_VSCR_VALID)); 2091 2092 case PPC_GST_CR: { 2093 /* Synthesise the entire CR into a single word. Expensive. */ 2094 # define FIELD(_n) \ 2095 binop(Iop_Shl32, \ 2096 unop(Iop_8Uto32, \ 2097 binop(Iop_Or8, \ 2098 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ 2099 binop(Iop_And8, getCR0(_n), mkU8(1)) \ 2100 ) \ 2101 ), \ 2102 mkU8(4 * (7-(_n))) \ 2103 ) 2104 return binop(Iop_Or32, 2105 binop(Iop_Or32, 2106 binop(Iop_Or32, FIELD(0), FIELD(1)), 2107 binop(Iop_Or32, FIELD(2), FIELD(3)) 2108 ), 2109 binop(Iop_Or32, 2110 binop(Iop_Or32, FIELD(4), FIELD(5)), 2111 binop(Iop_Or32, FIELD(6), FIELD(7)) 2112 ) 2113 ); 2114 # undef FIELD 2115 } 2116 2117 case PPC_GST_XER: 2118 return binop(Iop_Or32, 2119 binop(Iop_Or32, 2120 binop( Iop_Shl32, getXER_SO32(), mkU8(31)), 2121 binop( Iop_Shl32, getXER_OV32(), mkU8(30))), 2122 binop(Iop_Or32, 2123 binop( Iop_Shl32, getXER_CA32(), mkU8(29)), 2124 getXER_BC32())); 2125 2126 default: 2127 vex_printf("getGST(ppc): reg = %u", reg); 2128 vpanic("getGST(ppc)"); 2129 } 2130 } 2131 2132 /* Get a masked word from the given reg */ 2133 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask ) 2134 { 2135 IRTemp val = newTemp(Ity_I32); 2136 vassert( reg < PPC_GST_MAX ); 2137 2138 switch (reg) { 2139 2140 case PPC_GST_FPSCR: { 2141 /* Vex-generated code expects the FPSCR to be set as follows: 2142 all exceptions masked, round-to-nearest. 2143 This corresponds to a FPSCR value of 0x0. */ 2144 2145 /* We're only keeping track of the rounding mode, 2146 so if the mask isn't asking for this, just return 0x0 */ 2147 if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) { 2148 assign( val, IRExpr_Get( OFFB_FPROUND, Ity_I32 ) ); 2149 } else { 2150 assign( val, mkU32(0x0) ); 2151 } 2152 break; 2153 } 2154 2155 default: 2156 vex_printf("getGST_masked(ppc): reg = %u", reg); 2157 vpanic("getGST_masked(ppc)"); 2158 } 2159 2160 if (mask != 0xFFFFFFFF) { 2161 return binop(Iop_And32, mkexpr(val), mkU32(mask)); 2162 } else { 2163 return mkexpr(val); 2164 } 2165 } 2166 2167 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation) 2168 and return it at the bottom of an I32; the top 27 bits are 2169 guaranteed to be zero. */ 2170 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld ) 2171 { 2172 UInt shft, mask; 2173 2174 vassert( fld < 8 ); 2175 vassert( reg < PPC_GST_MAX ); 2176 2177 shft = 4*(7-fld); 2178 mask = 0xF<<shft; 2179 2180 switch (reg) { 2181 case PPC_GST_XER: 2182 vassert(fld ==7); 2183 return binop(Iop_Or32, 2184 binop(Iop_Or32, 2185 binop(Iop_Shl32, getXER_SO32(), mkU8(3)), 2186 binop(Iop_Shl32, getXER_OV32(), mkU8(2))), 2187 binop( Iop_Shl32, getXER_CA32(), mkU8(1))); 2188 break; 2189 2190 default: 2191 if (shft == 0) 2192 return getGST_masked( reg, mask ); 2193 else 2194 return binop(Iop_Shr32, 2195 getGST_masked( reg, mask ), 2196 mkU8(toUChar( shft ))); 2197 } 2198 } 2199 2200 static void putGST ( PPC_GST reg, IRExpr* src ) 2201 { 2202 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2203 IRType ty_src = typeOfIRExpr(irsb->tyenv,src ); 2204 vassert( reg < PPC_GST_MAX ); 2205 switch (reg) { 2206 case PPC_GST_IP_AT_SYSCALL: 2207 vassert( ty_src == ty ); 2208 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) ); 2209 break; 2210 case PPC_GST_CIA: 2211 vassert( ty_src == ty ); 2212 stmt( IRStmt_Put( OFFB_CIA, src ) ); 2213 break; 2214 case PPC_GST_LR: 2215 vassert( ty_src == ty ); 2216 stmt( IRStmt_Put( OFFB_LR, src ) ); 2217 break; 2218 case PPC_GST_CTR: 2219 vassert( ty_src == ty ); 2220 stmt( IRStmt_Put( OFFB_CTR, src ) ); 2221 break; 2222 case PPC_GST_VRSAVE: 2223 vassert( ty_src == Ity_I32 ); 2224 stmt( IRStmt_Put( OFFB_VRSAVE,src)); 2225 break; 2226 case PPC_GST_VSCR: 2227 vassert( ty_src == Ity_I32 ); 2228 stmt( IRStmt_Put( OFFB_VSCR, 2229 binop(Iop_And32, src, 2230 mkU32(MASK_VSCR_VALID)) ) ); 2231 break; 2232 case PPC_GST_XER: 2233 vassert( ty_src == Ity_I32 ); 2234 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) ); 2235 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) ); 2236 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) ); 2237 putXER_BC( unop(Iop_32to8, src) ); 2238 break; 2239 2240 case PPC_GST_EMWARN: 2241 vassert( ty_src == Ity_I32 ); 2242 stmt( IRStmt_Put( OFFB_EMWARN,src) ); 2243 break; 2244 2245 case PPC_GST_TISTART: 2246 vassert( ty_src == ty ); 2247 stmt( IRStmt_Put( OFFB_TISTART, src) ); 2248 break; 2249 2250 case PPC_GST_TILEN: 2251 vassert( ty_src == ty ); 2252 stmt( IRStmt_Put( OFFB_TILEN, src) ); 2253 break; 2254 2255 default: 2256 vex_printf("putGST(ppc): reg = %u", reg); 2257 vpanic("putGST(ppc)"); 2258 } 2259 } 2260 2261 /* Write masked src to the given reg */ 2262 static void putGST_masked ( PPC_GST reg, IRExpr* src, UInt mask ) 2263 { 2264 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2265 vassert( reg < PPC_GST_MAX ); 2266 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 2267 2268 switch (reg) { 2269 case PPC_GST_FPSCR: { 2270 /* Allow writes to Rounding Mode */ 2271 if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) { 2272 /* construct new fpround from new and old values as per mask: 2273 new fpround = (src & (3 & mask)) | (fpround & (3 & ~mask)) */ 2274 stmt( 2275 IRStmt_Put( 2276 OFFB_FPROUND, 2277 binop( 2278 Iop_Or32, 2279 binop(Iop_And32, src, mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & mask)), 2280 binop( 2281 Iop_And32, 2282 IRExpr_Get(OFFB_FPROUND,Ity_I32), 2283 mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & ~mask) 2284 ) 2285 ) 2286 ) 2287 ); 2288 } 2289 2290 /* Give EmWarn for attempted writes to: 2291 - Exception Controls 2292 - Non-IEEE Mode 2293 */ 2294 if (mask & 0xFC) { // Exception Control, Non-IEE mode 2295 VexEmWarn ew = EmWarn_PPCexns; 2296 2297 /* If any of the src::exception_control bits are actually set, 2298 side-exit to the next insn, reporting the warning, 2299 so that Valgrind's dispatcher sees the warning. */ 2300 putGST( PPC_GST_EMWARN, mkU32(ew) ); 2301 stmt( 2302 IRStmt_Exit( 2303 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)), 2304 Ijk_EmWarn, 2305 mkSzConst( ty, nextInsnAddr()) )); 2306 } 2307 2308 /* Ignore all other writes */ 2309 break; 2310 } 2311 2312 default: 2313 vex_printf("putGST_masked(ppc): reg = %u", reg); 2314 vpanic("putGST_masked(ppc)"); 2315 } 2316 } 2317 2318 /* Write the least significant nibble of src to the specified 2319 REG[FLD] (as per IBM/hardware notation). */ 2320 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld ) 2321 { 2322 UInt shft, mask; 2323 2324 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 2325 vassert( fld < 8 ); 2326 vassert( reg < PPC_GST_MAX ); 2327 2328 shft = 4*(7-fld); 2329 mask = 0xF<<shft; 2330 2331 switch (reg) { 2332 case PPC_GST_CR: 2333 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src))); 2334 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src))); 2335 break; 2336 2337 default: 2338 if (shft == 0) { 2339 putGST_masked( reg, src, mask ); 2340 } else { 2341 putGST_masked( reg, 2342 binop(Iop_Shl32, src, mkU8(toUChar(shft))), 2343 mask ); 2344 } 2345 } 2346 } 2347 2348 2349 2350 /*------------------------------------------------------------*/ 2351 /*--- Integer Instruction Translation --- */ 2352 /*------------------------------------------------------------*/ 2353 2354 /* 2355 Integer Arithmetic Instructions 2356 */ 2357 static Bool dis_int_arith ( UInt theInstr ) 2358 { 2359 /* D-Form, XO-Form */ 2360 UChar opc1 = ifieldOPC(theInstr); 2361 UChar rD_addr = ifieldRegDS(theInstr); 2362 UChar rA_addr = ifieldRegA(theInstr); 2363 UInt uimm16 = ifieldUIMM16(theInstr); 2364 UChar rB_addr = ifieldRegB(theInstr); 2365 UChar flag_OE = ifieldBIT10(theInstr); 2366 UInt opc2 = ifieldOPClo9(theInstr); 2367 UChar flag_rC = ifieldBIT0(theInstr); 2368 2369 Long simm16 = extend_s_16to64(uimm16); 2370 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2371 IRTemp rA = newTemp(ty); 2372 IRTemp rB = newTemp(ty); 2373 IRTemp rD = newTemp(ty); 2374 2375 Bool do_rc = False; 2376 2377 assign( rA, getIReg(rA_addr) ); 2378 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB 2379 2380 switch (opc1) { 2381 /* D-Form */ 2382 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 2383 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 2384 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 2385 mkSzExtendS16(ty, uimm16) ) ); 2386 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 2387 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 2388 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 2389 break; 2390 2391 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) 2392 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 2393 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 2394 mkSzExtendS16(ty, uimm16) ) ); 2395 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 2396 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 2397 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 2398 do_rc = True; // Always record to CR 2399 flag_rC = 1; 2400 break; 2401 2402 case 0x0E: // addi (Add Immediate, PPC32 p350) 2403 // li rD,val == addi rD,0,val 2404 // la disp(rA) == addi rD,rA,disp 2405 if ( rA_addr == 0 ) { 2406 DIP("li r%u,%d\n", rD_addr, (Int)simm16); 2407 assign( rD, mkSzExtendS16(ty, uimm16) ); 2408 } else { 2409 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 2410 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 2411 mkSzExtendS16(ty, uimm16) ) ); 2412 } 2413 break; 2414 2415 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353) 2416 // lis rD,val == addis rD,0,val 2417 if ( rA_addr == 0 ) { 2418 DIP("lis r%u,%d\n", rD_addr, (Int)simm16); 2419 assign( rD, mkSzExtendS32(ty, uimm16 << 16) ); 2420 } else { 2421 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16); 2422 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 2423 mkSzExtendS32(ty, uimm16 << 16) ) ); 2424 } 2425 break; 2426 2427 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490) 2428 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 2429 if (mode64) 2430 assign( rD, unop(Iop_128to64, 2431 binop(Iop_MullS64, mkexpr(rA), 2432 mkSzExtendS16(ty, uimm16))) ); 2433 else 2434 assign( rD, unop(Iop_64to32, 2435 binop(Iop_MullS32, mkexpr(rA), 2436 mkSzExtendS16(ty, uimm16))) ); 2437 break; 2438 2439 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540) 2440 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 2441 // rD = simm16 - rA 2442 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 2443 mkSzExtendS16(ty, uimm16), 2444 mkexpr(rA)) ); 2445 set_XER_CA( ty, PPCG_FLAG_OP_SUBFI, 2446 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 2447 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 2448 break; 2449 2450 /* XO-Form */ 2451 case 0x1F: 2452 do_rc = True; // All below record to CR 2453 2454 switch (opc2) { 2455 case 0x10A: // add (Add, PPC32 p347) 2456 DIP("add%s%s r%u,r%u,r%u\n", 2457 flag_OE ? "o" : "", flag_rC ? ".":"", 2458 rD_addr, rA_addr, rB_addr); 2459 assign( rD, binop( mkSzOp(ty, Iop_Add8), 2460 mkexpr(rA), mkexpr(rB) ) ); 2461 if (flag_OE) { 2462 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 2463 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2464 } 2465 break; 2466 2467 case 0x00A: // addc (Add Carrying, PPC32 p348) 2468 DIP("addc%s%s r%u,r%u,r%u\n", 2469 flag_OE ? "o" : "", flag_rC ? ".":"", 2470 rD_addr, rA_addr, rB_addr); 2471 assign( rD, binop( mkSzOp(ty, Iop_Add8), 2472 mkexpr(rA), mkexpr(rB)) ); 2473 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 2474 mkexpr(rD), mkexpr(rA), mkexpr(rB), 2475 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 2476 if (flag_OE) { 2477 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 2478 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2479 } 2480 break; 2481 2482 case 0x08A: { // adde (Add Extended, PPC32 p349) 2483 IRTemp old_xer_ca = newTemp(ty); 2484 DIP("adde%s%s r%u,r%u,r%u\n", 2485 flag_OE ? "o" : "", flag_rC ? ".":"", 2486 rD_addr, rA_addr, rB_addr); 2487 // rD = rA + rB + XER[CA] 2488 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 2489 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 2490 binop( mkSzOp(ty, Iop_Add8), 2491 mkexpr(rB), mkexpr(old_xer_ca))) ); 2492 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 2493 mkexpr(rD), mkexpr(rA), mkexpr(rB), 2494 mkexpr(old_xer_ca) ); 2495 if (flag_OE) { 2496 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 2497 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2498 } 2499 break; 2500 } 2501 2502 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354) 2503 IRTemp old_xer_ca = newTemp(ty); 2504 IRExpr *min_one; 2505 if (rB_addr != 0) { 2506 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n"); 2507 return False; 2508 } 2509 DIP("addme%s%s r%u,r%u,r%u\n", 2510 flag_OE ? "o" : "", flag_rC ? ".":"", 2511 rD_addr, rA_addr, rB_addr); 2512 // rD = rA + (-1) + XER[CA] 2513 // => Just another form of adde 2514 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 2515 min_one = mkSzImm(ty, (Long)-1); 2516 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 2517 binop( mkSzOp(ty, Iop_Add8), 2518 min_one, mkexpr(old_xer_ca)) )); 2519 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 2520 mkexpr(rD), mkexpr(rA), min_one, 2521 mkexpr(old_xer_ca) ); 2522 if (flag_OE) { 2523 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 2524 mkexpr(rD), mkexpr(rA), min_one ); 2525 } 2526 break; 2527 } 2528 2529 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355) 2530 IRTemp old_xer_ca = newTemp(ty); 2531 if (rB_addr != 0) { 2532 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n"); 2533 return False; 2534 } 2535 DIP("addze%s%s r%u,r%u,r%u\n", 2536 flag_OE ? "o" : "", flag_rC ? ".":"", 2537 rD_addr, rA_addr, rB_addr); 2538 // rD = rA + (0) + XER[CA] 2539 // => Just another form of adde 2540 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 2541 assign( rD, binop( mkSzOp(ty, Iop_Add8), 2542 mkexpr(rA), mkexpr(old_xer_ca)) ); 2543 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 2544 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 2545 mkexpr(old_xer_ca) ); 2546 if (flag_OE) { 2547 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 2548 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 2549 } 2550 break; 2551 } 2552 2553 case 0x1EB: // divw (Divide Word, PPC32 p388) 2554 DIP("divw%s%s r%u,r%u,r%u\n", 2555 flag_OE ? "o" : "", flag_rC ? ".":"", 2556 rD_addr, rA_addr, rB_addr); 2557 if (mode64) { 2558 /* Note: 2559 XER settings are mode independent, and reflect the 2560 overflow of the low-order 32bit result 2561 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 2562 */ 2563 /* rD[hi32] are undefined: setting them to sign of lo32 2564 - makes set_CR0 happy */ 2565 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) ); 2566 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) ); 2567 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend, 2568 divisor) ) ); 2569 if (flag_OE) { 2570 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 2571 mkexpr(rD), dividend, divisor ); 2572 } 2573 } else { 2574 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) ); 2575 if (flag_OE) { 2576 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 2577 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2578 } 2579 } 2580 /* Note: 2581 if (0x8000_0000 / -1) or (x / 0) 2582 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 2583 => But _no_ exception raised. */ 2584 break; 2585 2586 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389) 2587 DIP("divwu%s%s r%u,r%u,r%u\n", 2588 flag_OE ? "o" : "", flag_rC ? ".":"", 2589 rD_addr, rA_addr, rB_addr); 2590 if (mode64) { 2591 /* Note: 2592 XER settings are mode independent, and reflect the 2593 overflow of the low-order 32bit result 2594 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 2595 */ 2596 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) ); 2597 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) ); 2598 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend, 2599 divisor) ) ); 2600 if (flag_OE) { 2601 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 2602 mkexpr(rD), dividend, divisor ); 2603 } 2604 } else { 2605 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) ); 2606 if (flag_OE) { 2607 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 2608 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2609 } 2610 } 2611 /* Note: ditto comment divw, for (x / 0) */ 2612 break; 2613 2614 case 0x04B: // mulhw (Multiply High Word, PPC32 p488) 2615 if (flag_OE != 0) { 2616 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n"); 2617 return False; 2618 } 2619 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 2620 rD_addr, rA_addr, rB_addr); 2621 if (mode64) { 2622 /* rD[hi32] are undefined: setting them to sign of lo32 2623 - makes set_CR0 happy */ 2624 assign( rD, binop(Iop_Sar64, 2625 binop(Iop_Mul64, 2626 mk64lo32Sto64( mkexpr(rA) ), 2627 mk64lo32Sto64( mkexpr(rB) )), 2628 mkU8(32)) ); 2629 } else { 2630 assign( rD, unop(Iop_64HIto32, 2631 binop(Iop_MullS32, 2632 mkexpr(rA), mkexpr(rB))) ); 2633 } 2634 break; 2635 2636 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489) 2637 if (flag_OE != 0) { 2638 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n"); 2639 return False; 2640 } 2641 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 2642 rD_addr, rA_addr, rB_addr); 2643 if (mode64) { 2644 /* rD[hi32] are undefined: setting them to sign of lo32 2645 - makes set_CR0 happy */ 2646 assign( rD, binop(Iop_Sar64, 2647 binop(Iop_Mul64, 2648 mk64lo32Uto64( mkexpr(rA) ), 2649 mk64lo32Uto64( mkexpr(rB) ) ), 2650 mkU8(32)) ); 2651 } else { 2652 assign( rD, unop(Iop_64HIto32, 2653 binop(Iop_MullU32, 2654 mkexpr(rA), mkexpr(rB))) ); 2655 } 2656 break; 2657 2658 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491) 2659 DIP("mullw%s%s r%u,r%u,r%u\n", 2660 flag_OE ? "o" : "", flag_rC ? ".":"", 2661 rD_addr, rA_addr, rB_addr); 2662 if (mode64) { 2663 /* rD[hi32] are undefined: setting them to sign of lo32 2664 - set_XER_OV() and set_CR0() depend on this */ 2665 IRExpr *a = unop(Iop_64to32, mkexpr(rA) ); 2666 IRExpr *b = unop(Iop_64to32, mkexpr(rB) ); 2667 assign( rD, binop(Iop_MullS32, a, b) ); 2668 if (flag_OE) { 2669 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 2670 mkexpr(rD), 2671 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) ); 2672 } 2673 } else { 2674 assign( rD, unop(Iop_64to32, 2675 binop(Iop_MullU32, 2676 mkexpr(rA), mkexpr(rB))) ); 2677 if (flag_OE) { 2678 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 2679 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2680 } 2681 } 2682 break; 2683 2684 case 0x068: // neg (Negate, PPC32 p493) 2685 if (rB_addr != 0) { 2686 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n"); 2687 return False; 2688 } 2689 DIP("neg%s%s r%u,r%u\n", 2690 flag_OE ? "o" : "", flag_rC ? ".":"", 2691 rD_addr, rA_addr); 2692 // rD = (~rA) + 1 2693 assign( rD, binop( mkSzOp(ty, Iop_Add8), 2694 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ), 2695 mkSzImm(ty, 1)) ); 2696 if (flag_OE) { 2697 set_XER_OV( ty, PPCG_FLAG_OP_NEG, 2698 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2699 } 2700 break; 2701 2702 case 0x028: // subf (Subtract From, PPC32 p537) 2703 DIP("subf%s%s r%u,r%u,r%u\n", 2704 flag_OE ? "o" : "", flag_rC ? ".":"", 2705 rD_addr, rA_addr, rB_addr); 2706 // rD = rB - rA 2707 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 2708 mkexpr(rB), mkexpr(rA)) ); 2709 if (flag_OE) { 2710 set_XER_OV( ty, PPCG_FLAG_OP_SUBF, 2711 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2712 } 2713 break; 2714 2715 case 0x008: // subfc (Subtract from Carrying, PPC32 p538) 2716 DIP("subfc%s%s r%u,r%u,r%u\n", 2717 flag_OE ? "o" : "", flag_rC ? ".":"", 2718 rD_addr, rA_addr, rB_addr); 2719 // rD = rB - rA 2720 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 2721 mkexpr(rB), mkexpr(rA)) ); 2722 set_XER_CA( ty, PPCG_FLAG_OP_SUBFC, 2723 mkexpr(rD), mkexpr(rA), mkexpr(rB), 2724 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 2725 if (flag_OE) { 2726 set_XER_OV( ty, PPCG_FLAG_OP_SUBFC, 2727 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2728 } 2729 break; 2730 2731 case 0x088: {// subfe (Subtract from Extended, PPC32 p539) 2732 IRTemp old_xer_ca = newTemp(ty); 2733 DIP("subfe%s%s r%u,r%u,r%u\n", 2734 flag_OE ? "o" : "", flag_rC ? ".":"", 2735 rD_addr, rA_addr, rB_addr); 2736 // rD = (log not)rA + rB + XER[CA] 2737 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 2738 assign( rD, binop( mkSzOp(ty, Iop_Add8), 2739 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 2740 binop( mkSzOp(ty, Iop_Add8), 2741 mkexpr(rB), mkexpr(old_xer_ca))) ); 2742 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 2743 mkexpr(rD), mkexpr(rA), mkexpr(rB), 2744 mkexpr(old_xer_ca) ); 2745 if (flag_OE) { 2746 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 2747 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2748 } 2749 break; 2750 } 2751 2752 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541) 2753 IRTemp old_xer_ca = newTemp(ty); 2754 IRExpr *min_one; 2755 if (rB_addr != 0) { 2756 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n"); 2757 return False; 2758 } 2759 DIP("subfme%s%s r%u,r%u\n", 2760 flag_OE ? "o" : "", flag_rC ? ".":"", 2761 rD_addr, rA_addr); 2762 // rD = (log not)rA + (-1) + XER[CA] 2763 // => Just another form of subfe 2764 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 2765 min_one = mkSzImm(ty, (Long)-1); 2766 assign( rD, binop( mkSzOp(ty, Iop_Add8), 2767 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 2768 binop( mkSzOp(ty, Iop_Add8), 2769 min_one, mkexpr(old_xer_ca))) ); 2770 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 2771 mkexpr(rD), mkexpr(rA), min_one, 2772 mkexpr(old_xer_ca) ); 2773 if (flag_OE) { 2774 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 2775 mkexpr(rD), mkexpr(rA), min_one ); 2776 } 2777 break; 2778 } 2779 2780 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542) 2781 IRTemp old_xer_ca = newTemp(ty); 2782 if (rB_addr != 0) { 2783 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n"); 2784 return False; 2785 } 2786 DIP("subfze%s%s r%u,r%u\n", 2787 flag_OE ? "o" : "", flag_rC ? ".":"", 2788 rD_addr, rA_addr); 2789 // rD = (log not)rA + (0) + XER[CA] 2790 // => Just another form of subfe 2791 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 2792 assign( rD, binop( mkSzOp(ty, Iop_Add8), 2793 unop( mkSzOp(ty, Iop_Not8), 2794 mkexpr(rA)), mkexpr(old_xer_ca)) ); 2795 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 2796 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 2797 mkexpr(old_xer_ca) ); 2798 if (flag_OE) { 2799 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 2800 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 2801 } 2802 break; 2803 } 2804 2805 2806 /* 64bit Arithmetic */ 2807 case 0x49: // mulhd (Multiply High DWord, PPC64 p539) 2808 if (flag_OE != 0) { 2809 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n"); 2810 return False; 2811 } 2812 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"", 2813 rD_addr, rA_addr, rB_addr); 2814 assign( rD, unop(Iop_128HIto64, 2815 binop(Iop_MullS64, 2816 mkexpr(rA), mkexpr(rB))) ); 2817 2818 break; 2819 2820 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540) 2821 if (flag_OE != 0) { 2822 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n"); 2823 return False; 2824 } 2825 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 2826 rD_addr, rA_addr, rB_addr); 2827 assign( rD, unop(Iop_128HIto64, 2828 binop(Iop_MullU64, 2829 mkexpr(rA), mkexpr(rB))) ); 2830 break; 2831 2832 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543) 2833 DIP("mulld%s%s r%u,r%u,r%u\n", 2834 flag_OE ? "o" : "", flag_rC ? ".":"", 2835 rD_addr, rA_addr, rB_addr); 2836 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) ); 2837 if (flag_OE) { 2838 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 2839 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2840 } 2841 break; 2842 2843 case 0x1E9: // divd (Divide DWord, PPC64 p419) 2844 DIP("divd%s%s r%u,r%u,r%u\n", 2845 flag_OE ? "o" : "", flag_rC ? ".":"", 2846 rD_addr, rA_addr, rB_addr); 2847 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) ); 2848 if (flag_OE) { 2849 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 2850 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2851 } 2852 break; 2853 /* Note: 2854 if (0x8000_0000_0000_0000 / -1) or (x / 0) 2855 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 2856 => But _no_ exception raised. */ 2857 2858 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420) 2859 DIP("divdu%s%s r%u,r%u,r%u\n", 2860 flag_OE ? "o" : "", flag_rC ? ".":"", 2861 rD_addr, rA_addr, rB_addr); 2862 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) ); 2863 if (flag_OE) { 2864 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 2865 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2866 } 2867 break; 2868 /* Note: ditto comment divd, for (x / 0) */ 2869 2870 default: 2871 vex_printf("dis_int_arith(ppc)(opc2)\n"); 2872 return False; 2873 } 2874 break; 2875 2876 default: 2877 vex_printf("dis_int_arith(ppc)(opc1)\n"); 2878 return False; 2879 } 2880 2881 putIReg( rD_addr, mkexpr(rD) ); 2882 2883 if (do_rc && flag_rC) { 2884 set_CR0( mkexpr(rD) ); 2885 } 2886 return True; 2887 } 2888 2889 2890 2891 /* 2892 Integer Compare Instructions 2893 */ 2894 static Bool dis_int_cmp ( UInt theInstr ) 2895 { 2896 /* D-Form, X-Form */ 2897 UChar opc1 = ifieldOPC(theInstr); 2898 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 2899 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) ); 2900 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) ); 2901 UChar rA_addr = ifieldRegA(theInstr); 2902 UInt uimm16 = ifieldUIMM16(theInstr); 2903 UChar rB_addr = ifieldRegB(theInstr); 2904 UInt opc2 = ifieldOPClo10(theInstr); 2905 UChar b0 = ifieldBIT0(theInstr); 2906 2907 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2908 IRExpr *a = getIReg(rA_addr); 2909 IRExpr *b; 2910 2911 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit. 2912 vex_printf("dis_int_cmp(ppc)(flag_L)\n"); 2913 return False; 2914 } 2915 2916 if (b22 != 0) { 2917 vex_printf("dis_int_cmp(ppc)(b22)\n"); 2918 return False; 2919 } 2920 2921 switch (opc1) { 2922 case 0x0B: // cmpi (Compare Immediate, PPC32 p368) 2923 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr, 2924 (Int)extend_s_16to32(uimm16)); 2925 b = mkSzExtendS16( ty, uimm16 ); 2926 if (flag_L == 1) { 2927 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 2928 } else { 2929 a = mkNarrowTo32( ty, a ); 2930 b = mkNarrowTo32( ty, b ); 2931 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b))); 2932 } 2933 putCR0( crfD, getXER_SO() ); 2934 break; 2935 2936 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370) 2937 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16); 2938 b = mkSzImm( ty, uimm16 ); 2939 if (flag_L == 1) { 2940 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 2941 } else { 2942 a = mkNarrowTo32( ty, a ); 2943 b = mkNarrowTo32( ty, b ); 2944 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 2945 } 2946 putCR0( crfD, getXER_SO() ); 2947 break; 2948 2949 /* X Form */ 2950 case 0x1F: 2951 if (b0 != 0) { 2952 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n"); 2953 return False; 2954 } 2955 b = getIReg(rB_addr); 2956 2957 switch (opc2) { 2958 case 0x000: // cmp (Compare, PPC32 p367) 2959 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 2960 /* Comparing a reg with itself produces a result which 2961 doesn't depend on the contents of the reg. Therefore 2962 remove the false dependency, which has been known to cause 2963 memcheck to produce false errors. */ 2964 if (rA_addr == rB_addr) 2965 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 2966 ? mkU64(0) : mkU32(0); 2967 if (flag_L == 1) { 2968 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 2969 } else { 2970 a = mkNarrowTo32( ty, a ); 2971 b = mkNarrowTo32( ty, b ); 2972 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b))); 2973 } 2974 putCR0( crfD, getXER_SO() ); 2975 break; 2976 2977 case 0x020: // cmpl (Compare Logical, PPC32 p369) 2978 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 2979 /* Comparing a reg with itself produces a result which 2980 doesn't depend on the contents of the reg. Therefore 2981 remove the false dependency, which has been known to cause 2982 memcheck to produce false errors. */ 2983 if (rA_addr == rB_addr) 2984 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 2985 ? mkU64(0) : mkU32(0); 2986 if (flag_L == 1) { 2987 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 2988 } else { 2989 a = mkNarrowTo32( ty, a ); 2990 b = mkNarrowTo32( ty, b ); 2991 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 2992 } 2993 putCR0( crfD, getXER_SO() ); 2994 break; 2995 2996 default: 2997 vex_printf("dis_int_cmp(ppc)(opc2)\n"); 2998 return False; 2999 } 3000 break; 3001 3002 default: 3003 vex_printf("dis_int_cmp(ppc)(opc1)\n"); 3004 return False; 3005 } 3006 3007 return True; 3008 } 3009 3010 3011 /* 3012 Integer Logical Instructions 3013 */ 3014 static Bool dis_int_logic ( UInt theInstr ) 3015 { 3016 /* D-Form, X-Form */ 3017 UChar opc1 = ifieldOPC(theInstr); 3018 UChar rS_addr = ifieldRegDS(theInstr); 3019 UChar rA_addr = ifieldRegA(theInstr); 3020 UInt uimm16 = ifieldUIMM16(theInstr); 3021 UChar rB_addr = ifieldRegB(theInstr); 3022 UInt opc2 = ifieldOPClo10(theInstr); 3023 UChar flag_rC = ifieldBIT0(theInstr); 3024 3025 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3026 IRTemp rS = newTemp(ty); 3027 IRTemp rA = newTemp(ty); 3028 IRTemp rB = newTemp(ty); 3029 IRExpr* irx; 3030 Bool do_rc = False; 3031 3032 assign( rS, getIReg(rS_addr) ); 3033 assign( rB, getIReg(rB_addr) ); 3034 3035 switch (opc1) { 3036 case 0x1C: // andi. (AND Immediate, PPC32 p358) 3037 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3038 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 3039 mkSzImm(ty, uimm16)) ); 3040 do_rc = True; // Always record to CR 3041 flag_rC = 1; 3042 break; 3043 3044 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359) 3045 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3046 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 3047 mkSzImm(ty, uimm16 << 16)) ); 3048 do_rc = True; // Always record to CR 3049 flag_rC = 1; 3050 break; 3051 3052 case 0x18: // ori (OR Immediate, PPC32 p497) 3053 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3054 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 3055 mkSzImm(ty, uimm16)) ); 3056 break; 3057 3058 case 0x19: // oris (OR Immediate Shifted, PPC32 p498) 3059 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3060 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 3061 mkSzImm(ty, uimm16 << 16)) ); 3062 break; 3063 3064 case 0x1A: // xori (XOR Immediate, PPC32 p550) 3065 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3066 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 3067 mkSzImm(ty, uimm16)) ); 3068 break; 3069 3070 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551) 3071 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3072 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 3073 mkSzImm(ty, uimm16 << 16)) ); 3074 break; 3075 3076 /* X Form */ 3077 case 0x1F: 3078 do_rc = True; // All below record to CR 3079 3080 switch (opc2) { 3081 case 0x01C: // and (AND, PPC32 p356) 3082 DIP("and%s r%u,r%u,r%u\n", 3083 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3084 assign(rA, binop( mkSzOp(ty, Iop_And8), 3085 mkexpr(rS), mkexpr(rB))); 3086 break; 3087 3088 case 0x03C: // andc (AND with Complement, PPC32 p357) 3089 DIP("andc%s r%u,r%u,r%u\n", 3090 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3091 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 3092 unop( mkSzOp(ty, Iop_Not8), 3093 mkexpr(rB)))); 3094 break; 3095 3096 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371) 3097 IRExpr* lo32; 3098 if (rB_addr!=0) { 3099 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n"); 3100 return False; 3101 } 3102 DIP("cntlzw%s r%u,r%u\n", 3103 flag_rC ? ".":"", rA_addr, rS_addr); 3104 3105 // mode64: count in low word only 3106 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS); 3107 3108 // Iop_Clz32 undefined for arg==0, so deal with that case: 3109 irx = binop(Iop_CmpNE32, lo32, mkU32(0)); 3110 assign(rA, mkWidenFrom32(ty, 3111 IRExpr_Mux0X( unop(Iop_1Uto8, irx), 3112 mkU32(32), 3113 unop(Iop_Clz32, lo32)), 3114 False)); 3115 3116 // TODO: alternatively: assign(rA, verbose_Clz32(rS)); 3117 break; 3118 } 3119 3120 case 0x11C: // eqv (Equivalent, PPC32 p396) 3121 DIP("eqv%s r%u,r%u,r%u\n", 3122 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3123 assign( rA, unop( mkSzOp(ty, Iop_Not8), 3124 binop( mkSzOp(ty, Iop_Xor8), 3125 mkexpr(rS), mkexpr(rB))) ); 3126 break; 3127 3128 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397 3129 if (rB_addr!=0) { 3130 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n"); 3131 return False; 3132 } 3133 DIP("extsb%s r%u,r%u\n", 3134 flag_rC ? ".":"", rA_addr, rS_addr); 3135 if (mode64) 3136 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) ); 3137 else 3138 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) ); 3139 break; 3140 3141 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398) 3142 if (rB_addr!=0) { 3143 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n"); 3144 return False; 3145 } 3146 DIP("extsh%s r%u,r%u\n", 3147 flag_rC ? ".":"", rA_addr, rS_addr); 3148 if (mode64) 3149 assign( rA, unop(Iop_16Sto64, 3150 unop(Iop_64to16, mkexpr(rS))) ); 3151 else 3152 assign( rA, unop(Iop_16Sto32, 3153 unop(Iop_32to16, mkexpr(rS))) ); 3154 break; 3155 3156 case 0x1DC: // nand (NAND, PPC32 p492) 3157 DIP("nand%s r%u,r%u,r%u\n", 3158 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3159 assign( rA, unop( mkSzOp(ty, Iop_Not8), 3160 binop( mkSzOp(ty, Iop_And8), 3161 mkexpr(rS), mkexpr(rB))) ); 3162 break; 3163 3164 case 0x07C: // nor (NOR, PPC32 p494) 3165 DIP("nor%s r%u,r%u,r%u\n", 3166 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3167 assign( rA, unop( mkSzOp(ty, Iop_Not8), 3168 binop( mkSzOp(ty, Iop_Or8), 3169 mkexpr(rS), mkexpr(rB))) ); 3170 break; 3171 3172 case 0x1BC: // or (OR, PPC32 p495) 3173 if ((!flag_rC) && rS_addr == rB_addr) { 3174 DIP("mr r%u,r%u\n", rA_addr, rS_addr); 3175 assign( rA, mkexpr(rS) ); 3176 } else { 3177 DIP("or%s r%u,r%u,r%u\n", 3178 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3179 assign( rA, binop( mkSzOp(ty, Iop_Or8), 3180 mkexpr(rS), mkexpr(rB)) ); 3181 } 3182 break; 3183 3184 case 0x19C: // orc (OR with Complement, PPC32 p496) 3185 DIP("orc%s r%u,r%u,r%u\n", 3186 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3187 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 3188 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB)))); 3189 break; 3190 3191 case 0x13C: // xor (XOR, PPC32 p549) 3192 DIP("xor%s r%u,r%u,r%u\n", 3193 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3194 assign( rA, binop( mkSzOp(ty, Iop_Xor8), 3195 mkexpr(rS), mkexpr(rB)) ); 3196 break; 3197 3198 3199 /* 64bit Integer Logical Instructions */ 3200 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430) 3201 if (rB_addr!=0) { 3202 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n"); 3203 return False; 3204 } 3205 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr); 3206 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS)))); 3207 break; 3208 3209 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401) 3210 if (rB_addr!=0) { 3211 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n"); 3212 return False; 3213 } 3214 DIP("cntlzd%s r%u,r%u\n", 3215 flag_rC ? ".":"", rA_addr, rS_addr); 3216 // Iop_Clz64 undefined for arg==0, so deal with that case: 3217 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0)); 3218 assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx), 3219 mkU64(64), 3220 unop(Iop_Clz64, mkexpr(rS)) )); 3221 // TODO: alternatively: assign(rA, verbose_Clz64(rS)); 3222 break; 3223 3224 case 0x1FC: // cmpb (Power6: compare bytes) 3225 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 3226 3227 if (mode64) 3228 assign( rA, unop( Iop_V128to64, 3229 binop( Iop_CmpEQ8x16, 3230 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ), 3231 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) ) 3232 )) ); 3233 else 3234 assign( rA, unop( Iop_V128to32, 3235 binop( Iop_CmpEQ8x16, 3236 unop( Iop_32UtoV128, mkexpr(rS) ), 3237 unop( Iop_32UtoV128, mkexpr(rB) ) 3238 )) ); 3239 break; 3240 3241 case 0x2DF: { // mftgpr (move floating-point to general purpose register) 3242 IRTemp frB = newTemp(Ity_F64); 3243 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr); 3244 3245 assign( frB, getFReg(rB_addr)); // always F64 3246 if (mode64) 3247 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 3248 else 3249 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) ); 3250 3251 putIReg( rS_addr, mkexpr(rA)); 3252 return True; 3253 } 3254 3255 case 0x25F: { // mffgpr (move floating-point from general purpose register) 3256 IRTemp frA = newTemp(Ity_F64); 3257 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr); 3258 3259 if (mode64) 3260 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) ); 3261 else 3262 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) ); 3263 3264 putFReg( rS_addr, mkexpr(frA)); 3265 return True; 3266 } 3267 3268 default: 3269 vex_printf("dis_int_logic(ppc)(opc2)\n"); 3270 return False; 3271 } 3272 break; 3273 3274 default: 3275 vex_printf("dis_int_logic(ppc)(opc1)\n"); 3276 return False; 3277 } 3278 3279 putIReg( rA_addr, mkexpr(rA) ); 3280 3281 if (do_rc && flag_rC) { 3282 set_CR0( mkexpr(rA) ); 3283 } 3284 return True; 3285 } 3286 3287 /* 3288 Integer Parity Instructions 3289 */ 3290 static Bool dis_int_parity ( UInt theInstr ) 3291 { 3292 /* X-Form */ 3293 UChar opc1 = ifieldOPC(theInstr); 3294 UChar rS_addr = ifieldRegDS(theInstr); 3295 UChar rA_addr = ifieldRegA(theInstr); 3296 UChar rB_addr = ifieldRegB(theInstr); 3297 UInt opc2 = ifieldOPClo10(theInstr); 3298 UChar b0 = ifieldBIT0(theInstr); 3299 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3300 3301 IRTemp rS = newTemp(ty); 3302 IRTemp rA = newTemp(ty); 3303 IRTemp iTot1 = newTemp(Ity_I32); 3304 IRTemp iTot2 = newTemp(Ity_I32); 3305 IRTemp iTot3 = newTemp(Ity_I32); 3306 IRTemp iTot4 = newTemp(Ity_I32); 3307 IRTemp iTot5 = newTemp(Ity_I32); 3308 IRTemp iTot6 = newTemp(Ity_I32); 3309 IRTemp iTot7 = newTemp(Ity_I32); 3310 IRTemp iTot8 = newTemp(Ity_I32); 3311 IRTemp rS1 = newTemp(ty); 3312 IRTemp rS2 = newTemp(ty); 3313 IRTemp rS3 = newTemp(ty); 3314 IRTemp rS4 = newTemp(ty); 3315 IRTemp rS5 = newTemp(ty); 3316 IRTemp rS6 = newTemp(ty); 3317 IRTemp rS7 = newTemp(ty); 3318 IRTemp iHi = newTemp(Ity_I32); 3319 IRTemp iLo = newTemp(Ity_I32); 3320 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1); 3321 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32); 3322 3323 if (opc1 != 0x1f || rB_addr || b0) { 3324 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n"); 3325 return False; 3326 } 3327 3328 assign( rS, getIReg(rS_addr) ); 3329 3330 switch (opc2) { 3331 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320) 3332 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr); 3333 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 3334 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 3335 assign( iTot2, binop(Iop_Add32, 3336 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 3337 mkexpr(iTot1)) ); 3338 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 3339 assign( iTot3, binop(Iop_Add32, 3340 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 3341 mkexpr(iTot2)) ); 3342 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 3343 assign( iTot4, binop(Iop_Add32, 3344 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 3345 mkexpr(iTot3)) ); 3346 if (mode64) { 3347 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 3348 assign( iTot5, binop(Iop_Add32, 3349 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))), 3350 mkexpr(iTot4)) ); 3351 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 3352 assign( iTot6, binop(Iop_Add32, 3353 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 3354 mkexpr(iTot5)) ); 3355 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 3356 assign( iTot7, binop(Iop_Add32, 3357 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 3358 mkexpr(iTot6)) ); 3359 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) ); 3360 assign( iTot8, binop(Iop_Add32, 3361 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 3362 mkexpr(iTot7)) ); 3363 assign( rA, unop(Iop_32Uto64, 3364 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) ); 3365 } else 3366 assign( rA, mkexpr(iTot4) ); 3367 3368 break; 3369 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320) 3370 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 3371 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 3372 assign( iTot2, binop(Iop_Add32, 3373 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 3374 mkexpr(iTot1)) ); 3375 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 3376 assign( iTot3, binop(Iop_Add32, 3377 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 3378 mkexpr(iTot2)) ); 3379 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 3380 assign( iTot4, binop(Iop_Add32, 3381 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 3382 mkexpr(iTot3)) ); 3383 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) ); 3384 3385 if (mode64) { 3386 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 3387 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) ); 3388 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 3389 assign( iTot6, binop(Iop_Add32, 3390 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 3391 mkexpr(iTot5)) ); 3392 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 3393 assign( iTot7, binop(Iop_Add32, 3394 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 3395 mkexpr(iTot6)) ); 3396 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8))); 3397 assign( iTot8, binop(Iop_Add32, 3398 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 3399 mkexpr(iTot7)) ); 3400 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ), 3401 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) ); 3402 } else 3403 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) ); 3404 break; 3405 default: 3406 vex_printf("dis_int_parity(ppc)(opc2)\n"); 3407 return False; 3408 } 3409 3410 putIReg( rA_addr, mkexpr(rA) ); 3411 3412 return True; 3413 } 3414 3415 3416 /* 3417 Integer Rotate Instructions 3418 */ 3419 static Bool dis_int_rot ( UInt theInstr ) 3420 { 3421 /* M-Form, MDS-Form */ 3422 UChar opc1 = ifieldOPC(theInstr); 3423 UChar rS_addr = ifieldRegDS(theInstr); 3424 UChar rA_addr = ifieldRegA(theInstr); 3425 UChar rB_addr = ifieldRegB(theInstr); 3426 UChar sh_imm = rB_addr; 3427 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) ); 3428 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) ); 3429 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) ); 3430 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) ); 3431 UChar b1 = ifieldBIT1(theInstr); 3432 UChar flag_rC = ifieldBIT0(theInstr); 3433 3434 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3435 IRTemp rS = newTemp(ty); 3436 IRTemp rA = newTemp(ty); 3437 IRTemp rB = newTemp(ty); 3438 IRTemp rot = newTemp(ty); 3439 IRExpr *r; 3440 UInt mask32; 3441 ULong mask64; 3442 3443 assign( rS, getIReg(rS_addr) ); 3444 assign( rB, getIReg(rB_addr) ); 3445 3446 switch (opc1) { 3447 case 0x14: { 3448 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500) 3449 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 3450 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 3451 if (mode64) { 3452 // tmp32 = (ROTL(rS_Lo32, Imm) 3453 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64) 3454 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 3455 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 3456 r = unop(Iop_32Uto64, r); 3457 assign( rot, binop(Iop_Or64, r, 3458 binop(Iop_Shl64, r, mkU8(32))) ); 3459 assign( rA, 3460 binop(Iop_Or64, 3461 binop(Iop_And64, mkexpr(rot), mkU64(mask64)), 3462 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) ); 3463 } 3464 else { 3465 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask); 3466 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 3467 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 3468 assign( rA, 3469 binop(Iop_Or32, 3470 binop(Iop_And32, mkU32(mask32), r), 3471 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) ); 3472 } 3473 break; 3474 } 3475 3476 case 0x15: { 3477 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501) 3478 vassert(MaskBeg < 32); 3479 vassert(MaskEnd < 32); 3480 vassert(sh_imm < 32); 3481 3482 if (mode64) { 3483 IRTemp rTmp = newTemp(Ity_I64); 3484 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 3485 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 3486 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 3487 // tmp32 = (ROTL(rS_Lo32, Imm) 3488 // rA = ((tmp32 || tmp32) & mask64) 3489 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 3490 r = unop(Iop_32Uto64, r); 3491 assign( rTmp, r ); 3492 r = NULL; 3493 assign( rot, binop(Iop_Or64, mkexpr(rTmp), 3494 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) ); 3495 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 3496 } 3497 else { 3498 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) { 3499 /* Special-case the ,n,0,31-n form as that is just n-bit 3500 shift left, PPC32 p501 */ 3501 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 3502 rA_addr, rS_addr, sh_imm); 3503 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) ); 3504 } 3505 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) { 3506 /* Special-case the ,32-n,n,31 form as that is just n-bit 3507 unsigned shift right, PPC32 p501 */ 3508 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 3509 rA_addr, rS_addr, MaskBeg); 3510 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) ); 3511 } 3512 else { 3513 /* General case. */ 3514 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 3515 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 3516 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 3517 // rA = ROTL(rS, Imm) & mask 3518 assign( rA, binop(Iop_And32, 3519 ROTL(mkexpr(rS), mkU8(sh_imm)), 3520 mkU32(mask32)) ); 3521 } 3522 } 3523 break; 3524 } 3525 3526 case 0x17: { 3527 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503 3528 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"", 3529 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd); 3530 if (mode64) { 3531 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 3532 /* weird insn alert! 3533 tmp32 = (ROTL(rS_Lo32, rB[0-4]) 3534 rA = ((tmp32 || tmp32) & mask64) 3535 */ 3536 // note, ROTL does the masking, so we don't do it here 3537 r = ROTL( unop(Iop_64to32, mkexpr(rS)), 3538 unop(Iop_64to8, mkexpr(rB)) ); 3539 r = unop(Iop_32Uto64, r); 3540 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)))); 3541 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 3542 } else { 3543 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 3544 // rA = ROTL(rS, rB[0-4]) & mask 3545 // note, ROTL does the masking, so we don't do it here 3546 assign( rA, binop(Iop_And32, 3547 ROTL(mkexpr(rS), 3548 unop(Iop_32to8, mkexpr(rB))), 3549 mkU32(mask32)) ); 3550 } 3551 break; 3552 } 3553 3554 /* 64bit Integer Rotates */ 3555 case 0x1E: { 3556 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1); 3557 sh_imm |= b1 << 5; 3558 3559 vassert( msk_imm < 64 ); 3560 vassert( sh_imm < 64 ); 3561 3562 switch (opc2) { 3563 case 0x4: { 3564 /* r = ROTL64( rS, rB_lo6) */ 3565 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) ); 3566 3567 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555) 3568 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 3569 rA_addr, rS_addr, rB_addr, msk_imm); 3570 // note, ROTL does the masking, so we don't do it here 3571 mask64 = MASK64(0, 63-msk_imm); 3572 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 3573 break; 3574 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556) 3575 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 3576 rA_addr, rS_addr, rB_addr, msk_imm); 3577 mask64 = MASK64(63-msk_imm, 63); 3578 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 3579 break; 3580 } 3581 break; 3582 } 3583 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557) 3584 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 3585 rA_addr, rS_addr, sh_imm, msk_imm); 3586 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 3587 mask64 = MASK64(sh_imm, 63-msk_imm); 3588 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 3589 break; 3590 // later: deal with special case: (msk_imm==0) => SHL(sh_imm) 3591 /* 3592 Hmm... looks like this'll do the job more simply: 3593 r = SHL(rS, sh_imm) 3594 m = ~(1 << (63-msk_imm)) 3595 assign(rA, r & m); 3596 */ 3597 3598 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558) 3599 if (mode64 3600 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) { 3601 /* special-case the ,64-n,n form as that is just 3602 unsigned shift-right by n */ 3603 DIP("srdi%s r%u,r%u,%u\n", 3604 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm); 3605 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) ); 3606 } else { 3607 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 3608 rA_addr, rS_addr, sh_imm, msk_imm); 3609 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 3610 mask64 = MASK64(0, 63-msk_imm); 3611 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 3612 } 3613 break; 3614 3615 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559) 3616 if (mode64 3617 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) { 3618 /* special-case the ,n,63-n form as that is just 3619 shift-left by n */ 3620 DIP("sldi%s r%u,r%u,%u\n", 3621 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 3622 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) ); 3623 } else { 3624 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 3625 rA_addr, rS_addr, sh_imm, msk_imm); 3626 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 3627 mask64 = MASK64(63-msk_imm, 63); 3628 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 3629 } 3630 break; 3631 3632 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560) 3633 IRTemp rA_orig = newTemp(ty); 3634 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 3635 rA_addr, rS_addr, sh_imm, msk_imm); 3636 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 3637 mask64 = MASK64(sh_imm, 63-msk_imm); 3638 assign( rA_orig, getIReg(rA_addr) ); 3639 assign( rA, binop(Iop_Or64, 3640 binop(Iop_And64, mkU64(mask64), r), 3641 binop(Iop_And64, mkU64(~mask64), 3642 mkexpr(rA_orig))) ); 3643 break; 3644 } 3645 default: 3646 vex_printf("dis_int_rot(ppc)(opc2)\n"); 3647 return False; 3648 } 3649 break; 3650 } 3651 3652 default: 3653 vex_printf("dis_int_rot(ppc)(opc1)\n"); 3654 return False; 3655 } 3656 3657 putIReg( rA_addr, mkexpr(rA) ); 3658 3659 if (flag_rC) { 3660 set_CR0( mkexpr(rA) ); 3661 } 3662 return True; 3663 } 3664 3665 3666 /* 3667 Integer Load Instructions 3668 */ 3669 static Bool dis_int_load ( UInt theInstr ) 3670 { 3671 /* D-Form, X-Form, DS-Form */ 3672 UChar opc1 = ifieldOPC(theInstr); 3673 UChar rD_addr = ifieldRegDS(theInstr); 3674 UChar rA_addr = ifieldRegA(theInstr); 3675 UInt uimm16 = ifieldUIMM16(theInstr); 3676 UChar rB_addr = ifieldRegB(theInstr); 3677 UInt opc2 = ifieldOPClo10(theInstr); 3678 UChar b1 = ifieldBIT1(theInstr); 3679 UChar b0 = ifieldBIT0(theInstr); 3680 3681 Int simm16 = extend_s_16to32(uimm16); 3682 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3683 IRTemp EA = newTemp(ty); 3684 IRExpr* val; 3685 3686 switch (opc1) { 3687 case 0x1F: // register offset 3688 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 3689 break; 3690 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off 3691 // lowest 2 bits of immediate before forming EA 3692 simm16 = simm16 & 0xFFFFFFFC; 3693 default: // immediate offset 3694 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 3695 break; 3696 } 3697 3698 switch (opc1) { 3699 case 0x22: // lbz (Load B & Zero, PPC32 p433) 3700 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 3701 val = loadBE(Ity_I8, mkexpr(EA)); 3702 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 3703 break; 3704 3705 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434) 3706 if (rA_addr == 0 || rA_addr == rD_addr) { 3707 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n"); 3708 return False; 3709 } 3710 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 3711 val = loadBE(Ity_I8, mkexpr(EA)); 3712 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 3713 putIReg( rA_addr, mkexpr(EA) ); 3714 break; 3715 3716 case 0x2A: // lha (Load HW Alg, PPC32 p445) 3717 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 3718 val = loadBE(Ity_I16, mkexpr(EA)); 3719 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 3720 break; 3721 3722 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446) 3723 if (rA_addr == 0 || rA_addr == rD_addr) { 3724 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n"); 3725 return False; 3726 } 3727 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 3728 val = loadBE(Ity_I16, mkexpr(EA)); 3729 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 3730 putIReg( rA_addr, mkexpr(EA) ); 3731 break; 3732 3733 case 0x28: // lhz (Load HW & Zero, PPC32 p450) 3734 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 3735 val = loadBE(Ity_I16, mkexpr(EA)); 3736 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 3737 break; 3738 3739 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451) 3740 if (rA_addr == 0 || rA_addr == rD_addr) { 3741 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n"); 3742 return False; 3743 } 3744 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 3745 val = loadBE(Ity_I16, mkexpr(EA)); 3746 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 3747 putIReg( rA_addr, mkexpr(EA) ); 3748 break; 3749 3750 case 0x20: // lwz (Load W & Zero, PPC32 p460) 3751 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 3752 val = loadBE(Ity_I32, mkexpr(EA)); 3753 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 3754 break; 3755 3756 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461)) 3757 if (rA_addr == 0 || rA_addr == rD_addr) { 3758 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n"); 3759 return False; 3760 } 3761 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 3762 val = loadBE(Ity_I32, mkexpr(EA)); 3763 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 3764 putIReg( rA_addr, mkexpr(EA) ); 3765 break; 3766 3767 /* X Form */ 3768 case 0x1F: 3769 if (b0 != 0) { 3770 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n"); 3771 return False; 3772 } 3773 3774 switch (opc2) { 3775 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435) 3776 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3777 if (rA_addr == 0 || rA_addr == rD_addr) { 3778 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 3779 return False; 3780 } 3781 val = loadBE(Ity_I8, mkexpr(EA)); 3782 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 3783 putIReg( rA_addr, mkexpr(EA) ); 3784 break; 3785 3786 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436) 3787 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3788 val = loadBE(Ity_I8, mkexpr(EA)); 3789 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 3790 break; 3791 3792 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447) 3793 if (rA_addr == 0 || rA_addr == rD_addr) { 3794 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n"); 3795 return False; 3796 } 3797 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3798 val = loadBE(Ity_I16, mkexpr(EA)); 3799 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 3800 putIReg( rA_addr, mkexpr(EA) ); 3801 break; 3802 3803 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448) 3804 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3805 val = loadBE(Ity_I16, mkexpr(EA)); 3806 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 3807 break; 3808 3809 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452) 3810 if (rA_addr == 0 || rA_addr == rD_addr) { 3811 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n"); 3812 return False; 3813 } 3814 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3815 val = loadBE(Ity_I16, mkexpr(EA)); 3816 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 3817 putIReg( rA_addr, mkexpr(EA) ); 3818 break; 3819 3820 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453) 3821 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3822 val = loadBE(Ity_I16, mkexpr(EA)); 3823 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 3824 break; 3825 3826 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462) 3827 if (rA_addr == 0 || rA_addr == rD_addr) { 3828 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 3829 return False; 3830 } 3831 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3832 val = loadBE(Ity_I32, mkexpr(EA)); 3833 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 3834 putIReg( rA_addr, mkexpr(EA) ); 3835 break; 3836 3837 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463) 3838 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3839 val = loadBE(Ity_I32, mkexpr(EA)); 3840 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 3841 break; 3842 3843 3844 /* 64bit Loads */ 3845 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475) 3846 if (rA_addr == 0 || rA_addr == rD_addr) { 3847 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n"); 3848 return False; 3849 } 3850 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3851 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 3852 putIReg( rA_addr, mkexpr(EA) ); 3853 break; 3854 3855 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476) 3856 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3857 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 3858 break; 3859 3860 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501) 3861 if (rA_addr == 0 || rA_addr == rD_addr) { 3862 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n"); 3863 return False; 3864 } 3865 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3866 putIReg( rD_addr, 3867 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 3868 putIReg( rA_addr, mkexpr(EA) ); 3869 break; 3870 3871 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502) 3872 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 3873 putIReg( rD_addr, 3874 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 3875 break; 3876 3877 default: 3878 vex_printf("dis_int_load(ppc)(opc2)\n"); 3879 return False; 3880 } 3881 break; 3882 3883 /* DS Form - 64bit Loads. In each case EA will have been formed 3884 with the lowest 2 bits masked off the immediate offset. */ 3885 case 0x3A: 3886 switch ((b1<<1) | b0) { 3887 case 0x0: // ld (Load DWord, PPC64 p472) 3888 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 3889 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 3890 break; 3891 3892 case 0x1: // ldu (Load DWord, Update, PPC64 p474) 3893 if (rA_addr == 0 || rA_addr == rD_addr) { 3894 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n"); 3895 return False; 3896 } 3897 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 3898 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 3899 putIReg( rA_addr, mkexpr(EA) ); 3900 break; 3901 3902 case 0x2: // lwa (Load Word Alg, PPC64 p499) 3903 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 3904 putIReg( rD_addr, 3905 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 3906 break; 3907 3908 default: 3909 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 3910 return False; 3911 } 3912 break; 3913 3914 default: 3915 vex_printf("dis_int_load(ppc)(opc1)\n"); 3916 return False; 3917 } 3918 return True; 3919 } 3920 3921 3922 3923 /* 3924 Integer Store Instructions 3925 */ 3926 static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi ) 3927 { 3928 /* D-Form, X-Form, DS-Form */ 3929 UChar opc1 = ifieldOPC(theInstr); 3930 UInt rS_addr = ifieldRegDS(theInstr); 3931 UInt rA_addr = ifieldRegA(theInstr); 3932 UInt uimm16 = ifieldUIMM16(theInstr); 3933 UInt rB_addr = ifieldRegB(theInstr); 3934 UInt opc2 = ifieldOPClo10(theInstr); 3935 UChar b1 = ifieldBIT1(theInstr); 3936 UChar b0 = ifieldBIT0(theInstr); 3937 3938 Int simm16 = extend_s_16to32(uimm16); 3939 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3940 IRTemp rS = newTemp(ty); 3941 IRTemp rB = newTemp(ty); 3942 IRTemp EA = newTemp(ty); 3943 3944 assign( rB, getIReg(rB_addr) ); 3945 assign( rS, getIReg(rS_addr) ); 3946 3947 switch (opc1) { 3948 case 0x1F: // register offset 3949 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 3950 break; 3951 case 0x3E: // immediate offset: 64bit: std/stdu: mask off 3952 // lowest 2 bits of immediate before forming EA 3953 simm16 = simm16 & 0xFFFFFFFC; 3954 default: // immediate offset 3955 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 3956 break; 3957 } 3958 3959 switch (opc1) { 3960 case 0x26: // stb (Store B, PPC32 p509) 3961 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 3962 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 3963 break; 3964 3965 case 0x27: // stbu (Store B, Update, PPC32 p510) 3966 if (rA_addr == 0 ) { 3967 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n"); 3968 return False; 3969 } 3970 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 3971 putIReg( rA_addr, mkexpr(EA) ); 3972 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 3973 break; 3974 3975 case 0x2C: // sth (Store HW, PPC32 p522) 3976 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 3977 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 3978 break; 3979 3980 case 0x2D: // sthu (Store HW, Update, PPC32 p524) 3981 if (rA_addr == 0) { 3982 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n"); 3983 return False; 3984 } 3985 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 3986 putIReg( rA_addr, mkexpr(EA) ); 3987 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 3988 break; 3989 3990 case 0x24: // stw (Store W, PPC32 p530) 3991 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 3992 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 3993 break; 3994 3995 case 0x25: // stwu (Store W, Update, PPC32 p534) 3996 if (rA_addr == 0) { 3997 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n"); 3998 return False; 3999 } 4000 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4001 putIReg( rA_addr, mkexpr(EA) ); 4002 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 4003 break; 4004 4005 /* X Form : all these use EA_indexed */ 4006 case 0x1F: 4007 if (b0 != 0) { 4008 vex_printf("dis_int_store(ppc)(0x1F,b0)\n"); 4009 return False; 4010 } 4011 4012 switch (opc2) { 4013 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511) 4014 if (rA_addr == 0) { 4015 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n"); 4016 return False; 4017 } 4018 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4019 putIReg( rA_addr, mkexpr(EA) ); 4020 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 4021 break; 4022 4023 case 0x0D7: // stbx (Store B Indexed, PPC32 p512) 4024 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4025 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 4026 break; 4027 4028 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525) 4029 if (rA_addr == 0) { 4030 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n"); 4031 return False; 4032 } 4033 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4034 putIReg( rA_addr, mkexpr(EA) ); 4035 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 4036 break; 4037 4038 case 0x197: // sthx (Store HW Indexed, PPC32 p526) 4039 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4040 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 4041 break; 4042 4043 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535) 4044 if (rA_addr == 0) { 4045 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n"); 4046 return False; 4047 } 4048 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4049 putIReg( rA_addr, mkexpr(EA) ); 4050 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 4051 break; 4052 4053 case 0x097: // stwx (Store W Indexed, PPC32 p536) 4054 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4055 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 4056 break; 4057 4058 4059 /* 64bit Stores */ 4060 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584) 4061 if (rA_addr == 0) { 4062 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n"); 4063 return False; 4064 } 4065 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4066 putIReg( rA_addr, mkexpr(EA) ); 4067 storeBE( mkexpr(EA), mkexpr(rS) ); 4068 break; 4069 4070 case 0x095: // stdx (Store DWord Indexed, PPC64 p585) 4071 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4072 storeBE( mkexpr(EA), mkexpr(rS) ); 4073 break; 4074 4075 default: 4076 vex_printf("dis_int_store(ppc)(opc2)\n"); 4077 return False; 4078 } 4079 break; 4080 4081 /* DS Form - 64bit Stores. In each case EA will have been formed 4082 with the lowest 2 bits masked off the immediate offset. */ 4083 case 0x3E: 4084 switch ((b1<<1) | b0) { 4085 case 0x0: // std (Store DWord, PPC64 p580) 4086 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4087 storeBE( mkexpr(EA), mkexpr(rS) ); 4088 break; 4089 4090 case 0x1: // stdu (Store DWord, Update, PPC64 p583) 4091 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4092 putIReg( rA_addr, mkexpr(EA) ); 4093 storeBE( mkexpr(EA), mkexpr(rS) ); 4094 break; 4095 4096 default: 4097 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 4098 return False; 4099 } 4100 break; 4101 4102 default: 4103 vex_printf("dis_int_store(ppc)(opc1)\n"); 4104 return False; 4105 } 4106 return True; 4107 } 4108 4109 4110 4111 /* 4112 Integer Load/Store Multiple Instructions 4113 */ 4114 static Bool dis_int_ldst_mult ( UInt theInstr ) 4115 { 4116 /* D-Form */ 4117 UChar opc1 = ifieldOPC(theInstr); 4118 UChar rD_addr = ifieldRegDS(theInstr); 4119 UChar rS_addr = rD_addr; 4120 UChar rA_addr = ifieldRegA(theInstr); 4121 UInt uimm16 = ifieldUIMM16(theInstr); 4122 4123 Int simm16 = extend_s_16to32(uimm16); 4124 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4125 IRTemp EA = newTemp(ty); 4126 UInt r = 0; 4127 UInt ea_off = 0; 4128 IRExpr* irx_addr; 4129 4130 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4131 4132 switch (opc1) { 4133 case 0x2E: // lmw (Load Multiple Word, PPC32 p454) 4134 if (rA_addr >= rD_addr) { 4135 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n"); 4136 return False; 4137 } 4138 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4139 for (r = rD_addr; r <= 31; r++) { 4140 irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off)); 4141 putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ), 4142 False) ); 4143 ea_off += 4; 4144 } 4145 break; 4146 4147 case 0x2F: // stmw (Store Multiple Word, PPC32 p527) 4148 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4149 for (r = rS_addr; r <= 31; r++) { 4150 irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off)); 4151 storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) ); 4152 ea_off += 4; 4153 } 4154 break; 4155 4156 default: 4157 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n"); 4158 return False; 4159 } 4160 return True; 4161 } 4162 4163 4164 4165 /* 4166 Integer Load/Store String Instructions 4167 */ 4168 static 4169 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 4170 IRTemp EA, // EA 4171 Int rD, // first dst register 4172 Int maxBytes ) // 32 or 128 4173 { 4174 Int i, shift = 24; 4175 IRExpr* e_nbytes = mkexpr(tNBytes); 4176 IRExpr* e_EA = mkexpr(EA); 4177 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4178 4179 vassert(rD >= 0 && rD < 32); 4180 rD--; if (rD < 0) rD = 31; 4181 4182 for (i = 0; i < maxBytes; i++) { 4183 /* if (nBytes < (i+1)) goto NIA; */ 4184 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 4185 Ijk_Boring, 4186 mkSzConst( ty, nextInsnAddr()) )); 4187 /* when crossing into a new dest register, set it to zero. */ 4188 if ((i % 4) == 0) { 4189 rD++; if (rD == 32) rD = 0; 4190 putIReg(rD, mkSzImm(ty, 0)); 4191 shift = 24; 4192 } 4193 /* rD |= (8Uto32(*(EA+i))) << shift */ 4194 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 4195 putIReg( 4196 rD, 4197 mkWidenFrom32( 4198 ty, 4199 binop( 4200 Iop_Or32, 4201 mkNarrowTo32(ty, getIReg(rD)), 4202 binop( 4203 Iop_Shl32, 4204 unop( 4205 Iop_8Uto32, 4206 loadBE(Ity_I8, 4207 binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i))) 4208 ), 4209 mkU8(toUChar(shift)) 4210 ) 4211 ), 4212 /*Signed*/False 4213 ) 4214 ); 4215 shift -= 8; 4216 } 4217 } 4218 4219 static 4220 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 4221 IRTemp EA, // EA 4222 Int rS, // first src register 4223 Int maxBytes ) // 32 or 128 4224 { 4225 Int i, shift = 24; 4226 IRExpr* e_nbytes = mkexpr(tNBytes); 4227 IRExpr* e_EA = mkexpr(EA); 4228 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4229 4230 vassert(rS >= 0 && rS < 32); 4231 rS--; if (rS < 0) rS = 31; 4232 4233 for (i = 0; i < maxBytes; i++) { 4234 /* if (nBytes < (i+1)) goto NIA; */ 4235 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 4236 Ijk_Boring, 4237 mkSzConst( ty, nextInsnAddr() ) )); 4238 /* check for crossing into a new src register. */ 4239 if ((i % 4) == 0) { 4240 rS++; if (rS == 32) rS = 0; 4241 shift = 24; 4242 } 4243 /* *(EA+i) = 32to8(rS >> shift) */ 4244 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 4245 storeBE( 4246 binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)), 4247 unop(Iop_32to8, 4248 binop(Iop_Shr32, 4249 mkNarrowTo32(ty, getIReg(rS)), 4250 mkU8(toUChar(shift)))) 4251 ); 4252 shift -= 8; 4253 } 4254 } 4255 4256 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) 4257 { 4258 /* X-Form */ 4259 UChar opc1 = ifieldOPC(theInstr); 4260 UChar rD_addr = ifieldRegDS(theInstr); 4261 UChar rS_addr = rD_addr; 4262 UChar rA_addr = ifieldRegA(theInstr); 4263 UChar rB_addr = ifieldRegB(theInstr); 4264 UChar NumBytes = rB_addr; 4265 UInt opc2 = ifieldOPClo10(theInstr); 4266 UChar b0 = ifieldBIT0(theInstr); 4267 4268 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4269 IRTemp t_EA = newTemp(ty); 4270 IRTemp t_nbytes = IRTemp_INVALID; 4271 4272 *stopHere = False; 4273 4274 if (opc1 != 0x1F || b0 != 0) { 4275 vex_printf("dis_int_ldst_str(ppc)(opc1)\n"); 4276 return False; 4277 } 4278 4279 switch (opc2) { 4280 case 0x255: // lswi (Load String Word Immediate, PPC32 p455) 4281 /* NB: does not reject the case where RA is in the range of 4282 registers to be loaded. It should. */ 4283 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes); 4284 assign( t_EA, ea_rAor0(rA_addr) ); 4285 if (NumBytes == 8 && !mode64) { 4286 /* Special case hack */ 4287 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */ 4288 putIReg( rD_addr, 4289 loadBE(Ity_I32, mkexpr(t_EA)) ); 4290 putIReg( (rD_addr+1) % 32, 4291 loadBE(Ity_I32, 4292 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) ); 4293 } else { 4294 t_nbytes = newTemp(Ity_I32); 4295 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 4296 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 4297 *stopHere = True; 4298 } 4299 return True; 4300 4301 case 0x215: // lswx (Load String Word Indexed, PPC32 p456) 4302 /* NB: does not reject the case where RA is in the range of 4303 registers to be loaded. It should. Although considering 4304 that that can only be detected at run time, it's not easy to 4305 do so. */ 4306 if (rD_addr == rA_addr || rD_addr == rB_addr) 4307 return False; 4308 if (rD_addr == 0 && rA_addr == 0) 4309 return False; 4310 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4311 t_nbytes = newTemp(Ity_I32); 4312 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 4313 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 4314 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 ); 4315 *stopHere = True; 4316 return True; 4317 4318 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528) 4319 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes); 4320 assign( t_EA, ea_rAor0(rA_addr) ); 4321 if (NumBytes == 8 && !mode64) { 4322 /* Special case hack */ 4323 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */ 4324 storeBE( mkexpr(t_EA), 4325 getIReg(rD_addr) ); 4326 storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)), 4327 getIReg((rD_addr+1) % 32) ); 4328 } else { 4329 t_nbytes = newTemp(Ity_I32); 4330 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 4331 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 4332 *stopHere = True; 4333 } 4334 return True; 4335 4336 case 0x295: // stswx (Store String Word Indexed, PPC32 p529) 4337 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4338 t_nbytes = newTemp(Ity_I32); 4339 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 4340 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 4341 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 ); 4342 *stopHere = True; 4343 return True; 4344 4345 default: 4346 vex_printf("dis_int_ldst_str(ppc)(opc2)\n"); 4347 return False; 4348 } 4349 return True; 4350 } 4351 4352 4353 /* ------------------------------------------------------------------ 4354 Integer Branch Instructions 4355 ------------------------------------------------------------------ */ 4356 4357 /* 4358 Branch helper function 4359 ok = BO[2] | ((CTR[0] != 0) ^ BO[1]) 4360 Returns an I32 which is 0x00000000 if the ctr condition failed 4361 and 0xFFFFFFFF otherwise. 4362 */ 4363 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO ) 4364 { 4365 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4366 IRTemp ok = newTemp(Ity_I32); 4367 4368 if ((BO >> 2) & 1) { // independent of ctr 4369 assign( ok, mkU32(0xFFFFFFFF) ); 4370 } else { 4371 if ((BO >> 1) & 1) { // ctr == 0 ? 4372 assign( ok, unop( Iop_1Sto32, 4373 binop( mkSzOp(ty, Iop_CmpEQ8), 4374 getGST( PPC_GST_CTR ), 4375 mkSzImm(ty,0))) ); 4376 } else { // ctr != 0 ? 4377 assign( ok, unop( Iop_1Sto32, 4378 binop( mkSzOp(ty, Iop_CmpNE8), 4379 getGST( PPC_GST_CTR ), 4380 mkSzImm(ty,0))) ); 4381 } 4382 } 4383 return mkexpr(ok); 4384 } 4385 4386 4387 /* 4388 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3]) 4389 Returns an I32 which is either 0 if the condition failed or 4390 some arbitrary nonzero value otherwise. */ 4391 4392 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) 4393 { 4394 Int where; 4395 IRTemp res = newTemp(Ity_I32); 4396 IRTemp cr_bi = newTemp(Ity_I32); 4397 4398 if ((BO >> 4) & 1) { 4399 assign( res, mkU32(1) ); 4400 } else { 4401 // ok = (CR[BI] == BO[3]) Note, the following relies on 4402 // getCRbit_anywhere returning a value which 4403 // is either zero or has exactly 1 bit set. 4404 assign( cr_bi, getCRbit_anywhere( BI, &where ) ); 4405 4406 if ((BO >> 3) & 1) { 4407 /* We can use cr_bi as-is. */ 4408 assign( res, mkexpr(cr_bi) ); 4409 } else { 4410 /* We have to invert the sense of the information held in 4411 cr_bi. For that we need to know which bit 4412 getCRbit_anywhere regards as significant. */ 4413 assign( res, binop(Iop_Xor32, mkexpr(cr_bi), 4414 mkU32(1<<where)) ); 4415 } 4416 } 4417 return mkexpr(res); 4418 } 4419 4420 4421 /* 4422 Integer Branch Instructions 4423 */ 4424 static Bool dis_branch ( UInt theInstr, 4425 VexAbiInfo* vbi, 4426 /*OUT*/DisResult* dres, 4427 Bool (*resteerOkFn)(void*,Addr64), 4428 void* callback_opaque ) 4429 { 4430 UChar opc1 = ifieldOPC(theInstr); 4431 UChar BO = ifieldRegDS(theInstr); 4432 UChar BI = ifieldRegA(theInstr); 4433 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */ 4434 UChar b11to15 = ifieldRegB(theInstr); 4435 UInt opc2 = ifieldOPClo10(theInstr); 4436 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */ 4437 UChar flag_AA = ifieldBIT1(theInstr); 4438 UChar flag_LK = ifieldBIT0(theInstr); 4439 4440 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4441 Addr64 tgt = 0; 4442 Int BD = extend_s_16to32(BD_u16); 4443 IRTemp do_branch = newTemp(Ity_I32); 4444 IRTemp ctr_ok = newTemp(Ity_I32); 4445 IRTemp cond_ok = newTemp(Ity_I32); 4446 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr()); 4447 IRConst* c_nia = mkSzConst(ty, nextInsnAddr()); 4448 IRTemp lr_old = newTemp(ty); 4449 4450 /* Hack to pass through code that just wants to read the PC */ 4451 if (theInstr == 0x429F0005) { 4452 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI); 4453 putGST( PPC_GST_LR, e_nia ); 4454 return True; 4455 } 4456 4457 /* The default what-next. Individual cases can override it. */ 4458 dres->whatNext = Dis_StopHere; 4459 4460 switch (opc1) { 4461 case 0x12: // b (Branch, PPC32 p360) 4462 if (flag_AA) { 4463 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) ); 4464 } else { 4465 tgt = mkSzAddr( ty, guest_CIA_curr_instr + 4466 (Long)extend_s_26to64(LI_u26) ); 4467 } 4468 if (mode64) { 4469 DIP("b%s%s 0x%llx\n", 4470 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt); 4471 } else { 4472 DIP("b%s%s 0x%x\n", 4473 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt); 4474 } 4475 4476 if (flag_LK) { 4477 putGST( PPC_GST_LR, e_nia ); 4478 if (vbi->guest_ppc_zap_RZ_at_bl 4479 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) { 4480 IRTemp t_tgt = newTemp(ty); 4481 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) ); 4482 make_redzone_AbiHint( vbi, t_tgt, 4483 "branch-and-link (unconditional call)" ); 4484 } 4485 } 4486 4487 if (resteerOkFn( callback_opaque, tgt )) { 4488 dres->whatNext = Dis_ResteerU; 4489 dres->continueAt = tgt; 4490 } else { 4491 irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring; 4492 irsb->next = mkSzImm(ty, tgt); 4493 } 4494 break; 4495 4496 case 0x10: // bc (Branch Conditional, PPC32 p361) 4497 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", 4498 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); 4499 4500 if (!(BO & 0x4)) { 4501 putGST( PPC_GST_CTR, 4502 binop(mkSzOp(ty, Iop_Sub8), 4503 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 4504 } 4505 4506 /* This is a bit subtle. ctr_ok is either all 0s or all 1s. 4507 cond_ok is either zero or nonzero, since that's the cheapest 4508 way to compute it. Anding them together gives a value which 4509 is either zero or non zero and so that's what we must test 4510 for in the IRStmt_Exit. */ 4511 assign( ctr_ok, branch_ctr_ok( BO ) ); 4512 assign( cond_ok, branch_cond_ok( BO, BI ) ); 4513 assign( do_branch, 4514 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 4515 4516 if (flag_AA) { 4517 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16)); 4518 } else { 4519 tgt = mkSzAddr(ty, guest_CIA_curr_instr + 4520 (Long)extend_s_16to64(BD_u16)); 4521 } 4522 if (flag_LK) 4523 putGST( PPC_GST_LR, e_nia ); 4524 4525 stmt( IRStmt_Exit( 4526 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)), 4527 flag_LK ? Ijk_Call : Ijk_Boring, 4528 mkSzConst(ty, tgt) ) ); 4529 4530 irsb->jumpkind = Ijk_Boring; 4531 irsb->next = e_nia; 4532 break; 4533 4534 case 0x13: 4535 /* For bclr and bcctr, it appears that the lowest two bits of 4536 b11to15 are a branch hint, and so we only need to ensure it's 4537 of the form 000XX. */ 4538 if ((b11to15 & ~3) != 0) { 4539 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15); 4540 return False; 4541 } 4542 4543 switch (opc2) { 4544 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363) 4545 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid 4546 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n"); 4547 return False; 4548 } 4549 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 4550 4551 assign( cond_ok, branch_cond_ok( BO, BI ) ); 4552 4553 /* FIXME: this is confusing. lr_old holds the old value 4554 of ctr, not lr :-) */ 4555 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 )); 4556 4557 if (flag_LK) 4558 putGST( PPC_GST_LR, e_nia ); 4559 4560 stmt( IRStmt_Exit( 4561 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)), 4562 Ijk_Boring, 4563 c_nia )); 4564 4565 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) { 4566 make_redzone_AbiHint( vbi, lr_old, 4567 "b-ctr-l (indirect call)" ); 4568 } 4569 4570 irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring; 4571 irsb->next = mkexpr(lr_old); 4572 break; 4573 4574 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365) 4575 Bool vanilla_return = False; 4576 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) { 4577 DIP("blr\n"); 4578 vanilla_return = True; 4579 } else { 4580 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 4581 } 4582 4583 if (!(BO & 0x4)) { 4584 putGST( PPC_GST_CTR, 4585 binop(mkSzOp(ty, Iop_Sub8), 4586 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 4587 } 4588 4589 /* See comments above for 'bc' about this */ 4590 assign( ctr_ok, branch_ctr_ok( BO ) ); 4591 assign( cond_ok, branch_cond_ok( BO, BI ) ); 4592 assign( do_branch, 4593 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 4594 4595 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 )); 4596 4597 if (flag_LK) 4598 putGST( PPC_GST_LR, e_nia ); 4599 4600 stmt( IRStmt_Exit( 4601 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)), 4602 Ijk_Boring, 4603 c_nia )); 4604 4605 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) { 4606 make_redzone_AbiHint( vbi, lr_old, 4607 "branch-to-lr (unconditional return)" ); 4608 } 4609 4610 /* blrl is pretty strange; it's like a return that sets the 4611 return address of its caller to the insn following this 4612 one. Mark it as a return. */ 4613 irsb->jumpkind = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */ 4614 irsb->next = mkexpr(lr_old); 4615 break; 4616 } 4617 default: 4618 vex_printf("dis_int_branch(ppc)(opc2)\n"); 4619 return False; 4620 } 4621 break; 4622 4623 default: 4624 vex_printf("dis_int_branch(ppc)(opc1)\n"); 4625 return False; 4626 } 4627 4628 return True; 4629 } 4630 4631 4632 4633 /* 4634 Condition Register Logical Instructions 4635 */ 4636 static Bool dis_cond_logic ( UInt theInstr ) 4637 { 4638 /* XL-Form */ 4639 UChar opc1 = ifieldOPC(theInstr); 4640 UChar crbD_addr = ifieldRegDS(theInstr); 4641 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) ); 4642 UChar crbA_addr = ifieldRegA(theInstr); 4643 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) ); 4644 UChar crbB_addr = ifieldRegB(theInstr); 4645 UInt opc2 = ifieldOPClo10(theInstr); 4646 UChar b0 = ifieldBIT0(theInstr); 4647 4648 IRTemp crbD = newTemp(Ity_I32); 4649 IRTemp crbA = newTemp(Ity_I32); 4650 IRTemp crbB = newTemp(Ity_I32); 4651 4652 if (opc1 != 19 || b0 != 0) { 4653 vex_printf("dis_cond_logic(ppc)(opc1)\n"); 4654 return False; 4655 } 4656 4657 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464) 4658 if (((crbD_addr & 0x3) != 0) || 4659 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) { 4660 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n"); 4661 return False; 4662 } 4663 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr); 4664 putCR0( crfD_addr, getCR0( crfS_addr) ); 4665 putCR321( crfD_addr, getCR321(crfS_addr) ); 4666 } else { 4667 assign( crbA, getCRbit(crbA_addr) ); 4668 if (crbA_addr == crbB_addr) 4669 crbB = crbA; 4670 else 4671 assign( crbB, getCRbit(crbB_addr) ); 4672 4673 switch (opc2) { 4674 case 0x101: // crand (Cond Reg AND, PPC32 p372) 4675 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 4676 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) ); 4677 break; 4678 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373) 4679 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 4680 assign( crbD, binop(Iop_And32, 4681 mkexpr(crbA), 4682 unop(Iop_Not32, mkexpr(crbB))) ); 4683 break; 4684 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374) 4685 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 4686 assign( crbD, unop(Iop_Not32, 4687 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) ); 4688 break; 4689 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375) 4690 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 4691 assign( crbD, unop(Iop_Not32, 4692 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) ); 4693 break; 4694 case 0x021: // crnor (Cond Reg NOR, PPC32 p376) 4695 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 4696 assign( crbD, unop(Iop_Not32, 4697 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) ); 4698 break; 4699 case 0x1C1: // cror (Cond Reg OR, PPC32 p377) 4700 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 4701 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) ); 4702 break; 4703 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378) 4704 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 4705 assign( crbD, binop(Iop_Or32, 4706 mkexpr(crbA), 4707 unop(Iop_Not32, mkexpr(crbB))) ); 4708 break; 4709 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379) 4710 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 4711 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) ); 4712 break; 4713 default: 4714 vex_printf("dis_cond_logic(ppc)(opc2)\n"); 4715 return False; 4716 } 4717 4718 putCRbit( crbD_addr, mkexpr(crbD) ); 4719 } 4720 return True; 4721 } 4722 4723 4724 /* 4725 Trap instructions 4726 */ 4727 4728 /* Do the code generation for a trap. Returned Bool is true iff 4729 this is an unconditional trap. If the two arg IRExpr*s are 4730 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s 4731 then they are 64-bit, and we must be disassembling 64-bit 4732 instructions. */ 4733 static Bool do_trap ( UChar TO, 4734 IRExpr* argL0, IRExpr* argR0, Addr64 cia ) 4735 { 4736 IRTemp argL, argR; 4737 IRExpr *argLe, *argRe, *cond, *tmp; 4738 4739 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32; 4740 4741 IROp opAND = is32bit ? Iop_And32 : Iop_And64; 4742 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64; 4743 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S; 4744 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U; 4745 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64; 4746 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64; 4747 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0); 4748 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2); 4749 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4); 4750 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8); 4751 4752 const UChar b11100 = 0x1C; 4753 const UChar b00111 = 0x07; 4754 4755 if (is32bit) { 4756 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 ); 4757 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 ); 4758 } else { 4759 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 ); 4760 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 ); 4761 vassert( mode64 ); 4762 } 4763 4764 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) { 4765 /* Unconditional trap. Just do the exit without 4766 testing the arguments. */ 4767 stmt( IRStmt_Exit( 4768 binop(opCMPEQ, const0, const0), 4769 Ijk_SigTRAP, 4770 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia) 4771 )); 4772 return True; /* unconditional trap */ 4773 } 4774 4775 if (is32bit) { 4776 argL = newTemp(Ity_I32); 4777 argR = newTemp(Ity_I32); 4778 } else { 4779 argL = newTemp(Ity_I64); 4780 argR = newTemp(Ity_I64); 4781 } 4782 4783 assign( argL, argL0 ); 4784 assign( argR, argR0 ); 4785 4786 argLe = mkexpr(argL); 4787 argRe = mkexpr(argR); 4788 4789 cond = const0; 4790 if (TO & 16) { // L <s R 4791 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8); 4792 cond = binop(opOR, tmp, cond); 4793 } 4794 if (TO & 8) { // L >s R 4795 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4); 4796 cond = binop(opOR, tmp, cond); 4797 } 4798 if (TO & 4) { // L == R 4799 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2); 4800 cond = binop(opOR, tmp, cond); 4801 } 4802 if (TO & 2) { // L <u R 4803 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8); 4804 cond = binop(opOR, tmp, cond); 4805 } 4806 if (TO & 1) { // L >u R 4807 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4); 4808 cond = binop(opOR, tmp, cond); 4809 } 4810 stmt( IRStmt_Exit( 4811 binop(opCMPNE, cond, const0), 4812 Ijk_SigTRAP, 4813 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia) 4814 )); 4815 return False; /* not an unconditional trap */ 4816 } 4817 4818 static Bool dis_trapi ( UInt theInstr, 4819 /*OUT*/DisResult* dres ) 4820 { 4821 /* D-Form */ 4822 UChar opc1 = ifieldOPC(theInstr); 4823 UChar TO = ifieldRegDS(theInstr); 4824 UChar rA_addr = ifieldRegA(theInstr); 4825 UInt uimm16 = ifieldUIMM16(theInstr); 4826 ULong simm16 = extend_s_16to64(uimm16); 4827 Addr64 cia = guest_CIA_curr_instr; 4828 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4829 Bool uncond = False; 4830 4831 switch (opc1) { 4832 case 0x03: // twi (Trap Word Immediate, PPC32 p548) 4833 uncond = do_trap( TO, 4834 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 4835 : getIReg(rA_addr), 4836 mkU32( (UInt)simm16 ), 4837 cia ); 4838 if (TO == 4) { 4839 DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 4840 } else { 4841 DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 4842 } 4843 break; 4844 case 0x02: // tdi 4845 if (!mode64) 4846 return False; 4847 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia ); 4848 if (TO == 4) { 4849 DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 4850 } else { 4851 DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 4852 } 4853 break; 4854 default: 4855 return False; 4856 } 4857 4858 if (uncond) { 4859 /* If the trap shows signs of being unconditional, don't 4860 continue decoding past it. */ 4861 irsb->next = mkSzImm( ty, nextInsnAddr() ); 4862 irsb->jumpkind = Ijk_Boring; 4863 dres->whatNext = Dis_StopHere; 4864 } 4865 4866 return True; 4867 } 4868 4869 static Bool dis_trap ( UInt theInstr, 4870 /*OUT*/DisResult* dres ) 4871 { 4872 /* X-Form */ 4873 UInt opc2 = ifieldOPClo10(theInstr); 4874 UChar TO = ifieldRegDS(theInstr); 4875 UChar rA_addr = ifieldRegA(theInstr); 4876 UChar rB_addr = ifieldRegB(theInstr); 4877 Addr64 cia = guest_CIA_curr_instr; 4878 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4879 Bool uncond = False; 4880 4881 if (ifieldBIT0(theInstr) != 0) 4882 return False; 4883 4884 switch (opc2) { 4885 case 0x004: // tw (Trap Word, PPC64 p540) 4886 uncond = do_trap( TO, 4887 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 4888 : getIReg(rA_addr), 4889 mode64 ? unop(Iop_64to32, getIReg(rB_addr)) 4890 : getIReg(rB_addr), 4891 cia ); 4892 if (TO == 4) { 4893 DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 4894 } else { 4895 DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 4896 } 4897 break; 4898 case 0x044: // td (Trap Doubleword, PPC64 p534) 4899 if (!mode64) 4900 return False; 4901 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia ); 4902 if (TO == 4) { 4903 DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 4904 } else { 4905 DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 4906 } 4907 break; 4908 default: 4909 return False; 4910 } 4911 4912 if (uncond) { 4913 /* If the trap shows signs of being unconditional, don't 4914 continue decoding past it. */ 4915 irsb->next = mkSzImm( ty, nextInsnAddr() ); 4916 irsb->jumpkind = Ijk_Boring; 4917 dres->whatNext = Dis_StopHere; 4918 } 4919 4920 return True; 4921 } 4922 4923 4924 /* 4925 System Linkage Instructions 4926 */ 4927 static Bool dis_syslink ( UInt theInstr, 4928 VexAbiInfo* abiinfo, DisResult* dres ) 4929 { 4930 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4931 4932 if (theInstr != 0x44000002) { 4933 vex_printf("dis_syslink(ppc)(theInstr)\n"); 4934 return False; 4935 } 4936 4937 // sc (System Call, PPC32 p504) 4938 DIP("sc\n"); 4939 4940 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX 4941 Valgrind can back the guest up to this instruction if it needs 4942 to restart the syscall. */ 4943 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) ); 4944 4945 /* It's important that all ArchRegs carry their up-to-date value 4946 at this point. So we declare an end-of-block here, which 4947 forces any TempRegs caching ArchRegs to be flushed. */ 4948 irsb->next = abiinfo->guest_ppc_sc_continues_at_LR 4949 ? getGST( PPC_GST_LR ) 4950 : mkSzImm( ty, nextInsnAddr() ); 4951 irsb->jumpkind = Ijk_Sys_syscall; 4952 4953 dres->whatNext = Dis_StopHere; 4954 return True; 4955 } 4956 4957 4958 /* 4959 Memory Synchronization Instructions 4960 4961 Note on Reservations: 4962 We rely on the assumption that V will in fact only allow one thread at 4963 once to run. In effect, a thread can make a reservation, but we don't 4964 check any stores it does. Instead, the reservation is cancelled when 4965 the scheduler switches to another thread (run_thread_for_a_while()). 4966 */ 4967 static Bool dis_memsync ( UInt theInstr ) 4968 { 4969 /* X-Form, XL-Form */ 4970 UChar opc1 = ifieldOPC(theInstr); 4971 UInt b11to25 = IFIELD(theInstr, 11, 15); 4972 UChar flag_L = ifieldRegDS(theInstr); 4973 UInt b11to20 = IFIELD(theInstr, 11, 10); 4974 UChar rD_addr = ifieldRegDS(theInstr); 4975 UChar rS_addr = rD_addr; 4976 UChar rA_addr = ifieldRegA(theInstr); 4977 UChar rB_addr = ifieldRegB(theInstr); 4978 UInt opc2 = ifieldOPClo10(theInstr); 4979 UChar b0 = ifieldBIT0(theInstr); 4980 4981 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4982 IRTemp EA = newTemp(ty); 4983 4984 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 4985 4986 switch (opc1) { 4987 /* XL-Form */ 4988 case 0x13: // isync (Instruction Synchronize, PPC32 p432) 4989 if (opc2 != 0x096) { 4990 vex_printf("dis_memsync(ppc)(0x13,opc2)\n"); 4991 return False; 4992 } 4993 if (b11to25 != 0 || b0 != 0) { 4994 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n"); 4995 return False; 4996 } 4997 DIP("isync\n"); 4998 stmt( IRStmt_MBE(Imbe_Fence) ); 4999 break; 5000 5001 /* X-Form */ 5002 case 0x1F: 5003 switch (opc2) { 5004 case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394) 5005 if (b11to25 != 0 || b0 != 0) { 5006 vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n"); 5007 return False; 5008 } 5009 DIP("eieio\n"); 5010 /* Insert a memory fence, just to be on the safe side. */ 5011 stmt( IRStmt_MBE(Imbe_Fence) ); 5012 break; 5013 5014 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458) 5015 IRTemp res; 5016 /* According to the PowerPC ISA version 2.05, b0 (called EH 5017 in the documentation) is merely a hint bit to the 5018 hardware, I think as to whether or not contention is 5019 likely. So we can just ignore it. */ 5020 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 5021 5022 // trap if misaligned 5023 gen_SIGBUS_if_misaligned( EA, 4 ); 5024 5025 // and actually do the load 5026 res = newTemp(Ity_I32); 5027 stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) ); 5028 5029 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) ); 5030 break; 5031 } 5032 5033 case 0x096: { 5034 // stwcx. (Store Word Conditional Indexed, PPC32 p532) 5035 // Note this has to handle stwcx. in both 32- and 64-bit modes, 5036 // so isn't quite as straightforward as it might otherwise be. 5037 IRTemp rS = newTemp(Ity_I32); 5038 IRTemp resSC; 5039 if (b0 != 1) { 5040 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 5041 return False; 5042 } 5043 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5044 5045 // trap if misaligned 5046 gen_SIGBUS_if_misaligned( EA, 4 ); 5047 5048 // Get the data to be stored, and narrow to 32 bits if necessary 5049 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) ); 5050 5051 // Do the store, and get success/failure bit into resSC 5052 resSC = newTemp(Ity_I1); 5053 stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) ); 5054 5055 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 5056 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 5057 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 5058 putCR0(0, getXER_SO()); 5059 5060 /* Note: 5061 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 5062 whether rS is stored is dependent on that value. */ 5063 /* So I guess we can just ignore this case? */ 5064 break; 5065 } 5066 5067 case 0x256: // sync (Synchronize, PPC32 p543), 5068 // also lwsync (L==1), ptesync (L==2) 5069 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html 5070 5071 The PowerPC architecture used in IBM chips has expanded 5072 the sync instruction into two variants: lightweight sync 5073 and heavyweight sync. The original sync instruction is 5074 the new heavyweight sync and lightweight sync is a strict 5075 subset of the heavyweight sync functionality. This allows 5076 the programmer to specify a less expensive operation on 5077 high-end systems when the full sync functionality is not 5078 necessary. 5079 5080 The basic "sync" mnemonic now utilizes an operand. "sync" 5081 without an operand now becomes a extended mnemonic for 5082 heavyweight sync. Processors without the lwsync 5083 instruction will not decode the L field and will perform a 5084 heavyweight sync. Everything is backward compatible. 5085 5086 sync = sync 0 5087 lwsync = sync 1 5088 ptesync = sync 2 *** TODO - not implemented *** 5089 */ 5090 if (b11to20 != 0 || b0 != 0) { 5091 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n"); 5092 return False; 5093 } 5094 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) { 5095 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n"); 5096 return False; 5097 } 5098 DIP("%ssync\n", flag_L == 1 ? "lw" : ""); 5099 /* Insert a memory fence. It's sometimes important that these 5100 are carried through to the generated code. */ 5101 stmt( IRStmt_MBE(Imbe_Fence) ); 5102 break; 5103 5104 /* 64bit Memsync */ 5105 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473) 5106 IRTemp res; 5107 /* According to the PowerPC ISA version 2.05, b0 (called EH 5108 in the documentation) is merely a hint bit to the 5109 hardware, I think as to whether or not contention is 5110 likely. So we can just ignore it. */ 5111 if (!mode64) 5112 return False; 5113 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 5114 5115 // trap if misaligned 5116 gen_SIGBUS_if_misaligned( EA, 8 ); 5117 5118 // and actually do the load 5119 res = newTemp(Ity_I64); 5120 stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) ); 5121 5122 putIReg( rD_addr, mkexpr(res) ); 5123 break; 5124 } 5125 5126 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581) 5127 // A marginally simplified version of the stwcx. case 5128 IRTemp rS = newTemp(Ity_I64); 5129 IRTemp resSC; 5130 if (b0 != 1) { 5131 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n"); 5132 return False; 5133 } 5134 if (!mode64) 5135 return False; 5136 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5137 5138 // trap if misaligned 5139 gen_SIGBUS_if_misaligned( EA, 8 ); 5140 5141 // Get the data to be stored 5142 assign( rS, getIReg(rS_addr) ); 5143 5144 // Do the store, and get success/failure bit into resSC 5145 resSC = newTemp(Ity_I1); 5146 stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) ); 5147 5148 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 5149 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 5150 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 5151 putCR0(0, getXER_SO()); 5152 5153 /* Note: 5154 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 5155 whether rS is stored is dependent on that value. */ 5156 /* So I guess we can just ignore this case? */ 5157 break; 5158 } 5159 5160 default: 5161 vex_printf("dis_memsync(ppc)(opc2)\n"); 5162 return False; 5163 } 5164 break; 5165 5166 default: 5167 vex_printf("dis_memsync(ppc)(opc1)\n"); 5168 return False; 5169 } 5170 return True; 5171 } 5172 5173 5174 5175 /* 5176 Integer Shift Instructions 5177 */ 5178 static Bool dis_int_shift ( UInt theInstr ) 5179 { 5180 /* X-Form, XS-Form */ 5181 UChar opc1 = ifieldOPC(theInstr); 5182 UChar rS_addr = ifieldRegDS(theInstr); 5183 UChar rA_addr = ifieldRegA(theInstr); 5184 UChar rB_addr = ifieldRegB(theInstr); 5185 UChar sh_imm = rB_addr; 5186 UInt opc2 = ifieldOPClo10(theInstr); 5187 UChar b1 = ifieldBIT1(theInstr); 5188 UChar flag_rC = ifieldBIT0(theInstr); 5189 5190 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5191 IRTemp rA = newTemp(ty); 5192 IRTemp rS = newTemp(ty); 5193 IRTemp rB = newTemp(ty); 5194 IRTemp outofrange = newTemp(Ity_I8); 5195 IRTemp rS_lo32 = newTemp(Ity_I32); 5196 IRTemp rB_lo32 = newTemp(Ity_I32); 5197 IRExpr* e_tmp; 5198 5199 assign( rS, getIReg(rS_addr) ); 5200 assign( rB, getIReg(rB_addr) ); 5201 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) ); 5202 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) ); 5203 5204 if (opc1 == 0x1F) { 5205 switch (opc2) { 5206 case 0x018: { // slw (Shift Left Word, PPC32 p505) 5207 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5208 rA_addr, rS_addr, rB_addr); 5209 /* rA = rS << rB */ 5210 /* ppc32 semantics are: 5211 slw(x,y) = (x << (y & 31)) -- primary result 5212 & ~((y << 26) >>s 31) -- make result 0 5213 for y in 32 .. 63 5214 */ 5215 e_tmp = 5216 binop( Iop_And32, 5217 binop( Iop_Shl32, 5218 mkexpr(rS_lo32), 5219 unop( Iop_32to8, 5220 binop(Iop_And32, 5221 mkexpr(rB_lo32), mkU32(31)))), 5222 unop( Iop_Not32, 5223 binop( Iop_Sar32, 5224 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)), 5225 mkU8(31))) ); 5226 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 5227 break; 5228 } 5229 5230 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506) 5231 IRTemp sh_amt = newTemp(Ity_I32); 5232 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5233 rA_addr, rS_addr, rB_addr); 5234 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is: 5235 amt = rB & 63 5236 rA = Sar32( rS, amt > 31 ? 31 : amt ) 5237 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi) 5238 */ 5239 assign( sh_amt, binop(Iop_And32, mkU32(0x3F), 5240 mkexpr(rB_lo32)) ); 5241 assign( outofrange, 5242 unop( Iop_1Uto8, 5243 binop(Iop_CmpLT32U, mkU32(31), 5244 mkexpr(sh_amt)) )); 5245 e_tmp = binop( Iop_Sar32, 5246 mkexpr(rS_lo32), 5247 unop( Iop_32to8, 5248 IRExpr_Mux0X( mkexpr(outofrange), 5249 mkexpr(sh_amt), 5250 mkU32(31)) ) ); 5251 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) ); 5252 5253 set_XER_CA( ty, PPCG_FLAG_OP_SRAW, 5254 mkexpr(rA), 5255 mkWidenFrom32(ty, mkexpr(rS_lo32), True), 5256 mkWidenFrom32(ty, mkexpr(sh_amt), True ), 5257 mkWidenFrom32(ty, getXER_CA32(), True) ); 5258 break; 5259 } 5260 5261 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507) 5262 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"", 5263 rA_addr, rS_addr, sh_imm); 5264 vassert(sh_imm < 32); 5265 if (mode64) { 5266 assign( rA, binop(Iop_Sar64, 5267 binop(Iop_Shl64, getIReg(rS_addr), 5268 mkU8(32)), 5269 mkU8(32 + sh_imm)) ); 5270 } else { 5271 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32), 5272 mkU8(sh_imm)) ); 5273 } 5274 5275 set_XER_CA( ty, PPCG_FLAG_OP_SRAWI, 5276 mkexpr(rA), 5277 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True), 5278 mkSzImm(ty, sh_imm), 5279 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 5280 break; 5281 5282 case 0x218: // srw (Shift Right Word, PPC32 p508) 5283 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5284 rA_addr, rS_addr, rB_addr); 5285 /* rA = rS >>u rB */ 5286 /* ppc32 semantics are: 5287 srw(x,y) = (x >>u (y & 31)) -- primary result 5288 & ~((y << 26) >>s 31) -- make result 0 5289 for y in 32 .. 63 5290 */ 5291 e_tmp = 5292 binop( 5293 Iop_And32, 5294 binop( Iop_Shr32, 5295 mkexpr(rS_lo32), 5296 unop( Iop_32to8, 5297 binop(Iop_And32, mkexpr(rB_lo32), 5298 mkU32(31)))), 5299 unop( Iop_Not32, 5300 binop( Iop_Sar32, 5301 binop(Iop_Shl32, mkexpr(rB_lo32), 5302 mkU8(26)), 5303 mkU8(31)))); 5304 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 5305 break; 5306 5307 5308 /* 64bit Shifts */ 5309 case 0x01B: // sld (Shift Left DWord, PPC64 p568) 5310 DIP("sld%s r%u,r%u,r%u\n", 5311 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 5312 /* rA = rS << rB */ 5313 /* ppc64 semantics are: 5314 slw(x,y) = (x << (y & 63)) -- primary result 5315 & ~((y << 57) >>s 63) -- make result 0 5316 for y in 64 .. 5317 */ 5318 assign( rA, 5319 binop( 5320 Iop_And64, 5321 binop( Iop_Shl64, 5322 mkexpr(rS), 5323 unop( Iop_64to8, 5324 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 5325 unop( Iop_Not64, 5326 binop( Iop_Sar64, 5327 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 5328 mkU8(63)))) ); 5329 break; 5330 5331 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570) 5332 IRTemp sh_amt = newTemp(Ity_I64); 5333 DIP("srad%s r%u,r%u,r%u\n", 5334 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 5335 /* amt = rB & 127 5336 rA = Sar64( rS, amt > 63 ? 63 : amt ) 5337 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi) 5338 */ 5339 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) ); 5340 assign( outofrange, 5341 unop( Iop_1Uto8, 5342 binop(Iop_CmpLT64U, mkU64(63), 5343 mkexpr(sh_amt)) )); 5344 assign( rA, 5345 binop( Iop_Sar64, 5346 mkexpr(rS), 5347 unop( Iop_64to8, 5348 IRExpr_Mux0X( mkexpr(outofrange), 5349 mkexpr(sh_amt), 5350 mkU64(63)) )) 5351 ); 5352 set_XER_CA( ty, PPCG_FLAG_OP_SRAD, 5353 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt), 5354 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 5355 break; 5356 } 5357 5358 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571) 5359 sh_imm |= b1<<5; 5360 vassert(sh_imm < 64); 5361 DIP("sradi%s r%u,r%u,%u\n", 5362 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 5363 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) ); 5364 5365 set_XER_CA( ty, PPCG_FLAG_OP_SRADI, 5366 mkexpr(rA), 5367 getIReg(rS_addr), 5368 mkU64(sh_imm), 5369 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 5370 break; 5371 5372 case 0x21B: // srd (Shift Right DWord, PPC64 p574) 5373 DIP("srd%s r%u,r%u,r%u\n", 5374 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 5375 /* rA = rS >>u rB */ 5376 /* ppc semantics are: 5377 srw(x,y) = (x >>u (y & 63)) -- primary result 5378 & ~((y << 57) >>s 63) -- make result 0 5379 for y in 64 .. 127 5380 */ 5381 assign( rA, 5382 binop( 5383 Iop_And64, 5384 binop( Iop_Shr64, 5385 mkexpr(rS), 5386 unop( Iop_64to8, 5387 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 5388 unop( Iop_Not64, 5389 binop( Iop_Sar64, 5390 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 5391 mkU8(63)))) ); 5392 break; 5393 5394 default: 5395 vex_printf("dis_int_shift(ppc)(opc2)\n"); 5396 return False; 5397 } 5398 } else { 5399 vex_printf("dis_int_shift(ppc)(opc1)\n"); 5400 return False; 5401 } 5402 5403 putIReg( rA_addr, mkexpr(rA) ); 5404 5405 if (flag_rC) { 5406 set_CR0( mkexpr(rA) ); 5407 } 5408 return True; 5409 } 5410 5411 5412 5413 /* 5414 Integer Load/Store Reverse Instructions 5415 */ 5416 /* Generates code to swap the byte order in an Ity_I32. */ 5417 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t ) 5418 { 5419 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 5420 return 5421 binop(Iop_Or32, 5422 binop(Iop_Shl32, mkexpr(t), mkU8(24)), 5423 binop(Iop_Or32, 5424 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 5425 mkU32(0x00FF0000)), 5426 binop(Iop_Or32, 5427 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 5428 mkU32(0x0000FF00)), 5429 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)), 5430 mkU32(0x000000FF) ) 5431 ))); 5432 } 5433 5434 /* Generates code to swap the byte order in the lower half of an Ity_I32, 5435 and zeroes the upper half. */ 5436 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t ) 5437 { 5438 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 5439 return 5440 binop(Iop_Or32, 5441 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 5442 mkU32(0x0000FF00)), 5443 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 5444 mkU32(0x000000FF)) 5445 ); 5446 } 5447 5448 static Bool dis_int_ldst_rev ( UInt theInstr ) 5449 { 5450 /* X-Form */ 5451 UChar opc1 = ifieldOPC(theInstr); 5452 UChar rD_addr = ifieldRegDS(theInstr); 5453 UChar rS_addr = rD_addr; 5454 UChar rA_addr = ifieldRegA(theInstr); 5455 UChar rB_addr = ifieldRegB(theInstr); 5456 UInt opc2 = ifieldOPClo10(theInstr); 5457 UChar b0 = ifieldBIT0(theInstr); 5458 5459 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5460 IRTemp EA = newTemp(ty); 5461 IRTemp w1 = newTemp(Ity_I32); 5462 IRTemp w2 = newTemp(Ity_I32); 5463 5464 if (opc1 != 0x1F || b0 != 0) { 5465 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n"); 5466 return False; 5467 } 5468 5469 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 5470 5471 switch (opc2) { 5472 5473 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449) 5474 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5475 assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) ); 5476 assign( w2, gen_byterev16(w1) ); 5477 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 5478 /* Signed */False) ); 5479 break; 5480 5481 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459) 5482 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5483 assign( w1, loadBE(Ity_I32, mkexpr(EA)) ); 5484 assign( w2, gen_byterev32(w1) ); 5485 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 5486 /* Signed */False) ); 5487 break; 5488 5489 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523) 5490 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5491 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 5492 storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) ); 5493 break; 5494 5495 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531) 5496 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5497 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 5498 storeBE( mkexpr(EA), gen_byterev32(w1) ); 5499 break; 5500 5501 default: 5502 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n"); 5503 return False; 5504 } 5505 return True; 5506 } 5507 5508 5509 5510 /* 5511 Processor Control Instructions 5512 */ 5513 static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr ) 5514 { 5515 UChar opc1 = ifieldOPC(theInstr); 5516 5517 /* X-Form */ 5518 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 5519 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 5520 UChar rD_addr = ifieldRegDS(theInstr); 5521 UInt b11to20 = IFIELD( theInstr, 11, 10 ); 5522 5523 /* XFX-Form */ 5524 UChar rS_addr = rD_addr; 5525 UInt SPR = b11to20; 5526 UInt TBR = b11to20; 5527 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) ); 5528 UInt CRM = IFIELD( theInstr, 12, 8 ); 5529 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 5530 5531 UInt opc2 = ifieldOPClo10(theInstr); 5532 UChar b0 = ifieldBIT0(theInstr); 5533 5534 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5535 IRTemp rS = newTemp(ty); 5536 assign( rS, getIReg(rS_addr) ); 5537 5538 /* Reorder SPR field as per PPC32 p470 */ 5539 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); 5540 /* Reorder TBR field as per PPC32 p475 */ 5541 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31); 5542 5543 if (opc1 != 0x1F || b0 != 0) { 5544 vex_printf("dis_proc_ctl(ppc)(opc1|b0)\n"); 5545 return False; 5546 } 5547 5548 switch (opc2) { 5549 /* X-Form */ 5550 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466) 5551 if (b21to22 != 0 || b11to20 != 0) { 5552 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n"); 5553 return False; 5554 } 5555 DIP("mcrxr crf%d\n", crfD); 5556 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */ 5557 putGST_field( PPC_GST_CR, 5558 getGST_field( PPC_GST_XER, 7 ), 5559 crfD ); 5560 5561 // Clear XER[0-3] 5562 putXER_SO( mkU8(0) ); 5563 putXER_OV( mkU8(0) ); 5564 putXER_CA( mkU8(0) ); 5565 break; 5566 } 5567 5568 case 0x013: 5569 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467) 5570 // b20==1 & b11==0: mfocrf (Move from One CR Field) 5571 // However it seems that the 'mfcr' behaviour is an acceptable 5572 // implementation of mfocr (from the 2.02 arch spec) 5573 if (b11to20 == 0) { 5574 DIP("mfcr r%u\n", rD_addr); 5575 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 5576 /* Signed */False) ); 5577 break; 5578 } 5579 if (b20 == 1 && b11 == 0) { 5580 DIP("mfocrf r%u,%u\n", rD_addr, CRM); 5581 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 5582 /* Signed */False) ); 5583 break; 5584 } 5585 /* not decodable */ 5586 return False; 5587 5588 /* XFX-Form */ 5589 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470) 5590 5591 switch (SPR) { // Choose a register... 5592 case 0x1: 5593 DIP("mfxer r%u\n", rD_addr); 5594 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ), 5595 /* Signed */False) ); 5596 break; 5597 case 0x8: 5598 DIP("mflr r%u\n", rD_addr); 5599 putIReg( rD_addr, getGST( PPC_GST_LR ) ); 5600 break; 5601 case 0x9: 5602 DIP("mfctr r%u\n", rD_addr); 5603 putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 5604 break; 5605 case 0x100: 5606 DIP("mfvrsave r%u\n", rD_addr); 5607 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ), 5608 /* Signed */False) ); 5609 break; 5610 5611 case 0x103: 5612 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr); 5613 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) ); 5614 break; 5615 5616 /* Even a lowly PPC7400 can run the associated helper, so no 5617 obvious need for feature testing at this point. */ 5618 case 268 /* 0x10C */: 5619 case 269 /* 0x10D */: { 5620 UInt arg = SPR==268 ? 0 : 1; 5621 IRTemp val = newTemp(Ity_I32); 5622 IRExpr** args = mkIRExprVec_1( mkU32(arg) ); 5623 IRDirty* d = unsafeIRDirty_1_N( 5624 val, 5625 0/*regparms*/, 5626 "ppc32g_dirtyhelper_MFSPR_268_269", 5627 fnptr_to_fnentry 5628 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269), 5629 args 5630 ); 5631 /* execute the dirty call, dumping the result in val. */ 5632 stmt( IRStmt_Dirty(d) ); 5633 putIReg( rD_addr, 5634 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 5635 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 5636 break; 5637 } 5638 5639 /* Again, runs natively on PPC7400 (7447, really). Not 5640 bothering with a feature test. */ 5641 case 287: /* 0x11F */ { 5642 IRTemp val = newTemp(Ity_I32); 5643 IRExpr** args = mkIRExprVec_0(); 5644 IRDirty* d = unsafeIRDirty_1_N( 5645 val, 5646 0/*regparms*/, 5647 "ppc32g_dirtyhelper_MFSPR_287", 5648 fnptr_to_fnentry 5649 (vbi, &ppc32g_dirtyhelper_MFSPR_287), 5650 args 5651 ); 5652 /* execute the dirty call, dumping the result in val. */ 5653 stmt( IRStmt_Dirty(d) ); 5654 putIReg( rD_addr, 5655 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 5656 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 5657 break; 5658 } 5659 5660 default: 5661 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR); 5662 return False; 5663 } 5664 break; 5665 5666 case 0x173: { // mftb (Move from Time Base, PPC32 p475) 5667 IRTemp val = newTemp(Ity_I64); 5668 IRExpr** args = mkIRExprVec_0(); 5669 IRDirty* d = unsafeIRDirty_1_N( 5670 val, 5671 0/*regparms*/, 5672 "ppcg_dirtyhelper_MFTB", 5673 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB), 5674 args ); 5675 /* execute the dirty call, dumping the result in val. */ 5676 stmt( IRStmt_Dirty(d) ); 5677 5678 switch (TBR) { 5679 case 269: 5680 DIP("mftbu r%u", rD_addr); 5681 putIReg( rD_addr, 5682 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)), 5683 /* Signed */False) ); 5684 break; 5685 case 268: 5686 DIP("mftb r%u", rD_addr); 5687 putIReg( rD_addr, (mode64) ? mkexpr(val) : 5688 unop(Iop_64to32, mkexpr(val)) ); 5689 break; 5690 default: 5691 return False; /* illegal instruction */ 5692 } 5693 break; 5694 } 5695 5696 case 0x090: { 5697 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477) 5698 // b20==1: mtocrf (Move to One Cond Reg Field) 5699 Int cr; 5700 UChar shft; 5701 if (b11 != 0) 5702 return False; 5703 if (b20 == 1) { 5704 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if > 5705 1 field is written. It seems more robust to decline to 5706 decode the insn if so. */ 5707 switch (CRM) { 5708 case 0x01: case 0x02: case 0x04: case 0x08: 5709 case 0x10: case 0x20: case 0x40: case 0x80: 5710 break; 5711 default: 5712 return False; 5713 } 5714 } 5715 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf", 5716 CRM, rS_addr); 5717 /* Write to each field specified by CRM */ 5718 for (cr = 0; cr < 8; cr++) { 5719 if ((CRM & (1 << (7-cr))) == 0) 5720 continue; 5721 shft = 4*(7-cr); 5722 putGST_field( PPC_GST_CR, 5723 binop(Iop_Shr32, 5724 mkNarrowTo32(ty, mkexpr(rS)), 5725 mkU8(shft)), cr ); 5726 } 5727 break; 5728 } 5729 5730 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483) 5731 5732 switch (SPR) { // Choose a register... 5733 case 0x1: 5734 DIP("mtxer r%u\n", rS_addr); 5735 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) ); 5736 break; 5737 case 0x8: 5738 DIP("mtlr r%u\n", rS_addr); 5739 putGST( PPC_GST_LR, mkexpr(rS) ); 5740 break; 5741 case 0x9: 5742 DIP("mtctr r%u\n", rS_addr); 5743 putGST( PPC_GST_CTR, mkexpr(rS) ); 5744 break; 5745 case 0x100: 5746 DIP("mtvrsave r%u\n", rS_addr); 5747 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) ); 5748 break; 5749 5750 default: 5751 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR); 5752 return False; 5753 } 5754 break; 5755 5756 default: 5757 vex_printf("dis_proc_ctl(ppc)(opc2)\n"); 5758 return False; 5759 } 5760 return True; 5761 } 5762 5763 5764 /* 5765 Cache Management Instructions 5766 */ 5767 static Bool dis_cache_manage ( UInt theInstr, 5768 DisResult* dres, 5769 VexArchInfo* guest_archinfo ) 5770 { 5771 /* X-Form */ 5772 UChar opc1 = ifieldOPC(theInstr); 5773 UChar b21to25 = ifieldRegDS(theInstr); 5774 UChar rA_addr = ifieldRegA(theInstr); 5775 UChar rB_addr = ifieldRegB(theInstr); 5776 UInt opc2 = ifieldOPClo10(theInstr); 5777 UChar b0 = ifieldBIT0(theInstr); 5778 UInt lineszB = guest_archinfo->ppc_cache_line_szB; 5779 Bool is_dcbzl = False; 5780 5781 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5782 5783 /* For dcbt, the lowest two bits of b21to25 encode an 5784 access-direction hint (TH field) which we ignore. Well, that's 5785 what the PowerPC documentation says. In fact xlc -O4 on POWER5 5786 seems to generate values of 8 and 10 for b21to25. */ 5787 if (opc1 == 0x1F && opc2 == 0x116) { 5788 /* b21to25 &= ~3; */ /* if the docs were true */ 5789 b21to25 = 0; /* blunt instrument */ 5790 } 5791 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz 5792 if (b21to25 == 1) { 5793 is_dcbzl = True; 5794 b21to25 = 0; 5795 if (!(guest_archinfo->ppc_dcbzl_szB)) { 5796 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n"); 5797 return False; 5798 } 5799 } 5800 } 5801 5802 if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) { 5803 if (0) vex_printf("dis_cache_manage %d %d %d\n", 5804 (Int)opc1, (Int)b21to25, (Int)b0); 5805 vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n"); 5806 return False; 5807 } 5808 5809 /* stay sane .. */ 5810 vassert(lineszB == 32 || lineszB == 64 || lineszB == 128); 5811 5812 switch (opc2) { 5813 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380) 5814 //zz vassert(0); /* AWAITING TEST CASE */ 5815 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr); 5816 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n"); 5817 //zz break; 5818 5819 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382) 5820 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr); 5821 /* nop as far as vex is concerned */ 5822 break; 5823 5824 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384) 5825 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr); 5826 /* nop as far as vex is concerned */ 5827 break; 5828 5829 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385) 5830 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr); 5831 /* nop as far as vex is concerned */ 5832 break; 5833 5834 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386) 5835 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr); 5836 /* nop as far as vex is concerned */ 5837 break; 5838 5839 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387) 5840 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264) 5841 /* Clear all bytes in cache block at (rA|0) + rB. */ 5842 IRTemp EA = newTemp(ty); 5843 IRTemp addr = newTemp(ty); 5844 IRExpr* irx_addr; 5845 UInt i; 5846 UInt clearszB; 5847 if (is_dcbzl) { 5848 clearszB = guest_archinfo->ppc_dcbzl_szB; 5849 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr); 5850 } 5851 else { 5852 clearszB = guest_archinfo->ppc_dcbz_szB; 5853 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr); 5854 } 5855 5856 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 5857 5858 if (mode64) { 5859 /* Round EA down to the start of the containing block. */ 5860 assign( addr, binop( Iop_And64, 5861 mkexpr(EA), 5862 mkU64( ~((ULong)clearszB-1) )) ); 5863 5864 for (i = 0; i < clearszB / 8; i++) { 5865 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) ); 5866 storeBE( irx_addr, mkU64(0) ); 5867 } 5868 } else { 5869 /* Round EA down to the start of the containing block. */ 5870 assign( addr, binop( Iop_And32, 5871 mkexpr(EA), 5872 mkU32( ~(clearszB-1) )) ); 5873 5874 for (i = 0; i < clearszB / 4; i++) { 5875 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) ); 5876 storeBE( irx_addr, mkU32(0) ); 5877 } 5878 } 5879 break; 5880 } 5881 5882 case 0x3D6: { 5883 // icbi (Instruction Cache Block Invalidate, PPC32 p431) 5884 /* Invalidate all translations containing code from the cache 5885 block at (rA|0) + rB. */ 5886 IRTemp EA = newTemp(ty); 5887 IRTemp addr = newTemp(ty); 5888 DIP("icbi r%u,r%u\n", rA_addr, rB_addr); 5889 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 5890 5891 /* Round EA down to the start of the containing block. */ 5892 assign( addr, binop( mkSzOp(ty, Iop_And8), 5893 mkexpr(EA), 5894 mkSzImm(ty, ~(((ULong)lineszB)-1) )) ); 5895 putGST( PPC_GST_TISTART, mkexpr(addr) ); 5896 putGST( PPC_GST_TILEN, mkSzImm(ty, lineszB) ); 5897 5898 /* be paranoid ... */ 5899 stmt( IRStmt_MBE(Imbe_Fence) ); 5900 5901 irsb->jumpkind = Ijk_TInval; 5902 irsb->next = mkSzImm(ty, nextInsnAddr()); 5903 dres->whatNext = Dis_StopHere; 5904 break; 5905 } 5906 5907 default: 5908 vex_printf("dis_cache_manage(ppc)(opc2)\n"); 5909 return False; 5910 } 5911 return True; 5912 } 5913 5914 5915 /*------------------------------------------------------------*/ 5916 /*--- Floating Point Helpers ---*/ 5917 /*------------------------------------------------------------*/ 5918 5919 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */ 5920 /* Produces a value in 0 .. 3, which is encoded as per the type 5921 IRRoundingMode. PPCRoundingMode encoding is different to 5922 IRRoundingMode, so need to map it. 5923 */ 5924 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void ) 5925 { 5926 /* 5927 rounding mode | PPC | IR 5928 ------------------------ 5929 to nearest | 00 | 00 5930 to zero | 01 | 11 5931 to +infinity | 10 | 10 5932 to -infinity | 11 | 01 5933 */ 5934 IRTemp rm_PPC32 = newTemp(Ity_I32); 5935 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) ); 5936 5937 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 5938 return binop( Iop_Xor32, 5939 mkexpr(rm_PPC32), 5940 binop( Iop_And32, 5941 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)), 5942 mkU32(2) )); 5943 } 5944 5945 5946 /*------------------------------------------------------------*/ 5947 /*--- Floating Point Instruction Translation ---*/ 5948 /*------------------------------------------------------------*/ 5949 5950 /* 5951 Floating Point Load Instructions 5952 */ 5953 static Bool dis_fp_load ( UInt theInstr ) 5954 { 5955 /* X-Form, D-Form */ 5956 UChar opc1 = ifieldOPC(theInstr); 5957 UChar frD_addr = ifieldRegDS(theInstr); 5958 UChar rA_addr = ifieldRegA(theInstr); 5959 UChar rB_addr = ifieldRegB(theInstr); 5960 UInt opc2 = ifieldOPClo10(theInstr); 5961 UChar b0 = ifieldBIT0(theInstr); 5962 UInt uimm16 = ifieldUIMM16(theInstr); 5963 5964 Int simm16 = extend_s_16to32(uimm16); 5965 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5966 IRTemp EA = newTemp(ty); 5967 IRTemp rA = newTemp(ty); 5968 IRTemp rB = newTemp(ty); 5969 IRTemp iHi = newTemp(Ity_I32); 5970 IRTemp iLo = newTemp(Ity_I32); 5971 5972 assign( rA, getIReg(rA_addr) ); 5973 assign( rB, getIReg(rB_addr) ); 5974 5975 /* These are completely straightforward from a rounding and status 5976 bits perspective: no rounding involved and no funny status or CR 5977 bits affected. */ 5978 5979 switch (opc1) { 5980 case 0x30: // lfs (Load Float Single, PPC32 p441) 5981 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 5982 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 5983 putFReg( frD_addr, 5984 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 5985 break; 5986 5987 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442) 5988 if (rA_addr == 0) 5989 return False; 5990 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 5991 assign( EA, ea_rA_simm(rA_addr, simm16) ); 5992 putFReg( frD_addr, 5993 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 5994 putIReg( rA_addr, mkexpr(EA) ); 5995 break; 5996 5997 case 0x32: // lfd (Load Float Double, PPC32 p437) 5998 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 5999 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 6000 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 6001 break; 6002 6003 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438) 6004 if (rA_addr == 0) 6005 return False; 6006 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 6007 assign( EA, ea_rA_simm(rA_addr, simm16) ); 6008 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 6009 putIReg( rA_addr, mkexpr(EA) ); 6010 break; 6011 6012 case 0x1F: 6013 if (b0 != 0) { 6014 vex_printf("dis_fp_load(ppc)(instr,b0)\n"); 6015 return False; 6016 } 6017 6018 switch(opc2) { 6019 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444) 6020 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 6021 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6022 putFReg( frD_addr, unop( Iop_F32toF64, 6023 loadBE(Ity_F32, mkexpr(EA))) ); 6024 break; 6025 6026 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443) 6027 if (rA_addr == 0) 6028 return False; 6029 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 6030 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 6031 putFReg( frD_addr, 6032 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 6033 putIReg( rA_addr, mkexpr(EA) ); 6034 break; 6035 6036 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440) 6037 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 6038 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6039 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 6040 break; 6041 6042 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439) 6043 if (rA_addr == 0) 6044 return False; 6045 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 6046 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 6047 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 6048 putIReg( rA_addr, mkexpr(EA) ); 6049 break; 6050 6051 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120) 6052 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 6053 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6054 assign( iLo, loadBE(Ity_I32, mkexpr(EA)) ); 6055 assign( iHi, binop(Iop_Sub32, 6056 mkU32(0), 6057 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) ); 6058 putFReg( frD_addr, unop(Iop_ReinterpI64asF64, 6059 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) ); 6060 break; 6061 6062 default: 6063 vex_printf("dis_fp_load(ppc)(opc2)\n"); 6064 return False; 6065 } 6066 break; 6067 6068 default: 6069 vex_printf("dis_fp_load(ppc)(opc1)\n"); 6070 return False; 6071 } 6072 return True; 6073 } 6074 6075 6076 6077 /* 6078 Floating Point Store Instructions 6079 */ 6080 static Bool dis_fp_store ( UInt theInstr ) 6081 { 6082 /* X-Form, D-Form */ 6083 UChar opc1 = ifieldOPC(theInstr); 6084 UChar frS_addr = ifieldRegDS(theInstr); 6085 UChar rA_addr = ifieldRegA(theInstr); 6086 UChar rB_addr = ifieldRegB(theInstr); 6087 UInt opc2 = ifieldOPClo10(theInstr); 6088 UChar b0 = ifieldBIT0(theInstr); 6089 Int uimm16 = ifieldUIMM16(theInstr); 6090 6091 Int simm16 = extend_s_16to32(uimm16); 6092 IRTemp frS = newTemp(Ity_F64); 6093 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6094 IRTemp EA = newTemp(ty); 6095 IRTemp rA = newTemp(ty); 6096 IRTemp rB = newTemp(ty); 6097 6098 assign( frS, getFReg(frS_addr) ); 6099 assign( rA, getIReg(rA_addr) ); 6100 assign( rB, getIReg(rB_addr) ); 6101 6102 /* These are straightforward from a status bits perspective: no 6103 funny status or CR bits affected. For single precision stores, 6104 the values are truncated and denormalised (not rounded) to turn 6105 them into single precision values. */ 6106 6107 switch (opc1) { 6108 6109 case 0x34: // stfs (Store Float Single, PPC32 p518) 6110 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 6111 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 6112 /* Use Iop_TruncF64asF32 to truncate and possible denormalise 6113 the value to be stored in the correct way, without any 6114 rounding. */ 6115 storeBE( mkexpr(EA), 6116 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 6117 break; 6118 6119 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519) 6120 if (rA_addr == 0) 6121 return False; 6122 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 6123 assign( EA, ea_rA_simm(rA_addr, simm16) ); 6124 /* See comment for stfs */ 6125 storeBE( mkexpr(EA), 6126 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 6127 putIReg( rA_addr, mkexpr(EA) ); 6128 break; 6129 6130 case 0x36: // stfd (Store Float Double, PPC32 p513) 6131 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 6132 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 6133 storeBE( mkexpr(EA), mkexpr(frS) ); 6134 break; 6135 6136 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514) 6137 if (rA_addr == 0) 6138 return False; 6139 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 6140 assign( EA, ea_rA_simm(rA_addr, simm16) ); 6141 storeBE( mkexpr(EA), mkexpr(frS) ); 6142 putIReg( rA_addr, mkexpr(EA) ); 6143 break; 6144 6145 case 0x1F: 6146 if (b0 != 0) { 6147 vex_printf("dis_fp_store(ppc)(instr,b0)\n"); 6148 return False; 6149 } 6150 switch(opc2) { 6151 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521) 6152 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 6153 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6154 /* See note for stfs */ 6155 storeBE( mkexpr(EA), 6156 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 6157 break; 6158 6159 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520) 6160 if (rA_addr == 0) 6161 return False; 6162 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 6163 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 6164 /* See note for stfs */ 6165 storeBE( mkexpr(EA), 6166 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 6167 putIReg( rA_addr, mkexpr(EA) ); 6168 break; 6169 6170 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516) 6171 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 6172 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6173 storeBE( mkexpr(EA), mkexpr(frS) ); 6174 break; 6175 6176 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515) 6177 if (rA_addr == 0) 6178 return False; 6179 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 6180 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 6181 storeBE( mkexpr(EA), mkexpr(frS) ); 6182 putIReg( rA_addr, mkexpr(EA) ); 6183 break; 6184 6185 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517) 6186 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 6187 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 6188 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6189 storeBE( mkexpr(EA), 6190 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) ); 6191 break; 6192 6193 default: 6194 vex_printf("dis_fp_store(ppc)(opc2)\n"); 6195 return False; 6196 } 6197 break; 6198 6199 default: 6200 vex_printf("dis_fp_store(ppc)(opc1)\n"); 6201 return False; 6202 } 6203 return True; 6204 } 6205 6206 6207 6208 /* 6209 Floating Point Arith Instructions 6210 */ 6211 static Bool dis_fp_arith ( UInt theInstr ) 6212 { 6213 /* A-Form */ 6214 UChar opc1 = ifieldOPC(theInstr); 6215 UChar frD_addr = ifieldRegDS(theInstr); 6216 UChar frA_addr = ifieldRegA(theInstr); 6217 UChar frB_addr = ifieldRegB(theInstr); 6218 UChar frC_addr = ifieldRegC(theInstr); 6219 UChar opc2 = ifieldOPClo5(theInstr); 6220 UChar flag_rC = ifieldBIT0(theInstr); 6221 6222 IRTemp frD = newTemp(Ity_F64); 6223 IRTemp frA = newTemp(Ity_F64); 6224 IRTemp frB = newTemp(Ity_F64); 6225 IRTemp frC = newTemp(Ity_F64); 6226 IRExpr* rm = get_IR_roundingmode(); 6227 6228 /* By default, we will examine the results of the operation and set 6229 fpscr[FPRF] accordingly. */ 6230 Bool set_FPRF = True; 6231 6232 /* By default, if flag_RC is set, we will clear cr1 after the 6233 operation. In reality we should set cr1 to indicate the 6234 exception status of the operation, but since we're not 6235 simulating exceptions, the exception status will appear to be 6236 zero. Hence cr1 should be cleared if this is a . form insn. */ 6237 Bool clear_CR1 = True; 6238 6239 assign( frA, getFReg(frA_addr)); 6240 assign( frB, getFReg(frB_addr)); 6241 assign( frC, getFReg(frC_addr)); 6242 6243 switch (opc1) { 6244 case 0x3B: 6245 switch (opc2) { 6246 case 0x12: // fdivs (Floating Divide Single, PPC32 p407) 6247 if (frC_addr != 0) 6248 return False; 6249 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6250 frD_addr, frA_addr, frB_addr); 6251 assign( frD, triop( Iop_DivF64r32, 6252 rm, mkexpr(frA), mkexpr(frB) )); 6253 break; 6254 6255 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430) 6256 if (frC_addr != 0) 6257 return False; 6258 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6259 frD_addr, frA_addr, frB_addr); 6260 assign( frD, triop( Iop_SubF64r32, 6261 rm, mkexpr(frA), mkexpr(frB) )); 6262 break; 6263 6264 case 0x15: // fadds (Floating Add Single, PPC32 p401) 6265 if (frC_addr != 0) 6266 return False; 6267 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6268 frD_addr, frA_addr, frB_addr); 6269 assign( frD, triop( Iop_AddF64r32, 6270 rm, mkexpr(frA), mkexpr(frB) )); 6271 break; 6272 6273 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428) 6274 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 6275 if (frA_addr != 0 || frC_addr != 0) 6276 return False; 6277 DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"", 6278 frD_addr, frB_addr); 6279 // however illogically, on ppc970 this insn behaves identically 6280 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32. 6281 assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) )); 6282 break; 6283 6284 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421) 6285 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 6286 if (frA_addr != 0 || frC_addr != 0) 6287 return False; 6288 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"", 6289 frD_addr, frB_addr); 6290 { IRExpr* ieee_one 6291 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 6292 assign( frD, triop( Iop_DivF64r32, 6293 rm, 6294 ieee_one, mkexpr(frB) )); 6295 } 6296 break; 6297 6298 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414) 6299 if (frB_addr != 0) 6300 return False; 6301 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6302 frD_addr, frA_addr, frC_addr); 6303 assign( frD, triop( Iop_MulF64r32, 6304 rm, mkexpr(frA), mkexpr(frC) )); 6305 break; 6306 6307 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single) 6308 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 6309 // Undocumented instruction? 6310 if (frA_addr != 0 || frC_addr != 0) 6311 return False; 6312 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"", 6313 frD_addr, frB_addr); 6314 assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) ); 6315 break; 6316 6317 default: 6318 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n"); 6319 return False; 6320 } 6321 break; 6322 6323 case 0x3F: 6324 switch (opc2) { 6325 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406) 6326 if (frC_addr != 0) 6327 return False; 6328 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6329 frD_addr, frA_addr, frB_addr); 6330 assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) ); 6331 break; 6332 6333 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429) 6334 if (frC_addr != 0) 6335 return False; 6336 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6337 frD_addr, frA_addr, frB_addr); 6338 assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) ); 6339 break; 6340 6341 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400) 6342 if (frC_addr != 0) 6343 return False; 6344 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6345 frD_addr, frA_addr, frB_addr); 6346 assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) ); 6347 break; 6348 6349 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427) 6350 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 6351 if (frA_addr != 0 || frC_addr != 0) 6352 return False; 6353 DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"", 6354 frD_addr, frB_addr); 6355 assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) ); 6356 break; 6357 6358 case 0x17: { // fsel (Floating Select, PPC32 p426) 6359 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 6360 IRTemp cc = newTemp(Ity_I32); 6361 IRTemp cc_b0 = newTemp(Ity_I32); 6362 6363 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6364 frD_addr, frA_addr, frC_addr, frB_addr); 6365 6366 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40 6367 // => GT|EQ == (cc & 0x1 == 0) 6368 assign( cc, binop(Iop_CmpF64, mkexpr(frA), 6369 IRExpr_Const(IRConst_F64(0))) ); 6370 assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) ); 6371 6372 // frD = (frA >= 0.0) ? frC : frB 6373 // = (cc_b0 == 0) ? frC : frB 6374 assign( frD, 6375 IRExpr_Mux0X( 6376 unop(Iop_1Uto8, 6377 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0))), 6378 mkexpr(frB), 6379 mkexpr(frC) )); 6380 6381 /* One of the rare ones which don't mess with FPRF */ 6382 set_FPRF = False; 6383 break; 6384 } 6385 6386 case 0x18: // fre (Floating Reciprocal Estimate) 6387 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 6388 // Note: unclear whether this insn really exists or not 6389 // ppc970 doesn't have it, but POWER5 does 6390 if (frA_addr != 0 || frC_addr != 0) 6391 return False; 6392 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"", 6393 frD_addr, frB_addr); 6394 { IRExpr* ieee_one 6395 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 6396 assign( frD, triop( Iop_DivF64, 6397 rm, 6398 ieee_one, mkexpr(frB) )); 6399 } 6400 break; 6401 6402 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413) 6403 if (frB_addr != 0) 6404 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n"); 6405 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6406 frD_addr, frA_addr, frC_addr); 6407 assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) ); 6408 break; 6409 6410 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424) 6411 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 6412 if (frA_addr != 0 || frC_addr != 0) 6413 return False; 6414 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"", 6415 frD_addr, frB_addr); 6416 assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) ); 6417 break; 6418 6419 default: 6420 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n"); 6421 return False; 6422 } 6423 break; 6424 6425 default: 6426 vex_printf("dis_fp_arith(ppc)(opc1)\n"); 6427 return False; 6428 } 6429 6430 putFReg( frD_addr, mkexpr(frD) ); 6431 6432 if (set_FPRF) { 6433 // XXX XXX XXX FIXME 6434 // set FPRF from frD 6435 } 6436 6437 if (flag_rC && clear_CR1) { 6438 putCR321( 1, mkU8(0) ); 6439 putCR0( 1, mkU8(0) ); 6440 } 6441 6442 return True; 6443 } 6444 6445 6446 6447 /* 6448 Floating Point Mult-Add Instructions 6449 */ 6450 static Bool dis_fp_multadd ( UInt theInstr ) 6451 { 6452 /* A-Form */ 6453 UChar opc1 = ifieldOPC(theInstr); 6454 UChar frD_addr = ifieldRegDS(theInstr); 6455 UChar frA_addr = ifieldRegA(theInstr); 6456 UChar frB_addr = ifieldRegB(theInstr); 6457 UChar frC_addr = ifieldRegC(theInstr); 6458 UChar opc2 = ifieldOPClo5(theInstr); 6459 UChar flag_rC = ifieldBIT0(theInstr); 6460 6461 IRTemp frD = newTemp(Ity_F64); 6462 IRTemp frA = newTemp(Ity_F64); 6463 IRTemp frB = newTemp(Ity_F64); 6464 IRTemp frC = newTemp(Ity_F64); 6465 IRTemp rmt = newTemp(Ity_I32); 6466 IRExpr* rm; 6467 6468 /* By default, we will examine the results of the operation and set 6469 fpscr[FPRF] accordingly. */ 6470 Bool set_FPRF = True; 6471 6472 /* By default, if flag_RC is set, we will clear cr1 after the 6473 operation. In reality we should set cr1 to indicate the 6474 exception status of the operation, but since we're not 6475 simulating exceptions, the exception status will appear to be 6476 zero. Hence cr1 should be cleared if this is a . form insn. */ 6477 Bool clear_CR1 = True; 6478 6479 /* Bind the rounding mode expression to a temp; there's no 6480 point in creating gratuitous CSEs, as we know we'll need 6481 to use it twice. */ 6482 assign( rmt, get_IR_roundingmode() ); 6483 rm = mkexpr(rmt); 6484 6485 assign( frA, getFReg(frA_addr)); 6486 assign( frB, getFReg(frB_addr)); 6487 assign( frC, getFReg(frC_addr)); 6488 6489 /* The rounding in this is all a bit dodgy. The idea is to only do 6490 one rounding. That clearly isn't achieveable without dedicated 6491 four-input IR primops, although in the single precision case we 6492 can sort-of simulate it by doing the inner multiply in double 6493 precision. 6494 6495 In the negated cases, the negation happens after rounding. */ 6496 6497 switch (opc1) { 6498 case 0x3B: 6499 switch (opc2) { 6500 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412) 6501 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6502 frD_addr, frA_addr, frC_addr, frB_addr); 6503 assign( frD, qop( Iop_MSubF64r32, rm, 6504 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 6505 break; 6506 6507 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409) 6508 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6509 frD_addr, frA_addr, frC_addr, frB_addr); 6510 assign( frD, qop( Iop_MAddF64r32, rm, 6511 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 6512 break; 6513 6514 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420) 6515 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6516 frD_addr, frA_addr, frC_addr, frB_addr); 6517 assign( frD, unop( Iop_NegF64, 6518 qop( Iop_MSubF64r32, rm, 6519 mkexpr(frA), mkexpr(frC), mkexpr(frB) ))); 6520 break; 6521 6522 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418) 6523 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6524 frD_addr, frA_addr, frC_addr, frB_addr); 6525 assign( frD, unop( Iop_NegF64, 6526 qop( Iop_MAddF64r32, rm, 6527 mkexpr(frA), mkexpr(frC), mkexpr(frB) ))); 6528 break; 6529 6530 default: 6531 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n"); 6532 return False; 6533 } 6534 break; 6535 6536 case 0x3F: 6537 switch (opc2) { 6538 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411) 6539 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6540 frD_addr, frA_addr, frC_addr, frB_addr); 6541 assign( frD, qop( Iop_MSubF64, rm, 6542 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 6543 break; 6544 6545 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408) 6546 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6547 frD_addr, frA_addr, frC_addr, frB_addr); 6548 assign( frD, qop( Iop_MAddF64, rm, 6549 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 6550 break; 6551 6552 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419) 6553 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6554 frD_addr, frA_addr, frC_addr, frB_addr); 6555 assign( frD, unop( Iop_NegF64, 6556 qop( Iop_MSubF64, rm, 6557 mkexpr(frA), mkexpr(frC), mkexpr(frB) ))); 6558 break; 6559 6560 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417) 6561 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 6562 frD_addr, frA_addr, frC_addr, frB_addr); 6563 assign( frD, unop( Iop_NegF64, 6564 qop( Iop_MAddF64, rm, 6565 mkexpr(frA), mkexpr(frC), mkexpr(frB) ))); 6566 break; 6567 6568 default: 6569 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n"); 6570 return False; 6571 } 6572 break; 6573 6574 default: 6575 vex_printf("dis_fp_multadd(ppc)(opc1)\n"); 6576 return False; 6577 } 6578 6579 putFReg( frD_addr, mkexpr(frD) ); 6580 6581 if (set_FPRF) { 6582 // XXX XXX XXX FIXME 6583 // set FPRF from frD 6584 } 6585 6586 if (flag_rC && clear_CR1) { 6587 putCR321( 1, mkU8(0) ); 6588 putCR0( 1, mkU8(0) ); 6589 } 6590 6591 return True; 6592 } 6593 6594 6595 6596 /* 6597 Floating Point Compare Instructions 6598 */ 6599 static Bool dis_fp_cmp ( UInt theInstr ) 6600 { 6601 /* X-Form */ 6602 UChar opc1 = ifieldOPC(theInstr); 6603 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 6604 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 6605 UChar frA_addr = ifieldRegA(theInstr); 6606 UChar frB_addr = ifieldRegB(theInstr); 6607 UInt opc2 = ifieldOPClo10(theInstr); 6608 UChar b0 = ifieldBIT0(theInstr); 6609 6610 IRTemp ccIR = newTemp(Ity_I32); 6611 IRTemp ccPPC32 = newTemp(Ity_I32); 6612 6613 IRTemp frA = newTemp(Ity_F64); 6614 IRTemp frB = newTemp(Ity_F64); 6615 6616 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) { 6617 vex_printf("dis_fp_cmp(ppc)(instr)\n"); 6618 return False; 6619 } 6620 6621 assign( frA, getFReg(frA_addr)); 6622 assign( frB, getFReg(frB_addr)); 6623 6624 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) ); 6625 6626 /* Map compare result from IR to PPC32 */ 6627 /* 6628 FP cmp result | PPC | IR 6629 -------------------------- 6630 UN | 0x1 | 0x45 6631 EQ | 0x2 | 0x40 6632 GT | 0x4 | 0x00 6633 LT | 0x8 | 0x01 6634 */ 6635 6636 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2) 6637 // | ((ccIR ^ (ccIR>>6)) & 1) 6638 assign( 6639 ccPPC32, 6640 binop( 6641 Iop_Shl32, 6642 mkU32(1), 6643 unop( 6644 Iop_32to8, 6645 binop( 6646 Iop_Or32, 6647 binop( 6648 Iop_And32, 6649 unop( 6650 Iop_Not32, 6651 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5)) 6652 ), 6653 mkU32(2) 6654 ), 6655 binop( 6656 Iop_And32, 6657 binop( 6658 Iop_Xor32, 6659 mkexpr(ccIR), 6660 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6)) 6661 ), 6662 mkU32(1) 6663 ) 6664 ) 6665 ) 6666 ) 6667 ); 6668 6669 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 6670 6671 /* CAB: TODO?: Support writing cc to FPSCR->FPCC ? 6672 putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 ); 6673 */ 6674 // XXX XXX XXX FIXME 6675 // Also write the result into FPRF (it's not entirely clear how) 6676 6677 /* Note: Differences between fcmpu and fcmpo are only in exception 6678 flag settings, which aren't supported anyway. */ 6679 switch (opc2) { 6680 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403) 6681 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 6682 break; 6683 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402) 6684 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 6685 break; 6686 default: 6687 vex_printf("dis_fp_cmp(ppc)(opc2)\n"); 6688 return False; 6689 } 6690 return True; 6691 } 6692 6693 6694 6695 /* 6696 Floating Point Rounding/Conversion Instructions 6697 */ 6698 static Bool dis_fp_round ( UInt theInstr ) 6699 { 6700 /* X-Form */ 6701 UChar opc1 = ifieldOPC(theInstr); 6702 UChar b16to20 = ifieldRegA(theInstr); 6703 UChar frD_addr = ifieldRegDS(theInstr); 6704 UChar frB_addr = ifieldRegB(theInstr); 6705 UInt opc2 = ifieldOPClo10(theInstr); 6706 UChar flag_rC = ifieldBIT0(theInstr); 6707 6708 IRTemp frD = newTemp(Ity_F64); 6709 IRTemp frB = newTemp(Ity_F64); 6710 IRTemp r_tmp32 = newTemp(Ity_I32); 6711 IRTemp r_tmp64 = newTemp(Ity_I64); 6712 IRExpr* rm = get_IR_roundingmode(); 6713 6714 /* By default, we will examine the results of the operation and set 6715 fpscr[FPRF] accordingly. */ 6716 Bool set_FPRF = True; 6717 6718 /* By default, if flag_RC is set, we will clear cr1 after the 6719 operation. In reality we should set cr1 to indicate the 6720 exception status of the operation, but since we're not 6721 simulating exceptions, the exception status will appear to be 6722 zero. Hence cr1 should be cleared if this is a . form insn. */ 6723 Bool clear_CR1 = True; 6724 6725 if (opc1 != 0x3F || b16to20 != 0) { 6726 vex_printf("dis_fp_round(ppc)(instr)\n"); 6727 return False; 6728 } 6729 6730 assign( frB, getFReg(frB_addr)); 6731 6732 switch (opc2) { 6733 case 0x00C: // frsp (Float Round to Single, PPC32 p423) 6734 DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6735 assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) )); 6736 break; 6737 6738 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404) 6739 DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6740 assign( r_tmp32, 6741 binop(Iop_F64toI32S, rm, mkexpr(frB)) ); 6742 assign( frD, unop( Iop_ReinterpI64asF64, 6743 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 6744 /* FPRF is undefined after fctiw. Leave unchanged. */ 6745 set_FPRF = False; 6746 break; 6747 6748 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405) 6749 DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6750 assign( r_tmp32, 6751 binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) )); 6752 assign( frD, unop( Iop_ReinterpI64asF64, 6753 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 6754 /* FPRF is undefined after fctiwz. Leave unchanged. */ 6755 set_FPRF = False; 6756 break; 6757 6758 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437) 6759 DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6760 assign( r_tmp64, 6761 binop(Iop_F64toI64S, rm, mkexpr(frB)) ); 6762 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 6763 /* FPRF is undefined after fctid. Leave unchanged. */ 6764 set_FPRF = False; 6765 break; 6766 6767 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437) 6768 DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6769 assign( r_tmp64, 6770 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 6771 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 6772 /* FPRF is undefined after fctidz. Leave unchanged. */ 6773 set_FPRF = False; 6774 break; 6775 6776 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434) 6777 DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6778 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 6779 assign( frD, 6780 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) ); 6781 break; 6782 6783 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim 6784 switch(opc2) { 6785 case 0x188: // frin (Floating Round to Integer Nearest) 6786 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6787 assign( r_tmp64, 6788 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) ); 6789 break; 6790 case 0x1A8: // friz (Floating Round to Integer Toward Zero) 6791 DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6792 assign( r_tmp64, 6793 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 6794 break; 6795 case 0x1C8: // frip (Floating Round to Integer Plus) 6796 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6797 assign( r_tmp64, 6798 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) ); 6799 break; 6800 case 0x1E8: // frim (Floating Round to Integer Minus) 6801 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6802 assign( r_tmp64, 6803 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) ); 6804 break; 6805 } 6806 6807 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 6808 /* F64 has only log10(2**52) significant digits anyway */ 6809 /* need to preserve sign of zero */ 6810 /* frD = (fabs(frB) > 9e18) ? frB : 6811 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */ 6812 assign(frD, IRExpr_Mux0X( unop(Iop_32to8, 6813 binop(Iop_CmpF64, 6814 IRExpr_Const(IRConst_F64(9e18)), 6815 unop(Iop_AbsF64, mkexpr(frB)))), 6816 IRExpr_Mux0X(unop(Iop_32to8, 6817 binop(Iop_Shr32, 6818 unop(Iop_64HIto32, 6819 unop(Iop_ReinterpF64asI64, 6820 mkexpr(frB))), mkU8(31))), 6821 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ), 6822 unop(Iop_NegF64, 6823 unop( Iop_AbsF64, 6824 binop(Iop_I64StoF64, mkU32(0), 6825 mkexpr(r_tmp64)) )) ), 6826 mkexpr(frB))); 6827 break; 6828 6829 default: 6830 vex_printf("dis_fp_round(ppc)(opc2)\n"); 6831 return False; 6832 } 6833 6834 putFReg( frD_addr, mkexpr(frD) ); 6835 6836 if (set_FPRF) { 6837 // XXX XXX XXX FIXME 6838 // set FPRF from frD 6839 } 6840 6841 if (flag_rC && clear_CR1) { 6842 putCR321( 1, mkU8(0) ); 6843 putCR0( 1, mkU8(0) ); 6844 } 6845 6846 return True; 6847 } 6848 6849 /* 6850 Floating Point Pair Instructions 6851 */ 6852 static Bool dis_fp_pair ( UInt theInstr ) 6853 { 6854 /* X-Form/DS-Form */ 6855 UChar opc1 = ifieldOPC(theInstr); 6856 UChar frT_hi_addr = ifieldRegDS(theInstr); 6857 UChar frT_lo_addr = frT_hi_addr + 1; 6858 UChar rA_addr = ifieldRegA(theInstr); 6859 UChar rB_addr = ifieldRegB(theInstr); 6860 UInt uimm16 = ifieldUIMM16(theInstr); 6861 Int simm16 = extend_s_16to32(uimm16); 6862 UInt opc2 = ifieldOPClo10(theInstr); 6863 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6864 IRTemp EA_hi = newTemp(ty); 6865 IRTemp EA_lo = newTemp(ty); 6866 IRTemp frT_hi = newTemp(Ity_F64); 6867 IRTemp frT_lo = newTemp(Ity_F64); 6868 UChar b0 = ifieldBIT0(theInstr); 6869 Bool is_load = 0; 6870 6871 if ((frT_hi_addr %2) != 0) { 6872 vex_printf("dis_fp_pair(ppc) : odd frT register\n"); 6873 return False; 6874 } 6875 6876 switch (opc1) { 6877 case 0x1F: // register offset 6878 switch(opc2) { 6879 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125) 6880 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 6881 is_load = 1; 6882 break; 6883 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125) 6884 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 6885 break; 6886 default: 6887 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n"); 6888 return False; 6889 } 6890 6891 if (b0 != 0) { 6892 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n"); 6893 return False; 6894 } 6895 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6896 break; 6897 case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125) 6898 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 6899 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 6900 is_load = 1; 6901 break; 6902 case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125) 6903 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 6904 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 6905 break; 6906 default: // immediate offset 6907 vex_printf("dis_fp_pair(ppc)(instr)\n"); 6908 return False; 6909 } 6910 6911 if (mode64) 6912 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) ); 6913 else 6914 assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) ); 6915 6916 assign( frT_hi, getFReg(frT_hi_addr) ); 6917 assign( frT_lo, getFReg(frT_lo_addr) ); 6918 6919 if (is_load) { 6920 putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) ); 6921 putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) ); 6922 } else { 6923 storeBE( mkexpr(EA_hi), mkexpr(frT_hi) ); 6924 storeBE( mkexpr(EA_lo), mkexpr(frT_lo) ); 6925 } 6926 6927 return True; 6928 } 6929 6930 6931 /* 6932 Floating Point Move Instructions 6933 */ 6934 static Bool dis_fp_move ( UInt theInstr ) 6935 { 6936 /* X-Form */ 6937 UChar opc1 = ifieldOPC(theInstr); 6938 UChar frD_addr = ifieldRegDS(theInstr); 6939 UChar frA_addr = ifieldRegA(theInstr); 6940 UChar frB_addr = ifieldRegB(theInstr); 6941 UInt opc2 = ifieldOPClo10(theInstr); 6942 UChar flag_rC = ifieldBIT0(theInstr); 6943 6944 IRTemp frD = newTemp(Ity_F64); 6945 IRTemp frB = newTemp(Ity_F64); 6946 IRTemp itmpB = newTemp(Ity_F64); 6947 IRTemp frA; 6948 IRTemp signA; 6949 IRTemp hiD; 6950 6951 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) { 6952 vex_printf("dis_fp_move(ppc)(instr)\n"); 6953 return False; 6954 } 6955 6956 assign( frB, getFReg(frB_addr)); 6957 6958 switch (opc2) { 6959 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126) 6960 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr, 6961 frB_addr); 6962 signA = newTemp(Ity_I32); 6963 hiD = newTemp(Ity_I32); 6964 itmpB = newTemp(Ity_I64); 6965 frA = newTemp(Ity_F64); 6966 assign( frA, getFReg(frA_addr) ); 6967 6968 /* get A's sign bit */ 6969 assign(signA, binop(Iop_And32, 6970 unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64, 6971 mkexpr(frA))), 6972 mkU32(0x80000000)) ); 6973 6974 assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) ); 6975 6976 /* mask off B's sign bit and or in A's sign bit */ 6977 assign(hiD, binop(Iop_Or32, 6978 binop(Iop_And32, 6979 unop(Iop_64HIto32, 6980 mkexpr(itmpB)), /* frB's high 32 bits */ 6981 mkU32(0x7fffffff)), 6982 mkexpr(signA)) ); 6983 6984 /* combine hiD/loB into frD */ 6985 assign( frD, unop(Iop_ReinterpI64asF64, 6986 binop(Iop_32HLto64, 6987 mkexpr(hiD), 6988 unop(Iop_64to32, 6989 mkexpr(itmpB)))) ); /* frB's low 32 bits */ 6990 break; 6991 6992 case 0x028: // fneg (Floating Negate, PPC32 p416) 6993 DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6994 assign( frD, unop( Iop_NegF64, mkexpr(frB) )); 6995 break; 6996 6997 case 0x048: // fmr (Floating Move Register, PPC32 p410) 6998 DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 6999 assign( frD, mkexpr(frB) ); 7000 break; 7001 7002 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415) 7003 DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7004 assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) ))); 7005 break; 7006 7007 case 0x108: // fabs (Floating Absolute Value, PPC32 p399) 7008 DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7009 assign( frD, unop( Iop_AbsF64, mkexpr(frB) )); 7010 break; 7011 7012 default: 7013 vex_printf("dis_fp_move(ppc)(opc2)\n"); 7014 return False; 7015 } 7016 7017 putFReg( frD_addr, mkexpr(frD) ); 7018 7019 /* None of these change FPRF. cr1 is set in the usual way though, 7020 if flag_rC is set. */ 7021 7022 if (flag_rC) { 7023 putCR321( 1, mkU8(0) ); 7024 putCR0( 1, mkU8(0) ); 7025 } 7026 7027 return True; 7028 } 7029 7030 7031 7032 /* 7033 Floating Point Status/Control Register Instructions 7034 */ 7035 static Bool dis_fp_scr ( UInt theInstr ) 7036 { 7037 /* Many forms - see each switch case */ 7038 UChar opc1 = ifieldOPC(theInstr); 7039 UInt opc2 = ifieldOPClo10(theInstr); 7040 UChar flag_rC = ifieldBIT0(theInstr); 7041 7042 if (opc1 != 0x3F) { 7043 vex_printf("dis_fp_scr(ppc)(instr)\n"); 7044 return False; 7045 } 7046 7047 switch (opc2) { 7048 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479) 7049 // Bit crbD of the FPSCR is set. 7050 UChar crbD = ifieldRegDS(theInstr); 7051 UInt b11to20 = IFIELD(theInstr, 11, 10); 7052 7053 if (b11to20 != 0) { 7054 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n"); 7055 return False; 7056 } 7057 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD); 7058 putGST_masked( PPC_GST_FPSCR, mkU32(1<<(31-crbD)), 1<<(31-crbD) ); 7059 break; 7060 } 7061 7062 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465) 7063 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 7064 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 7065 UChar crfS = toUChar( IFIELD( theInstr, 18, 3 ) ); 7066 UChar b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) ); 7067 IRTemp tmp = newTemp(Ity_I32); 7068 IRExpr* fpscr_all; 7069 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) { 7070 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n"); 7071 return False; 7072 } 7073 DIP("mcrfs crf%d,crf%d\n", crfD, crfS); 7074 vassert(crfD < 8); 7075 vassert(crfS < 8); 7076 fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 7077 assign( tmp, binop(Iop_And32, 7078 binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))), 7079 mkU32(0xF)) ); 7080 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD ); 7081 break; 7082 } 7083 7084 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478) 7085 // Bit crbD of the FPSCR is cleared. 7086 UChar crbD = ifieldRegDS(theInstr); 7087 UInt b11to20 = IFIELD(theInstr, 11, 10); 7088 7089 if (b11to20 != 0) { 7090 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n"); 7091 return False; 7092 } 7093 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD); 7094 putGST_masked( PPC_GST_FPSCR, mkU32(0), 1<<(31-crbD) ); 7095 break; 7096 } 7097 7098 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481) 7099 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 7100 UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) ); 7101 UChar IMM = toUChar( IFIELD( theInstr, 12, 4 ) ); 7102 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 7103 7104 if (b16to22 != 0 || b11 != 0) { 7105 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n"); 7106 return False; 7107 } 7108 DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM); 7109 putGST_field( PPC_GST_FPSCR, mkU32(IMM), crfD ); 7110 break; 7111 } 7112 7113 case 0x247: { // mffs (Move from FPSCR, PPC32 p468) 7114 UChar frD_addr = ifieldRegDS(theInstr); 7115 UInt b11to20 = IFIELD(theInstr, 11, 10); 7116 IRExpr* fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 7117 7118 if (b11to20 != 0) { 7119 vex_printf("dis_fp_scr(ppc)(instr,mffs)\n"); 7120 return False; 7121 } 7122 DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr); 7123 putFReg( frD_addr, 7124 unop( Iop_ReinterpI64asF64, 7125 unop( Iop_32Uto64, fpscr_all ))); 7126 break; 7127 } 7128 7129 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480) 7130 UChar b25 = toUChar( IFIELD(theInstr, 25, 1) ); 7131 UChar FM = toUChar( IFIELD(theInstr, 17, 8) ); 7132 UChar frB_addr = ifieldRegB(theInstr); 7133 IRTemp frB = newTemp(Ity_F64); 7134 IRTemp rB_32 = newTemp(Ity_I32); 7135 Int i, mask; 7136 7137 if (b25 == 1) { 7138 /* new 64 bit move variant for power 6. If L field (bit 25) is 7139 * a one do a full 64 bit move. Note, the FPSCR is not really 7140 * properly modeled. This instruciton only changes the value of 7141 * the rounding mode. The HW exception bits do not get set in 7142 * the simulator. 1/12/09 7143 */ 7144 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr); 7145 mask = 0xFF; 7146 7147 } else { 7148 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr); 7149 // Build 32bit mask from FM: 7150 mask = 0; 7151 for (i=0; i<8; i++) { 7152 if ((FM & (1<<(7-i))) == 1) { 7153 mask |= 0xF << (7-i); 7154 } 7155 } 7156 } 7157 assign( frB, getFReg(frB_addr)); 7158 assign( rB_32, unop( Iop_64to32, 7159 unop( Iop_ReinterpF64asI64, mkexpr(frB) ))); 7160 putGST_masked( PPC_GST_FPSCR, mkexpr(rB_32), mask ); 7161 break; 7162 } 7163 7164 default: 7165 vex_printf("dis_fp_scr(ppc)(opc2)\n"); 7166 return False; 7167 } 7168 return True; 7169 } 7170 7171 7172 7173 /*------------------------------------------------------------*/ 7174 /*--- AltiVec Instruction Translation ---*/ 7175 /*------------------------------------------------------------*/ 7176 7177 /* 7178 Altivec Cache Control Instructions (Data Streams) 7179 */ 7180 static Bool dis_av_datastream ( UInt theInstr ) 7181 { 7182 /* X-Form */ 7183 UChar opc1 = ifieldOPC(theInstr); 7184 UChar flag_T = toUChar( IFIELD( theInstr, 25, 1 ) ); 7185 UChar flag_A = flag_T; 7186 UChar b23to24 = toUChar( IFIELD( theInstr, 23, 2 ) ); 7187 UChar STRM = toUChar( IFIELD( theInstr, 21, 2 ) ); 7188 UChar rA_addr = ifieldRegA(theInstr); 7189 UChar rB_addr = ifieldRegB(theInstr); 7190 UInt opc2 = ifieldOPClo10(theInstr); 7191 UChar b0 = ifieldBIT0(theInstr); 7192 7193 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) { 7194 vex_printf("dis_av_datastream(ppc)(instr)\n"); 7195 return False; 7196 } 7197 7198 switch (opc2) { 7199 case 0x156: // dst (Data Stream Touch, AV p115) 7200 DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "", 7201 rA_addr, rB_addr, STRM); 7202 break; 7203 7204 case 0x176: // dstst (Data Stream Touch for Store, AV p117) 7205 DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "", 7206 rA_addr, rB_addr, STRM); 7207 break; 7208 7209 case 0x336: // dss (Data Stream Stop, AV p114) 7210 if (rA_addr != 0 || rB_addr != 0) { 7211 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n"); 7212 return False; 7213 } 7214 if (flag_A == 0) { 7215 DIP("dss %d\n", STRM); 7216 } else { 7217 DIP("dssall\n"); 7218 } 7219 break; 7220 7221 default: 7222 vex_printf("dis_av_datastream(ppc)(opc2)\n"); 7223 return False; 7224 } 7225 return True; 7226 } 7227 7228 /* 7229 AltiVec Processor Control Instructions 7230 */ 7231 static Bool dis_av_procctl ( UInt theInstr ) 7232 { 7233 /* VX-Form */ 7234 UChar opc1 = ifieldOPC(theInstr); 7235 UChar vD_addr = ifieldRegDS(theInstr); 7236 UChar vA_addr = ifieldRegA(theInstr); 7237 UChar vB_addr = ifieldRegB(theInstr); 7238 UInt opc2 = IFIELD( theInstr, 0, 11 ); 7239 7240 if (opc1 != 0x4) { 7241 vex_printf("dis_av_procctl(ppc)(instr)\n"); 7242 return False; 7243 } 7244 7245 switch (opc2) { 7246 case 0x604: // mfvscr (Move from VSCR, AV p129) 7247 if (vA_addr != 0 || vB_addr != 0) { 7248 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 7249 return False; 7250 } 7251 DIP("mfvscr v%d\n", vD_addr); 7252 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) ); 7253 break; 7254 7255 case 0x644: { // mtvscr (Move to VSCR, AV p130) 7256 IRTemp vB = newTemp(Ity_V128); 7257 if (vD_addr != 0 || vA_addr != 0) { 7258 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 7259 return False; 7260 } 7261 DIP("mtvscr v%d\n", vB_addr); 7262 assign( vB, getVReg(vB_addr)); 7263 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) ); 7264 break; 7265 } 7266 default: 7267 vex_printf("dis_av_procctl(ppc)(opc2)\n"); 7268 return False; 7269 } 7270 return True; 7271 } 7272 7273 /* 7274 AltiVec Load Instructions 7275 */ 7276 static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr ) 7277 { 7278 /* X-Form */ 7279 UChar opc1 = ifieldOPC(theInstr); 7280 UChar vD_addr = ifieldRegDS(theInstr); 7281 UChar rA_addr = ifieldRegA(theInstr); 7282 UChar rB_addr = ifieldRegB(theInstr); 7283 UInt opc2 = ifieldOPClo10(theInstr); 7284 UChar b0 = ifieldBIT0(theInstr); 7285 7286 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7287 IRTemp EA = newTemp(ty); 7288 IRTemp EA_align16 = newTemp(ty); 7289 7290 if (opc1 != 0x1F || b0 != 0) { 7291 vex_printf("dis_av_load(ppc)(instr)\n"); 7292 return False; 7293 } 7294 7295 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7296 assign( EA_align16, addr_align( mkexpr(EA), 16 ) ); 7297 7298 switch (opc2) { 7299 7300 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123) 7301 IRDirty* d; 7302 UInt vD_off = vectorGuestRegOffset(vD_addr); 7303 IRExpr** args = mkIRExprVec_3( 7304 mkU32(vD_off), 7305 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 7306 mkU32(0xF)), 7307 mkU32(0)/*left*/ ); 7308 if (!mode64) { 7309 d = unsafeIRDirty_0_N ( 7310 0/*regparms*/, 7311 "ppc32g_dirtyhelper_LVS", 7312 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 7313 args ); 7314 } else { 7315 d = unsafeIRDirty_0_N ( 7316 0/*regparms*/, 7317 "ppc64g_dirtyhelper_LVS", 7318 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 7319 args ); 7320 } 7321 DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 7322 /* declare guest state effects */ 7323 d->needsBBP = True; 7324 d->nFxState = 1; 7325 d->fxState[0].fx = Ifx_Write; 7326 d->fxState[0].offset = vD_off; 7327 d->fxState[0].size = sizeof(U128); 7328 7329 /* execute the dirty call, side-effecting guest state */ 7330 stmt( IRStmt_Dirty(d) ); 7331 break; 7332 } 7333 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125) 7334 IRDirty* d; 7335 UInt vD_off = vectorGuestRegOffset(vD_addr); 7336 IRExpr** args = mkIRExprVec_3( 7337 mkU32(vD_off), 7338 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 7339 mkU32(0xF)), 7340 mkU32(1)/*right*/ ); 7341 if (!mode64) { 7342 d = unsafeIRDirty_0_N ( 7343 0/*regparms*/, 7344 "ppc32g_dirtyhelper_LVS", 7345 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 7346 args ); 7347 } else { 7348 d = unsafeIRDirty_0_N ( 7349 0/*regparms*/, 7350 "ppc64g_dirtyhelper_LVS", 7351 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 7352 args ); 7353 } 7354 DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 7355 /* declare guest state effects */ 7356 d->needsBBP = True; 7357 d->nFxState = 1; 7358 d->fxState[0].fx = Ifx_Write; 7359 d->fxState[0].offset = vD_off; 7360 d->fxState[0].size = sizeof(U128); 7361 7362 /* execute the dirty call, side-effecting guest state */ 7363 stmt( IRStmt_Dirty(d) ); 7364 break; 7365 } 7366 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119) 7367 DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 7368 /* loads addressed byte into vector[EA[0:3] 7369 since all other destination bytes are undefined, 7370 can simply load entire vector from 16-aligned EA */ 7371 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 7372 break; 7373 7374 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121) 7375 DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 7376 /* see note for lvebx */ 7377 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 7378 break; 7379 7380 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122) 7381 DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 7382 /* see note for lvebx */ 7383 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 7384 break; 7385 7386 case 0x067: // lvx (Load Vector Indexed, AV p127) 7387 DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 7388 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 7389 break; 7390 7391 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128) 7392 DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 7393 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 7394 break; 7395 7396 default: 7397 vex_printf("dis_av_load(ppc)(opc2)\n"); 7398 return False; 7399 } 7400 return True; 7401 } 7402 7403 7404 /* 7405 AltiVec Store Instructions 7406 */ 7407 static Bool dis_av_store ( UInt theInstr ) 7408 { 7409 /* X-Form */ 7410 UChar opc1 = ifieldOPC(theInstr); 7411 UChar vS_addr = ifieldRegDS(theInstr); 7412 UChar rA_addr = ifieldRegA(theInstr); 7413 UChar rB_addr = ifieldRegB(theInstr); 7414 UInt opc2 = ifieldOPClo10(theInstr); 7415 UChar b0 = ifieldBIT0(theInstr); 7416 7417 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7418 IRTemp EA = newTemp(ty); 7419 IRTemp addr_aligned = newTemp(ty); 7420 IRTemp vS = newTemp(Ity_V128); 7421 IRTemp eb = newTemp(Ity_I8); 7422 IRTemp idx = newTemp(Ity_I8); 7423 7424 if (opc1 != 0x1F || b0 != 0) { 7425 vex_printf("dis_av_store(ppc)(instr)\n"); 7426 return False; 7427 } 7428 7429 assign( vS, getVReg(vS_addr)); 7430 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7431 7432 switch (opc2) { 7433 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131) 7434 DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 7435 assign( eb, binop(Iop_And8, mkU8(0xF), 7436 unop(Iop_32to8, 7437 mkNarrowTo32(ty, mkexpr(EA)) )) ); 7438 assign( idx, binop(Iop_Shl8, 7439 binop(Iop_Sub8, mkU8(15), mkexpr(eb)), 7440 mkU8(3)) ); 7441 storeBE( mkexpr(EA), 7442 unop(Iop_32to8, unop(Iop_V128to32, 7443 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 7444 break; 7445 } 7446 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132) 7447 DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 7448 assign( addr_aligned, addr_align(mkexpr(EA), 2) ); 7449 assign( eb, binop(Iop_And8, mkU8(0xF), 7450 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 7451 assign( idx, binop(Iop_Shl8, 7452 binop(Iop_Sub8, mkU8(14), mkexpr(eb)), 7453 mkU8(3)) ); 7454 storeBE( mkexpr(addr_aligned), 7455 unop(Iop_32to16, unop(Iop_V128to32, 7456 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 7457 break; 7458 } 7459 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133) 7460 DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 7461 assign( addr_aligned, addr_align(mkexpr(EA), 4) ); 7462 assign( eb, binop(Iop_And8, mkU8(0xF), 7463 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 7464 assign( idx, binop(Iop_Shl8, 7465 binop(Iop_Sub8, mkU8(12), mkexpr(eb)), 7466 mkU8(3)) ); 7467 storeBE( mkexpr(addr_aligned), 7468 unop(Iop_V128to32, 7469 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) ); 7470 break; 7471 } 7472 7473 case 0x0E7: // stvx (Store Vector Indexed, AV p134) 7474 DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 7475 storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 7476 break; 7477 7478 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135) 7479 DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 7480 storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 7481 break; 7482 7483 default: 7484 vex_printf("dis_av_store(ppc)(opc2)\n"); 7485 return False; 7486 } 7487 return True; 7488 } 7489 7490 /* 7491 AltiVec Arithmetic Instructions 7492 */ 7493 static Bool dis_av_arith ( UInt theInstr ) 7494 { 7495 /* VX-Form */ 7496 UChar opc1 = ifieldOPC(theInstr); 7497 UChar vD_addr = ifieldRegDS(theInstr); 7498 UChar vA_addr = ifieldRegA(theInstr); 7499 UChar vB_addr = ifieldRegB(theInstr); 7500 UInt opc2 = IFIELD( theInstr, 0, 11 ); 7501 7502 IRTemp vA = newTemp(Ity_V128); 7503 IRTemp vB = newTemp(Ity_V128); 7504 IRTemp z3 = newTemp(Ity_I64); 7505 IRTemp z2 = newTemp(Ity_I64); 7506 IRTemp z1 = newTemp(Ity_I64); 7507 IRTemp z0 = newTemp(Ity_I64); 7508 IRTemp aEvn, aOdd; 7509 IRTemp a15, a14, a13, a12, a11, a10, a9, a8; 7510 IRTemp a7, a6, a5, a4, a3, a2, a1, a0; 7511 IRTemp b3, b2, b1, b0; 7512 7513 aEvn = aOdd = IRTemp_INVALID; 7514 a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID; 7515 a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID; 7516 b3 = b2 = b1 = b0 = IRTemp_INVALID; 7517 7518 assign( vA, getVReg(vA_addr)); 7519 assign( vB, getVReg(vB_addr)); 7520 7521 if (opc1 != 0x4) { 7522 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n"); 7523 return False; 7524 } 7525 7526 switch (opc2) { 7527 /* Add */ 7528 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136) 7529 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7530 /* unsigned_ov(x+y) = (y >u not(x)) */ 7531 putVReg( vD_addr, binop(Iop_ShrN32x4, 7532 binop(Iop_CmpGT32Ux4, mkexpr(vB), 7533 unop(Iop_NotV128, mkexpr(vA))), 7534 mkU8(31)) ); 7535 break; 7536 } 7537 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141) 7538 DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7539 putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) ); 7540 break; 7541 7542 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143) 7543 DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7544 putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) ); 7545 break; 7546 7547 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145) 7548 DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7549 putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) ); 7550 break; 7551 7552 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142) 7553 DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7554 putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) ); 7555 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16 7556 break; 7557 7558 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144) 7559 DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7560 putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) ); 7561 // TODO: set VSCR[SAT] 7562 break; 7563 7564 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146) 7565 DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7566 putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) ); 7567 // TODO: set VSCR[SAT] 7568 break; 7569 7570 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138) 7571 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7572 putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) ); 7573 // TODO: set VSCR[SAT] 7574 break; 7575 7576 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139) 7577 DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7578 putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) ); 7579 // TODO: set VSCR[SAT] 7580 break; 7581 7582 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140) 7583 DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7584 putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) ); 7585 // TODO: set VSCR[SAT] 7586 break; 7587 7588 7589 /* Subtract */ 7590 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260) 7591 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7592 /* unsigned_ov(x-y) = (y >u x) */ 7593 putVReg( vD_addr, binop(Iop_ShrN32x4, 7594 unop(Iop_NotV128, 7595 binop(Iop_CmpGT32Ux4, mkexpr(vB), 7596 mkexpr(vA))), 7597 mkU8(31)) ); 7598 break; 7599 } 7600 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265) 7601 DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7602 putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) ); 7603 break; 7604 7605 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267) 7606 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7607 putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) ); 7608 break; 7609 7610 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269) 7611 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7612 putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) ); 7613 break; 7614 7615 case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266) 7616 DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7617 putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) ); 7618 // TODO: set VSCR[SAT] 7619 break; 7620 7621 case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268) 7622 DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7623 putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) ); 7624 // TODO: set VSCR[SAT] 7625 break; 7626 7627 case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270) 7628 DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7629 putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) ); 7630 // TODO: set VSCR[SAT] 7631 break; 7632 7633 case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262) 7634 DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7635 putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) ); 7636 // TODO: set VSCR[SAT] 7637 break; 7638 7639 case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263) 7640 DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7641 putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) ); 7642 // TODO: set VSCR[SAT] 7643 break; 7644 7645 case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264) 7646 DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7647 putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) ); 7648 // TODO: set VSCR[SAT] 7649 break; 7650 7651 7652 /* Maximum */ 7653 case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182) 7654 DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7655 putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) ); 7656 break; 7657 7658 case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183) 7659 DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7660 putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) ); 7661 break; 7662 7663 case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184) 7664 DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7665 putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) ); 7666 break; 7667 7668 case 0x102: // vmaxsb (Maximum Signed Byte, AV p179) 7669 DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7670 putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) ); 7671 break; 7672 7673 case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180) 7674 DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7675 putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) ); 7676 break; 7677 7678 case 0x182: // vmaxsw (Maximum Signed Word, AV p181) 7679 DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7680 putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) ); 7681 break; 7682 7683 7684 /* Minimum */ 7685 case 0x202: // vminub (Minimum Unsigned Byte, AV p191) 7686 DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7687 putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) ); 7688 break; 7689 7690 case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192) 7691 DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7692 putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) ); 7693 break; 7694 7695 case 0x282: // vminuw (Minimum Unsigned Word, AV p193) 7696 DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7697 putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) ); 7698 break; 7699 7700 case 0x302: // vminsb (Minimum Signed Byte, AV p188) 7701 DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7702 putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) ); 7703 break; 7704 7705 case 0x342: // vminsh (Minimum Signed Half Word, AV p189) 7706 DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7707 putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) ); 7708 break; 7709 7710 case 0x382: // vminsw (Minimum Signed Word, AV p190) 7711 DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7712 putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) ); 7713 break; 7714 7715 7716 /* Average */ 7717 case 0x402: // vavgub (Average Unsigned Byte, AV p152) 7718 DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7719 putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) ); 7720 break; 7721 7722 case 0x442: // vavguh (Average Unsigned Half Word, AV p153) 7723 DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7724 putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) ); 7725 break; 7726 7727 case 0x482: // vavguw (Average Unsigned Word, AV p154) 7728 DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7729 putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) ); 7730 break; 7731 7732 case 0x502: // vavgsb (Average Signed Byte, AV p149) 7733 DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7734 putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) ); 7735 break; 7736 7737 case 0x542: // vavgsh (Average Signed Half Word, AV p150) 7738 DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7739 putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) ); 7740 break; 7741 7742 case 0x582: // vavgsw (Average Signed Word, AV p151) 7743 DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7744 putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) ); 7745 break; 7746 7747 7748 /* Multiply */ 7749 case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213) 7750 DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7751 putVReg( vD_addr, 7752 binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB))); 7753 break; 7754 7755 case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214) 7756 DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7757 putVReg( vD_addr, 7758 binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB))); 7759 break; 7760 7761 case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211) 7762 DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7763 putVReg( vD_addr, 7764 binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB))); 7765 break; 7766 7767 case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212) 7768 DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7769 putVReg( vD_addr, 7770 binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB))); 7771 break; 7772 7773 case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209) 7774 DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7775 putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 7776 break; 7777 7778 case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210) 7779 DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7780 putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 7781 break; 7782 7783 case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207) 7784 DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7785 putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) )); 7786 break; 7787 7788 case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208) 7789 DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7790 putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 7791 break; 7792 7793 7794 /* Sum Across Partial */ 7795 case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275) 7796 IRTemp aEE, aEO, aOE, aOO; 7797 aEE = aEO = aOE = aOO = IRTemp_INVALID; 7798 DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7799 7800 /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */ 7801 expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 7802 expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 7803 expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 7804 7805 /* break V128 to 4xI32's, zero-extending to I64's */ 7806 breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 7807 breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 7808 breakV128to4x64U( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 7809 breakV128to4x64U( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 7810 breakV128to4x64U( mkexpr(vB), &b3, &b2, &b1, &b0 ); 7811 7812 /* add lanes */ 7813 assign( z3, binop(Iop_Add64, mkexpr(b3), 7814 binop(Iop_Add64, 7815 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 7816 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 7817 assign( z2, binop(Iop_Add64, mkexpr(b2), 7818 binop(Iop_Add64, 7819 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 7820 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 7821 assign( z1, binop(Iop_Add64, mkexpr(b1), 7822 binop(Iop_Add64, 7823 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 7824 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 7825 assign( z0, binop(Iop_Add64, mkexpr(b0), 7826 binop(Iop_Add64, 7827 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 7828 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 7829 7830 /* saturate-narrow to 32bit, and combine to V128 */ 7831 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 7832 mkexpr(z1), mkexpr(z0)) ); 7833 break; 7834 } 7835 case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273) 7836 IRTemp aEE, aEO, aOE, aOO; 7837 aEE = aEO = aOE = aOO = IRTemp_INVALID; 7838 DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7839 7840 /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */ 7841 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 7842 expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 7843 expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 7844 7845 /* break V128 to 4xI32's, sign-extending to I64's */ 7846 breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 7847 breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 7848 breakV128to4x64S( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 7849 breakV128to4x64S( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 7850 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 7851 7852 /* add lanes */ 7853 assign( z3, binop(Iop_Add64, mkexpr(b3), 7854 binop(Iop_Add64, 7855 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 7856 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 7857 assign( z2, binop(Iop_Add64, mkexpr(b2), 7858 binop(Iop_Add64, 7859 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 7860 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 7861 assign( z1, binop(Iop_Add64, mkexpr(b1), 7862 binop(Iop_Add64, 7863 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 7864 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 7865 assign( z0, binop(Iop_Add64, mkexpr(b0), 7866 binop(Iop_Add64, 7867 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 7868 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 7869 7870 /* saturate-narrow to 32bit, and combine to V128 */ 7871 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 7872 mkexpr(z1), mkexpr(z0)) ); 7873 break; 7874 } 7875 case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274) 7876 DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7877 7878 /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */ 7879 expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...) 7880 7881 /* break V128 to 4xI32's, sign-extending to I64's */ 7882 breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 ); 7883 breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 ); 7884 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 7885 7886 /* add lanes */ 7887 assign( z3, binop(Iop_Add64, mkexpr(b3), 7888 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)))); 7889 assign( z2, binop(Iop_Add64, mkexpr(b2), 7890 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))); 7891 assign( z1, binop(Iop_Add64, mkexpr(b1), 7892 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)))); 7893 assign( z0, binop(Iop_Add64, mkexpr(b0), 7894 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))); 7895 7896 /* saturate-narrow to 32bit, and combine to V128 */ 7897 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 7898 mkexpr(z1), mkexpr(z0)) ); 7899 break; 7900 } 7901 case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272) 7902 DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7903 7904 /* break V128 to 4xI32's, sign-extending to I64's */ 7905 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 7906 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 7907 7908 /* add lanes */ 7909 assign( z2, binop(Iop_Add64, mkexpr(b2), 7910 binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) ); 7911 assign( z0, binop(Iop_Add64, mkexpr(b0), 7912 binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) ); 7913 7914 /* saturate-narrow to 32bit, and combine to V128 */ 7915 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2), 7916 mkU64(0), mkexpr(z0)) ); 7917 break; 7918 } 7919 case 0x788: { // vsumsws (Sum SW Saturate, AV p271) 7920 DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7921 7922 /* break V128 to 4xI32's, sign-extending to I64's */ 7923 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 7924 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 7925 7926 /* add lanes */ 7927 assign( z0, binop(Iop_Add64, mkexpr(b0), 7928 binop(Iop_Add64, 7929 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 7930 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 7931 7932 /* saturate-narrow to 32bit, and combine to V128 */ 7933 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0), 7934 mkU64(0), mkexpr(z0)) ); 7935 break; 7936 } 7937 default: 7938 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2); 7939 return False; 7940 } 7941 return True; 7942 } 7943 7944 /* 7945 AltiVec Logic Instructions 7946 */ 7947 static Bool dis_av_logic ( UInt theInstr ) 7948 { 7949 /* VX-Form */ 7950 UChar opc1 = ifieldOPC(theInstr); 7951 UChar vD_addr = ifieldRegDS(theInstr); 7952 UChar vA_addr = ifieldRegA(theInstr); 7953 UChar vB_addr = ifieldRegB(theInstr); 7954 UInt opc2 = IFIELD( theInstr, 0, 11 ); 7955 7956 IRTemp vA = newTemp(Ity_V128); 7957 IRTemp vB = newTemp(Ity_V128); 7958 assign( vA, getVReg(vA_addr)); 7959 assign( vB, getVReg(vB_addr)); 7960 7961 if (opc1 != 0x4) { 7962 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n"); 7963 return False; 7964 } 7965 7966 switch (opc2) { 7967 case 0x404: // vand (And, AV p147) 7968 DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7969 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) ); 7970 break; 7971 7972 case 0x444: // vandc (And, AV p148) 7973 DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7974 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), 7975 unop(Iop_NotV128, mkexpr(vB))) ); 7976 break; 7977 7978 case 0x484: // vor (Or, AV p217) 7979 DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7980 putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) ); 7981 break; 7982 7983 case 0x4C4: // vxor (Xor, AV p282) 7984 DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7985 putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) ); 7986 break; 7987 7988 case 0x504: // vnor (Nor, AV p216) 7989 DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 7990 putVReg( vD_addr, 7991 unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) ); 7992 break; 7993 7994 default: 7995 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2); 7996 return False; 7997 } 7998 return True; 7999 } 8000 8001 /* 8002 AltiVec Compare Instructions 8003 */ 8004 static Bool dis_av_cmp ( UInt theInstr ) 8005 { 8006 /* VXR-Form */ 8007 UChar opc1 = ifieldOPC(theInstr); 8008 UChar vD_addr = ifieldRegDS(theInstr); 8009 UChar vA_addr = ifieldRegA(theInstr); 8010 UChar vB_addr = ifieldRegB(theInstr); 8011 UChar flag_rC = ifieldBIT10(theInstr); 8012 UInt opc2 = IFIELD( theInstr, 0, 10 ); 8013 8014 IRTemp vA = newTemp(Ity_V128); 8015 IRTemp vB = newTemp(Ity_V128); 8016 IRTemp vD = newTemp(Ity_V128); 8017 assign( vA, getVReg(vA_addr)); 8018 assign( vB, getVReg(vB_addr)); 8019 8020 if (opc1 != 0x4) { 8021 vex_printf("dis_av_cmp(ppc)(instr)\n"); 8022 return False; 8023 } 8024 8025 switch (opc2) { 8026 case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160) 8027 DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 8028 vD_addr, vA_addr, vB_addr); 8029 assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) ); 8030 break; 8031 8032 case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161) 8033 DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 8034 vD_addr, vA_addr, vB_addr); 8035 assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) ); 8036 break; 8037 8038 case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162) 8039 DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 8040 vD_addr, vA_addr, vB_addr); 8041 assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) ); 8042 break; 8043 8044 case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168) 8045 DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 8046 vD_addr, vA_addr, vB_addr); 8047 assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) ); 8048 break; 8049 8050 case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169) 8051 DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 8052 vD_addr, vA_addr, vB_addr); 8053 assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) ); 8054 break; 8055 8056 case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170) 8057 DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 8058 vD_addr, vA_addr, vB_addr); 8059 assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) ); 8060 break; 8061 8062 case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165) 8063 DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 8064 vD_addr, vA_addr, vB_addr); 8065 assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) ); 8066 break; 8067 8068 case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166) 8069 DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 8070 vD_addr, vA_addr, vB_addr); 8071 assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) ); 8072 break; 8073 8074 case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167) 8075 DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 8076 vD_addr, vA_addr, vB_addr); 8077 assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) ); 8078 break; 8079 8080 default: 8081 vex_printf("dis_av_cmp(ppc)(opc2)\n"); 8082 return False; 8083 } 8084 8085 putVReg( vD_addr, mkexpr(vD) ); 8086 8087 if (flag_rC) { 8088 set_AV_CR6( mkexpr(vD), True ); 8089 } 8090 return True; 8091 } 8092 8093 /* 8094 AltiVec Multiply-Sum Instructions 8095 */ 8096 static Bool dis_av_multarith ( UInt theInstr ) 8097 { 8098 /* VA-Form */ 8099 UChar opc1 = ifieldOPC(theInstr); 8100 UChar vD_addr = ifieldRegDS(theInstr); 8101 UChar vA_addr = ifieldRegA(theInstr); 8102 UChar vB_addr = ifieldRegB(theInstr); 8103 UChar vC_addr = ifieldRegC(theInstr); 8104 UChar opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 8105 8106 IRTemp vA = newTemp(Ity_V128); 8107 IRTemp vB = newTemp(Ity_V128); 8108 IRTemp vC = newTemp(Ity_V128); 8109 IRTemp zeros = newTemp(Ity_V128); 8110 IRTemp aLo = newTemp(Ity_V128); 8111 IRTemp bLo = newTemp(Ity_V128); 8112 IRTemp cLo = newTemp(Ity_V128); 8113 IRTemp zLo = newTemp(Ity_V128); 8114 IRTemp aHi = newTemp(Ity_V128); 8115 IRTemp bHi = newTemp(Ity_V128); 8116 IRTemp cHi = newTemp(Ity_V128); 8117 IRTemp zHi = newTemp(Ity_V128); 8118 IRTemp abEvn = newTemp(Ity_V128); 8119 IRTemp abOdd = newTemp(Ity_V128); 8120 IRTemp z3 = newTemp(Ity_I64); 8121 IRTemp z2 = newTemp(Ity_I64); 8122 IRTemp z1 = newTemp(Ity_I64); 8123 IRTemp z0 = newTemp(Ity_I64); 8124 IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0; 8125 IRTemp c3, c2, c1, c0; 8126 8127 ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID; 8128 c3 = c2 = c1 = c0 = IRTemp_INVALID; 8129 8130 assign( vA, getVReg(vA_addr)); 8131 assign( vB, getVReg(vB_addr)); 8132 assign( vC, getVReg(vC_addr)); 8133 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 8134 8135 if (opc1 != 0x4) { 8136 vex_printf("dis_av_multarith(ppc)(instr)\n"); 8137 return False; 8138 } 8139 8140 switch (opc2) { 8141 /* Multiply-Add */ 8142 case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185) 8143 IRTemp cSigns = newTemp(Ity_V128); 8144 DIP("vmhaddshs v%d,v%d,v%d,v%d\n", 8145 vD_addr, vA_addr, vB_addr, vC_addr); 8146 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC))); 8147 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 8148 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 8149 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 8150 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 8151 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 8152 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 8153 8154 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 8155 binop(Iop_SarN32x4, 8156 binop(Iop_MullEven16Sx8, 8157 mkexpr(aLo), mkexpr(bLo)), 8158 mkU8(15))) ); 8159 8160 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 8161 binop(Iop_SarN32x4, 8162 binop(Iop_MullEven16Sx8, 8163 mkexpr(aHi), mkexpr(bHi)), 8164 mkU8(15))) ); 8165 8166 putVReg( vD_addr, 8167 binop(Iop_QNarrow32Sx4, mkexpr(zHi), mkexpr(zLo)) ); 8168 break; 8169 } 8170 case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186) 8171 IRTemp zKonst = newTemp(Ity_V128); 8172 IRTemp cSigns = newTemp(Ity_V128); 8173 DIP("vmhraddshs v%d,v%d,v%d,v%d\n", 8174 vD_addr, vA_addr, vB_addr, vC_addr); 8175 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) ); 8176 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 8177 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 8178 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 8179 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 8180 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 8181 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 8182 8183 /* shifting our const avoids store/load version of Dup */ 8184 assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)), 8185 mkU8(14)) ); 8186 8187 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 8188 binop(Iop_SarN32x4, 8189 binop(Iop_Add32x4, mkexpr(zKonst), 8190 binop(Iop_MullEven16Sx8, 8191 mkexpr(aLo), mkexpr(bLo))), 8192 mkU8(15))) ); 8193 8194 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 8195 binop(Iop_SarN32x4, 8196 binop(Iop_Add32x4, mkexpr(zKonst), 8197 binop(Iop_MullEven16Sx8, 8198 mkexpr(aHi), mkexpr(bHi))), 8199 mkU8(15))) ); 8200 8201 putVReg( vD_addr, binop(Iop_QNarrow32Sx4, mkexpr(zHi), mkexpr(zLo)) ); 8202 break; 8203 } 8204 case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194) 8205 DIP("vmladduhm v%d,v%d,v%d,v%d\n", 8206 vD_addr, vA_addr, vB_addr, vC_addr); 8207 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 8208 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 8209 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC))); 8210 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 8211 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 8212 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC))); 8213 assign(zLo, binop(Iop_Add32x4, 8214 binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)), 8215 mkexpr(cLo)) ); 8216 assign(zHi, binop(Iop_Add32x4, 8217 binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)), 8218 mkexpr(cHi))); 8219 putVReg(vD_addr, binop(Iop_Narrow32x4, mkexpr(zHi), mkexpr(zLo))); 8220 break; 8221 } 8222 8223 8224 /* Multiply-Sum */ 8225 case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204) 8226 IRTemp abEE, abEO, abOE, abOO; 8227 abEE = abEO = abOE = abOO = IRTemp_INVALID; 8228 DIP("vmsumubm v%d,v%d,v%d,v%d\n", 8229 vD_addr, vA_addr, vB_addr, vC_addr); 8230 8231 /* multiply vA,vB (unsigned, widening) */ 8232 assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 8233 assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) ); 8234 8235 /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */ 8236 expand16Ux8( mkexpr(abEvn), &abEE, &abEO ); 8237 expand16Ux8( mkexpr(abOdd), &abOE, &abOO ); 8238 8239 putVReg( vD_addr, 8240 binop(Iop_Add32x4, mkexpr(vC), 8241 binop(Iop_Add32x4, 8242 binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)), 8243 binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) ); 8244 break; 8245 } 8246 case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201) 8247 IRTemp aEvn, aOdd, bEvn, bOdd; 8248 IRTemp abEE = newTemp(Ity_V128); 8249 IRTemp abEO = newTemp(Ity_V128); 8250 IRTemp abOE = newTemp(Ity_V128); 8251 IRTemp abOO = newTemp(Ity_V128); 8252 aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID; 8253 DIP("vmsummbm v%d,v%d,v%d,v%d\n", 8254 vD_addr, vA_addr, vB_addr, vC_addr); 8255 8256 /* sign-extend vA, zero-extend vB, for mixed-sign multiply 8257 (separating out adjacent lanes to different vectors) */ 8258 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); 8259 expand8Ux16( mkexpr(vB), &bEvn, &bOdd ); 8260 8261 /* multiply vA, vB, again separating adjacent lanes */ 8262 assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) )); 8263 assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) ); 8264 assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) )); 8265 assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) ); 8266 8267 /* add results together, + vC */ 8268 putVReg( vD_addr, 8269 binop(Iop_QAdd32Sx4, mkexpr(vC), 8270 binop(Iop_QAdd32Sx4, 8271 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)), 8272 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) ); 8273 break; 8274 } 8275 case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205) 8276 DIP("vmsumuhm v%d,v%d,v%d,v%d\n", 8277 vD_addr, vA_addr, vB_addr, vC_addr); 8278 assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 8279 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 8280 putVReg( vD_addr, 8281 binop(Iop_Add32x4, mkexpr(vC), 8282 binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) ); 8283 break; 8284 } 8285 case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206) 8286 DIP("vmsumuhs v%d,v%d,v%d,v%d\n", 8287 vD_addr, vA_addr, vB_addr, vC_addr); 8288 /* widening multiply, separating lanes */ 8289 assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) )); 8290 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 8291 8292 /* break V128 to 4xI32's, zero-extending to I64's */ 8293 breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 8294 breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 8295 breakV128to4x64U( mkexpr(vC), &c3, &c2, &c1, &c0 ); 8296 8297 /* add lanes */ 8298 assign( z3, binop(Iop_Add64, mkexpr(c3), 8299 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 8300 assign( z2, binop(Iop_Add64, mkexpr(c2), 8301 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 8302 assign( z1, binop(Iop_Add64, mkexpr(c1), 8303 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 8304 assign( z0, binop(Iop_Add64, mkexpr(c0), 8305 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 8306 8307 /* saturate-narrow to 32bit, and combine to V128 */ 8308 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 8309 mkexpr(z1), mkexpr(z0)) ); 8310 8311 break; 8312 } 8313 case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202) 8314 DIP("vmsumshm v%d,v%d,v%d,v%d\n", 8315 vD_addr, vA_addr, vB_addr, vC_addr); 8316 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 8317 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 8318 putVReg( vD_addr, 8319 binop(Iop_Add32x4, mkexpr(vC), 8320 binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) ); 8321 break; 8322 } 8323 case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203) 8324 DIP("vmsumshs v%d,v%d,v%d,v%d\n", 8325 vD_addr, vA_addr, vB_addr, vC_addr); 8326 /* widening multiply, separating lanes */ 8327 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 8328 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 8329 8330 /* break V128 to 4xI32's, sign-extending to I64's */ 8331 breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 8332 breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 8333 breakV128to4x64S( mkexpr(vC), &c3, &c2, &c1, &c0 ); 8334 8335 /* add lanes */ 8336 assign( z3, binop(Iop_Add64, mkexpr(c3), 8337 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 8338 assign( z2, binop(Iop_Add64, mkexpr(c2), 8339 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 8340 assign( z1, binop(Iop_Add64, mkexpr(c1), 8341 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 8342 assign( z0, binop(Iop_Add64, mkexpr(c0), 8343 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 8344 8345 /* saturate-narrow to 32bit, and combine to V128 */ 8346 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 8347 mkexpr(z1), mkexpr(z0)) ); 8348 break; 8349 } 8350 default: 8351 vex_printf("dis_av_multarith(ppc)(opc2)\n"); 8352 return False; 8353 } 8354 return True; 8355 } 8356 8357 /* 8358 AltiVec Shift/Rotate Instructions 8359 */ 8360 static Bool dis_av_shift ( UInt theInstr ) 8361 { 8362 /* VX-Form */ 8363 UChar opc1 = ifieldOPC(theInstr); 8364 UChar vD_addr = ifieldRegDS(theInstr); 8365 UChar vA_addr = ifieldRegA(theInstr); 8366 UChar vB_addr = ifieldRegB(theInstr); 8367 UInt opc2 = IFIELD( theInstr, 0, 11 ); 8368 8369 IRTemp vA = newTemp(Ity_V128); 8370 IRTemp vB = newTemp(Ity_V128); 8371 assign( vA, getVReg(vA_addr)); 8372 assign( vB, getVReg(vB_addr)); 8373 8374 if (opc1 != 0x4){ 8375 vex_printf("dis_av_shift(ppc)(instr)\n"); 8376 return False; 8377 } 8378 8379 switch (opc2) { 8380 /* Rotate */ 8381 case 0x004: // vrlb (Rotate Left Integer B, AV p234) 8382 DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8383 putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) ); 8384 break; 8385 8386 case 0x044: // vrlh (Rotate Left Integer HW, AV p235) 8387 DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8388 putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) ); 8389 break; 8390 8391 case 0x084: // vrlw (Rotate Left Integer W, AV p236) 8392 DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8393 putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) ); 8394 break; 8395 8396 8397 /* Shift Left */ 8398 case 0x104: // vslb (Shift Left Integer B, AV p240) 8399 DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8400 putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) ); 8401 break; 8402 8403 case 0x144: // vslh (Shift Left Integer HW, AV p242) 8404 DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8405 putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) ); 8406 break; 8407 8408 case 0x184: // vslw (Shift Left Integer W, AV p244) 8409 DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8410 putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) ); 8411 break; 8412 8413 case 0x1C4: { // vsl (Shift Left, AV p239) 8414 IRTemp sh = newTemp(Ity_I8); 8415 DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8416 assign( sh, binop(Iop_And8, mkU8(0x7), 8417 unop(Iop_32to8, 8418 unop(Iop_V128to32, mkexpr(vB)))) ); 8419 putVReg( vD_addr, 8420 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 8421 break; 8422 } 8423 case 0x40C: { // vslo (Shift Left by Octet, AV p243) 8424 IRTemp sh = newTemp(Ity_I8); 8425 DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8426 assign( sh, binop(Iop_And8, mkU8(0x78), 8427 unop(Iop_32to8, 8428 unop(Iop_V128to32, mkexpr(vB)))) ); 8429 putVReg( vD_addr, 8430 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 8431 break; 8432 } 8433 8434 8435 /* Shift Right */ 8436 case 0x204: // vsrb (Shift Right B, AV p256) 8437 DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8438 putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) ); 8439 break; 8440 8441 case 0x244: // vsrh (Shift Right HW, AV p257) 8442 DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8443 putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) ); 8444 break; 8445 8446 case 0x284: // vsrw (Shift Right W, AV p259) 8447 DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8448 putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) ); 8449 break; 8450 8451 case 0x2C4: { // vsr (Shift Right, AV p251) 8452 IRTemp sh = newTemp(Ity_I8); 8453 DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8454 assign( sh, binop(Iop_And8, mkU8(0x7), 8455 unop(Iop_32to8, 8456 unop(Iop_V128to32, mkexpr(vB)))) ); 8457 putVReg( vD_addr, 8458 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 8459 break; 8460 } 8461 case 0x304: // vsrab (Shift Right Alg B, AV p253) 8462 DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8463 putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) ); 8464 break; 8465 8466 case 0x344: // vsrah (Shift Right Alg HW, AV p254) 8467 DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8468 putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) ); 8469 break; 8470 8471 case 0x384: // vsraw (Shift Right Alg W, AV p255) 8472 DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8473 putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) ); 8474 break; 8475 8476 case 0x44C: { // vsro (Shift Right by Octet, AV p258) 8477 IRTemp sh = newTemp(Ity_I8); 8478 DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8479 assign( sh, binop(Iop_And8, mkU8(0x78), 8480 unop(Iop_32to8, 8481 unop(Iop_V128to32, mkexpr(vB)))) ); 8482 putVReg( vD_addr, 8483 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 8484 break; 8485 } 8486 8487 default: 8488 vex_printf("dis_av_shift(ppc)(opc2)\n"); 8489 return False; 8490 } 8491 return True; 8492 } 8493 8494 /* 8495 AltiVec Permute Instructions 8496 */ 8497 static Bool dis_av_permute ( UInt theInstr ) 8498 { 8499 /* VA-Form, VX-Form */ 8500 UChar opc1 = ifieldOPC(theInstr); 8501 UChar vD_addr = ifieldRegDS(theInstr); 8502 UChar vA_addr = ifieldRegA(theInstr); 8503 UChar UIMM_5 = vA_addr; 8504 UChar vB_addr = ifieldRegB(theInstr); 8505 UChar vC_addr = ifieldRegC(theInstr); 8506 UChar b10 = ifieldBIT10(theInstr); 8507 UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) ); 8508 UInt opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 8509 8510 UChar SIMM_8 = extend_s_5to8(UIMM_5); 8511 8512 IRTemp vA = newTemp(Ity_V128); 8513 IRTemp vB = newTemp(Ity_V128); 8514 IRTemp vC = newTemp(Ity_V128); 8515 assign( vA, getVReg(vA_addr)); 8516 assign( vB, getVReg(vB_addr)); 8517 assign( vC, getVReg(vC_addr)); 8518 8519 if (opc1 != 0x4) { 8520 vex_printf("dis_av_permute(ppc)(instr)\n"); 8521 return False; 8522 } 8523 8524 switch (opc2) { 8525 case 0x2A: // vsel (Conditional Select, AV p238) 8526 DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr); 8527 /* vD = (vA & ~vC) | (vB & vC) */ 8528 putVReg( vD_addr, binop(Iop_OrV128, 8529 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 8530 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 8531 return True; 8532 8533 case 0x2B: { // vperm (Permute, AV p218) 8534 /* limited to two args for IR, so have to play games... */ 8535 IRTemp a_perm = newTemp(Ity_V128); 8536 IRTemp b_perm = newTemp(Ity_V128); 8537 IRTemp mask = newTemp(Ity_V128); 8538 IRTemp vC_andF = newTemp(Ity_V128); 8539 DIP("vperm v%d,v%d,v%d,v%d\n", 8540 vD_addr, vA_addr, vB_addr, vC_addr); 8541 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what 8542 IR specifies, and also to hide irrelevant bits from 8543 memcheck */ 8544 assign( vC_andF, 8545 binop(Iop_AndV128, mkexpr(vC), 8546 unop(Iop_Dup8x16, mkU8(0xF))) ); 8547 assign( a_perm, 8548 binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) ); 8549 assign( b_perm, 8550 binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) ); 8551 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0 8552 assign( mask, binop(Iop_SarN8x16, 8553 binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)), 8554 mkU8(7)) ); 8555 // dst = (a & ~mask) | (b & mask) 8556 putVReg( vD_addr, binop(Iop_OrV128, 8557 binop(Iop_AndV128, mkexpr(a_perm), 8558 unop(Iop_NotV128, mkexpr(mask))), 8559 binop(Iop_AndV128, mkexpr(b_perm), 8560 mkexpr(mask))) ); 8561 return True; 8562 } 8563 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241) 8564 if (b10 != 0) { 8565 vex_printf("dis_av_permute(ppc)(vsldoi)\n"); 8566 return False; 8567 } 8568 DIP("vsldoi v%d,v%d,v%d,%d\n", 8569 vD_addr, vA_addr, vB_addr, SHB_uimm4); 8570 if (SHB_uimm4 == 0) 8571 putVReg( vD_addr, mkexpr(vA) ); 8572 else 8573 putVReg( vD_addr, 8574 binop(Iop_OrV128, 8575 binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)), 8576 binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) ); 8577 return True; 8578 8579 default: 8580 break; // Fall through... 8581 } 8582 8583 opc2 = IFIELD( theInstr, 0, 11 ); 8584 switch (opc2) { 8585 8586 /* Merge */ 8587 case 0x00C: // vmrghb (Merge High B, AV p195) 8588 DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8589 putVReg( vD_addr, 8590 binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) ); 8591 break; 8592 8593 case 0x04C: // vmrghh (Merge High HW, AV p196) 8594 DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8595 putVReg( vD_addr, 8596 binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) ); 8597 break; 8598 8599 case 0x08C: // vmrghw (Merge High W, AV p197) 8600 DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8601 putVReg( vD_addr, 8602 binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) ); 8603 break; 8604 8605 case 0x10C: // vmrglb (Merge Low B, AV p198) 8606 DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8607 putVReg( vD_addr, 8608 binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) ); 8609 break; 8610 8611 case 0x14C: // vmrglh (Merge Low HW, AV p199) 8612 DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8613 putVReg( vD_addr, 8614 binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) ); 8615 break; 8616 8617 case 0x18C: // vmrglw (Merge Low W, AV p200) 8618 DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8619 putVReg( vD_addr, 8620 binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) ); 8621 break; 8622 8623 8624 /* Splat */ 8625 case 0x20C: { // vspltb (Splat Byte, AV p245) 8626 /* vD = Dup8x16( vB[UIMM_5] ) */ 8627 UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8; 8628 DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 8629 putVReg( vD_addr, unop(Iop_Dup8x16, 8630 unop(Iop_32to8, unop(Iop_V128to32, 8631 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 8632 break; 8633 } 8634 case 0x24C: { // vsplth (Splat Half Word, AV p246) 8635 UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16; 8636 DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 8637 putVReg( vD_addr, unop(Iop_Dup16x8, 8638 unop(Iop_32to16, unop(Iop_V128to32, 8639 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 8640 break; 8641 } 8642 case 0x28C: { // vspltw (Splat Word, AV p250) 8643 /* vD = Dup32x4( vB[UIMM_5] ) */ 8644 UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32; 8645 DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 8646 putVReg( vD_addr, unop(Iop_Dup32x4, 8647 unop(Iop_V128to32, 8648 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) ); 8649 break; 8650 } 8651 case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247) 8652 DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8); 8653 putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) ); 8654 break; 8655 8656 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248) 8657 DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8); 8658 putVReg( vD_addr, 8659 unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) ); 8660 break; 8661 8662 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249) 8663 DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8); 8664 putVReg( vD_addr, 8665 unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) ); 8666 break; 8667 8668 default: 8669 vex_printf("dis_av_permute(ppc)(opc2)\n"); 8670 return False; 8671 } 8672 return True; 8673 } 8674 8675 /* 8676 AltiVec Pack/Unpack Instructions 8677 */ 8678 static Bool dis_av_pack ( UInt theInstr ) 8679 { 8680 /* VX-Form */ 8681 UChar opc1 = ifieldOPC(theInstr); 8682 UChar vD_addr = ifieldRegDS(theInstr); 8683 UChar vA_addr = ifieldRegA(theInstr); 8684 UChar vB_addr = ifieldRegB(theInstr); 8685 UInt opc2 = IFIELD( theInstr, 0, 11 ); 8686 8687 IRTemp signs = IRTemp_INVALID; 8688 IRTemp zeros = IRTemp_INVALID; 8689 IRTemp vA = newTemp(Ity_V128); 8690 IRTemp vB = newTemp(Ity_V128); 8691 assign( vA, getVReg(vA_addr)); 8692 assign( vB, getVReg(vB_addr)); 8693 8694 if (opc1 != 0x4) { 8695 vex_printf("dis_av_pack(ppc)(instr)\n"); 8696 return False; 8697 } 8698 8699 switch (opc2) { 8700 /* Packing */ 8701 case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224) 8702 DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8703 putVReg( vD_addr, binop(Iop_Narrow16x8, mkexpr(vA), mkexpr(vB)) ); 8704 return True; 8705 8706 case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226) 8707 DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8708 putVReg( vD_addr, binop(Iop_Narrow32x4, mkexpr(vA), mkexpr(vB)) ); 8709 return True; 8710 8711 case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225) 8712 DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8713 putVReg( vD_addr, 8714 binop(Iop_QNarrow16Ux8, mkexpr(vA), mkexpr(vB)) ); 8715 // TODO: set VSCR[SAT] 8716 return True; 8717 8718 case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227) 8719 DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8720 putVReg( vD_addr, 8721 binop(Iop_QNarrow32Ux4, mkexpr(vA), mkexpr(vB)) ); 8722 // TODO: set VSCR[SAT] 8723 return True; 8724 8725 case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221) 8726 // This insn does a signed->unsigned saturating conversion. 8727 // Conversion done here, then uses unsigned->unsigned vpk insn: 8728 // => UnsignedSaturatingNarrow( x & ~ (x >>s 15) ) 8729 IRTemp vA_tmp = newTemp(Ity_V128); 8730 IRTemp vB_tmp = newTemp(Ity_V128); 8731 DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8732 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 8733 unop(Iop_NotV128, 8734 binop(Iop_SarN16x8, 8735 mkexpr(vA), mkU8(15)))) ); 8736 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 8737 unop(Iop_NotV128, 8738 binop(Iop_SarN16x8, 8739 mkexpr(vB), mkU8(15)))) ); 8740 putVReg( vD_addr, binop(Iop_QNarrow16Ux8, 8741 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 8742 // TODO: set VSCR[SAT] 8743 return True; 8744 } 8745 case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223) 8746 // This insn does a signed->unsigned saturating conversion. 8747 // Conversion done here, then uses unsigned->unsigned vpk insn: 8748 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) ) 8749 IRTemp vA_tmp = newTemp(Ity_V128); 8750 IRTemp vB_tmp = newTemp(Ity_V128); 8751 DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8752 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 8753 unop(Iop_NotV128, 8754 binop(Iop_SarN32x4, 8755 mkexpr(vA), mkU8(31)))) ); 8756 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 8757 unop(Iop_NotV128, 8758 binop(Iop_SarN32x4, 8759 mkexpr(vB), mkU8(31)))) ); 8760 putVReg( vD_addr, binop(Iop_QNarrow32Ux4, 8761 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 8762 // TODO: set VSCR[SAT] 8763 return True; 8764 } 8765 case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220) 8766 DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8767 putVReg( vD_addr, 8768 binop(Iop_QNarrow16Sx8, mkexpr(vA), mkexpr(vB)) ); 8769 // TODO: set VSCR[SAT] 8770 return True; 8771 8772 case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222) 8773 DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8774 putVReg( vD_addr, 8775 binop(Iop_QNarrow32Sx4, mkexpr(vA), mkexpr(vB)) ); 8776 // TODO: set VSCR[SAT] 8777 return True; 8778 8779 case 0x30E: { // vpkpx (Pack Pixel, AV p219) 8780 /* CAB: Worth a new primop? */ 8781 /* Using shifts to compact pixel elements, then packing them */ 8782 IRTemp a1 = newTemp(Ity_V128); 8783 IRTemp a2 = newTemp(Ity_V128); 8784 IRTemp a3 = newTemp(Ity_V128); 8785 IRTemp a_tmp = newTemp(Ity_V128); 8786 IRTemp b1 = newTemp(Ity_V128); 8787 IRTemp b2 = newTemp(Ity_V128); 8788 IRTemp b3 = newTemp(Ity_V128); 8789 IRTemp b_tmp = newTemp(Ity_V128); 8790 DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8791 assign( a1, binop(Iop_ShlN16x8, 8792 binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)), 8793 mkU8(10)) ); 8794 assign( a2, binop(Iop_ShlN16x8, 8795 binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)), 8796 mkU8(5)) ); 8797 assign( a3, binop(Iop_ShrN16x8, 8798 binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)), 8799 mkU8(11)) ); 8800 assign( a_tmp, binop(Iop_OrV128, mkexpr(a1), 8801 binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) ); 8802 8803 assign( b1, binop(Iop_ShlN16x8, 8804 binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)), 8805 mkU8(10)) ); 8806 assign( b2, binop(Iop_ShlN16x8, 8807 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)), 8808 mkU8(5)) ); 8809 assign( b3, binop(Iop_ShrN16x8, 8810 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)), 8811 mkU8(11)) ); 8812 assign( b_tmp, binop(Iop_OrV128, mkexpr(b1), 8813 binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) ); 8814 8815 putVReg( vD_addr, binop(Iop_Narrow32x4, 8816 mkexpr(a_tmp), mkexpr(b_tmp)) ); 8817 return True; 8818 } 8819 8820 default: 8821 break; // Fall through... 8822 } 8823 8824 8825 if (vA_addr != 0) { 8826 vex_printf("dis_av_pack(ppc)(vA_addr)\n"); 8827 return False; 8828 } 8829 8830 signs = newTemp(Ity_V128); 8831 zeros = newTemp(Ity_V128); 8832 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 8833 8834 switch (opc2) { 8835 /* Unpacking */ 8836 case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277) 8837 DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr); 8838 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 8839 putVReg( vD_addr, 8840 binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) ); 8841 break; 8842 } 8843 case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278) 8844 DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr); 8845 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 8846 putVReg( vD_addr, 8847 binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) ); 8848 break; 8849 } 8850 case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280) 8851 DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr); 8852 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 8853 putVReg( vD_addr, 8854 binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) ); 8855 break; 8856 } 8857 case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281) 8858 DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr); 8859 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 8860 putVReg( vD_addr, 8861 binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) ); 8862 break; 8863 } 8864 case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276) 8865 /* CAB: Worth a new primop? */ 8866 /* Using shifts to isolate pixel elements, then expanding them */ 8867 IRTemp z0 = newTemp(Ity_V128); 8868 IRTemp z1 = newTemp(Ity_V128); 8869 IRTemp z01 = newTemp(Ity_V128); 8870 IRTemp z2 = newTemp(Ity_V128); 8871 IRTemp z3 = newTemp(Ity_V128); 8872 IRTemp z23 = newTemp(Ity_V128); 8873 DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr); 8874 assign( z0, binop(Iop_ShlN16x8, 8875 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 8876 mkU8(8)) ); 8877 assign( z1, binop(Iop_ShrN16x8, 8878 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 8879 mkU8(11)) ); 8880 assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 8881 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 8882 assign( z2, binop(Iop_ShrN16x8, 8883 binop(Iop_ShlN16x8, 8884 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 8885 mkU8(11)), 8886 mkU8(3)) ); 8887 assign( z3, binop(Iop_ShrN16x8, 8888 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 8889 mkU8(11)) ); 8890 assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 8891 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 8892 putVReg( vD_addr, 8893 binop(Iop_OrV128, 8894 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 8895 mkexpr(z23)) ); 8896 break; 8897 } 8898 case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279) 8899 /* identical to vupkhpx, except interleaving LO */ 8900 IRTemp z0 = newTemp(Ity_V128); 8901 IRTemp z1 = newTemp(Ity_V128); 8902 IRTemp z01 = newTemp(Ity_V128); 8903 IRTemp z2 = newTemp(Ity_V128); 8904 IRTemp z3 = newTemp(Ity_V128); 8905 IRTemp z23 = newTemp(Ity_V128); 8906 DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr); 8907 assign( z0, binop(Iop_ShlN16x8, 8908 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 8909 mkU8(8)) ); 8910 assign( z1, binop(Iop_ShrN16x8, 8911 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 8912 mkU8(11)) ); 8913 assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 8914 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 8915 assign( z2, binop(Iop_ShrN16x8, 8916 binop(Iop_ShlN16x8, 8917 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 8918 mkU8(11)), 8919 mkU8(3)) ); 8920 assign( z3, binop(Iop_ShrN16x8, 8921 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 8922 mkU8(11)) ); 8923 assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 8924 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 8925 putVReg( vD_addr, 8926 binop(Iop_OrV128, 8927 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 8928 mkexpr(z23)) ); 8929 break; 8930 } 8931 default: 8932 vex_printf("dis_av_pack(ppc)(opc2)\n"); 8933 return False; 8934 } 8935 return True; 8936 } 8937 8938 8939 /* 8940 AltiVec Floating Point Arithmetic Instructions 8941 */ 8942 static Bool dis_av_fp_arith ( UInt theInstr ) 8943 { 8944 /* VA-Form */ 8945 UChar opc1 = ifieldOPC(theInstr); 8946 UChar vD_addr = ifieldRegDS(theInstr); 8947 UChar vA_addr = ifieldRegA(theInstr); 8948 UChar vB_addr = ifieldRegB(theInstr); 8949 UChar vC_addr = ifieldRegC(theInstr); 8950 UInt opc2=0; 8951 8952 IRTemp vA = newTemp(Ity_V128); 8953 IRTemp vB = newTemp(Ity_V128); 8954 IRTemp vC = newTemp(Ity_V128); 8955 assign( vA, getVReg(vA_addr)); 8956 assign( vB, getVReg(vB_addr)); 8957 assign( vC, getVReg(vC_addr)); 8958 8959 if (opc1 != 0x4) { 8960 vex_printf("dis_av_fp_arith(ppc)(instr)\n"); 8961 return False; 8962 } 8963 8964 opc2 = IFIELD( theInstr, 0, 6 ); 8965 switch (opc2) { 8966 case 0x2E: // vmaddfp (Multiply Add FP, AV p177) 8967 DIP("vmaddfp v%d,v%d,v%d,v%d\n", 8968 vD_addr, vA_addr, vC_addr, vB_addr); 8969 putVReg( vD_addr, 8970 binop(Iop_Add32Fx4, mkexpr(vB), 8971 binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) ); 8972 return True; 8973 8974 case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215) 8975 DIP("vnmsubfp v%d,v%d,v%d,v%d\n", 8976 vD_addr, vA_addr, vC_addr, vB_addr); 8977 putVReg( vD_addr, 8978 binop(Iop_Sub32Fx4, 8979 mkexpr(vB), 8980 binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) ); 8981 return True; 8982 } 8983 8984 default: 8985 break; // Fall through... 8986 } 8987 8988 opc2 = IFIELD( theInstr, 0, 11 ); 8989 switch (opc2) { 8990 case 0x00A: // vaddfp (Add FP, AV p137) 8991 DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8992 putVReg( vD_addr, binop(Iop_Add32Fx4, mkexpr(vA), mkexpr(vB)) ); 8993 return True; 8994 8995 case 0x04A: // vsubfp (Subtract FP, AV p261) 8996 DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 8997 putVReg( vD_addr, binop(Iop_Sub32Fx4, mkexpr(vA), mkexpr(vB)) ); 8998 return True; 8999 9000 case 0x40A: // vmaxfp (Maximum FP, AV p178) 9001 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 9002 putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) ); 9003 return True; 9004 9005 case 0x44A: // vminfp (Minimum FP, AV p187) 9006 DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 9007 putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) ); 9008 return True; 9009 9010 default: 9011 break; // Fall through... 9012 } 9013 9014 9015 if (vA_addr != 0) { 9016 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n"); 9017 return False; 9018 } 9019 9020 switch (opc2) { 9021 case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228) 9022 DIP("vrefp v%d,v%d\n", vD_addr, vB_addr); 9023 putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) ); 9024 return True; 9025 9026 case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237) 9027 DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr); 9028 putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) ); 9029 return True; 9030 9031 case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173) 9032 DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr); 9033 DIP(" => not implemented\n"); 9034 return False; 9035 9036 case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175) 9037 DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr); 9038 DIP(" => not implemented\n"); 9039 return False; 9040 9041 default: 9042 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2); 9043 return False; 9044 } 9045 return True; 9046 } 9047 9048 /* 9049 AltiVec Floating Point Compare Instructions 9050 */ 9051 static Bool dis_av_fp_cmp ( UInt theInstr ) 9052 { 9053 /* VXR-Form */ 9054 UChar opc1 = ifieldOPC(theInstr); 9055 UChar vD_addr = ifieldRegDS(theInstr); 9056 UChar vA_addr = ifieldRegA(theInstr); 9057 UChar vB_addr = ifieldRegB(theInstr); 9058 UChar flag_rC = ifieldBIT10(theInstr); 9059 UInt opc2 = IFIELD( theInstr, 0, 10 ); 9060 9061 Bool cmp_bounds = False; 9062 9063 IRTemp vA = newTemp(Ity_V128); 9064 IRTemp vB = newTemp(Ity_V128); 9065 IRTemp vD = newTemp(Ity_V128); 9066 assign( vA, getVReg(vA_addr)); 9067 assign( vB, getVReg(vB_addr)); 9068 9069 if (opc1 != 0x4) { 9070 vex_printf("dis_av_fp_cmp(ppc)(instr)\n"); 9071 return False; 9072 } 9073 9074 switch (opc2) { 9075 case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159) 9076 DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 9077 vD_addr, vA_addr, vB_addr); 9078 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 9079 break; 9080 9081 case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163) 9082 DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 9083 vD_addr, vA_addr, vB_addr); 9084 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 9085 break; 9086 9087 case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164) 9088 DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 9089 vD_addr, vA_addr, vB_addr); 9090 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 9091 break; 9092 9093 case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157) 9094 IRTemp gt = newTemp(Ity_V128); 9095 IRTemp lt = newTemp(Ity_V128); 9096 IRTemp zeros = newTemp(Ity_V128); 9097 DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 9098 vD_addr, vA_addr, vB_addr); 9099 cmp_bounds = True; 9100 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 9101 9102 /* Note: making use of fact that the ppc backend for compare insns 9103 return zero'd lanes if either of the corresponding arg lanes is 9104 a nan. 9105 9106 Perhaps better to have an irop Iop_isNan32Fx4, but then we'd 9107 need this for the other compares too (vcmpeqfp etc)... 9108 Better still, tighten down the spec for compare irops. 9109 */ 9110 assign( gt, unop(Iop_NotV128, 9111 binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) ); 9112 assign( lt, unop(Iop_NotV128, 9113 binop(Iop_CmpGE32Fx4, mkexpr(vA), 9114 binop(Iop_Sub32Fx4, mkexpr(zeros), 9115 mkexpr(vB)))) ); 9116 9117 // finally, just shift gt,lt to correct position 9118 assign( vD, binop(Iop_ShlN32x4, 9119 binop(Iop_OrV128, 9120 binop(Iop_AndV128, mkexpr(gt), 9121 unop(Iop_Dup32x4, mkU32(0x2))), 9122 binop(Iop_AndV128, mkexpr(lt), 9123 unop(Iop_Dup32x4, mkU32(0x1)))), 9124 mkU8(30)) ); 9125 break; 9126 } 9127 9128 default: 9129 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n"); 9130 return False; 9131 } 9132 9133 putVReg( vD_addr, mkexpr(vD) ); 9134 9135 if (flag_rC) { 9136 set_AV_CR6( mkexpr(vD), !cmp_bounds ); 9137 } 9138 return True; 9139 } 9140 9141 /* 9142 AltiVec Floating Point Convert/Round Instructions 9143 */ 9144 static Bool dis_av_fp_convert ( UInt theInstr ) 9145 { 9146 /* VX-Form */ 9147 UChar opc1 = ifieldOPC(theInstr); 9148 UChar vD_addr = ifieldRegDS(theInstr); 9149 UChar UIMM_5 = ifieldRegA(theInstr); 9150 UChar vB_addr = ifieldRegB(theInstr); 9151 UInt opc2 = IFIELD( theInstr, 0, 11 ); 9152 9153 IRTemp vB = newTemp(Ity_V128); 9154 IRTemp vScale = newTemp(Ity_V128); 9155 IRTemp vInvScale = newTemp(Ity_V128); 9156 9157 float scale, inv_scale; 9158 9159 assign( vB, getVReg(vB_addr)); 9160 9161 /* scale = 2^UIMM, cast to float, reinterpreted as uint */ 9162 scale = (float)( (unsigned int) 1<<UIMM_5 ); 9163 assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) ); 9164 inv_scale = 1/scale; 9165 assign( vInvScale, 9166 unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) ); 9167 9168 if (opc1 != 0x4) { 9169 vex_printf("dis_av_fp_convert(ppc)(instr)\n"); 9170 return False; 9171 } 9172 9173 switch (opc2) { 9174 case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156) 9175 DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 9176 putVReg( vD_addr, binop(Iop_Mul32Fx4, 9177 unop(Iop_I32UtoFx4, mkexpr(vB)), 9178 mkexpr(vInvScale)) ); 9179 return True; 9180 9181 case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155) 9182 DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 9183 9184 putVReg( vD_addr, binop(Iop_Mul32Fx4, 9185 unop(Iop_I32StoFx4, mkexpr(vB)), 9186 mkexpr(vInvScale)) ); 9187 return True; 9188 9189 case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172) 9190 DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 9191 putVReg( vD_addr, 9192 unop(Iop_QFtoI32Ux4_RZ, 9193 binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) ); 9194 return True; 9195 9196 case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171) 9197 DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 9198 putVReg( vD_addr, 9199 unop(Iop_QFtoI32Sx4_RZ, 9200 binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) ); 9201 return True; 9202 9203 default: 9204 break; // Fall through... 9205 } 9206 9207 if (UIMM_5 != 0) { 9208 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n"); 9209 return False; 9210 } 9211 9212 switch (opc2) { 9213 case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231) 9214 DIP("vrfin v%d,v%d\n", vD_addr, vB_addr); 9215 putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) ); 9216 break; 9217 9218 case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233) 9219 DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr); 9220 putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) ); 9221 break; 9222 9223 case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232) 9224 DIP("vrfip v%d,v%d\n", vD_addr, vB_addr); 9225 putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) ); 9226 break; 9227 9228 case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230) 9229 DIP("vrfim v%d,v%d\n", vD_addr, vB_addr); 9230 putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) ); 9231 break; 9232 9233 default: 9234 vex_printf("dis_av_fp_convert(ppc)(opc2)\n"); 9235 return False; 9236 } 9237 return True; 9238 } 9239 9240 9241 9242 9243 9244 /*------------------------------------------------------------*/ 9245 /*--- Disassemble a single instruction ---*/ 9246 /*------------------------------------------------------------*/ 9247 9248 /* Disassemble a single instruction into IR. The instruction 9249 is located in host memory at &guest_code[delta]. */ 9250 9251 static 9252 DisResult disInstr_PPC_WRK ( 9253 Bool put_IP, 9254 Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ), 9255 Bool resteerCisOk, 9256 void* callback_opaque, 9257 Long delta64, 9258 VexArchInfo* archinfo, 9259 VexAbiInfo* abiinfo 9260 ) 9261 { 9262 UChar opc1; 9263 UInt opc2; 9264 DisResult dres; 9265 UInt theInstr; 9266 IRType ty = mode64 ? Ity_I64 : Ity_I32; 9267 Bool allow_F = False; 9268 Bool allow_V = False; 9269 Bool allow_FX = False; 9270 Bool allow_GX = False; 9271 UInt hwcaps = archinfo->hwcaps; 9272 Long delta; 9273 9274 /* What insn variants are we supporting today? */ 9275 if (mode64) { 9276 allow_F = True; 9277 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC64_V)); 9278 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX)); 9279 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX)); 9280 } else { 9281 allow_F = (0 != (hwcaps & VEX_HWCAPS_PPC32_F)); 9282 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC32_V)); 9283 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX)); 9284 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX)); 9285 } 9286 9287 /* The running delta */ 9288 delta = (Long)mkSzAddr(ty, (ULong)delta64); 9289 9290 /* Set result defaults. */ 9291 dres.whatNext = Dis_Continue; 9292 dres.len = 0; 9293 dres.continueAt = 0; 9294 9295 /* At least this is simple on PPC32: insns are all 4 bytes long, and 9296 4-aligned. So just fish the whole thing out of memory right now 9297 and have done. */ 9298 theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) ); 9299 9300 if (0) vex_printf("insn: 0x%x\n", theInstr); 9301 9302 DIP("\t0x%llx: ", (ULong)guest_CIA_curr_instr); 9303 9304 /* We may be asked to update the guest CIA before going further. */ 9305 if (put_IP) 9306 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) ); 9307 9308 /* Spot "Special" instructions (see comment at top of file). */ 9309 { 9310 UChar* code = (UChar*)(guest_code + delta); 9311 /* Spot the 16-byte preamble: 9312 32-bit mode: 9313 54001800 rlwinm 0,0,3,0,0 9314 54006800 rlwinm 0,0,13,0,0 9315 5400E800 rlwinm 0,0,29,0,0 9316 54009800 rlwinm 0,0,19,0,0 9317 64-bit mode: 9318 78001800 rotldi 0,0,3 9319 78006800 rotldi 0,0,13 9320 7800E802 rotldi 0,0,61 9321 78009802 rotldi 0,0,51 9322 */ 9323 UInt word1 = mode64 ? 0x78001800 : 0x54001800; 9324 UInt word2 = mode64 ? 0x78006800 : 0x54006800; 9325 UInt word3 = mode64 ? 0x7800E802 : 0x5400E800; 9326 UInt word4 = mode64 ? 0x78009802 : 0x54009800; 9327 if (getUIntBigendianly(code+ 0) == word1 && 9328 getUIntBigendianly(code+ 4) == word2 && 9329 getUIntBigendianly(code+ 8) == word3 && 9330 getUIntBigendianly(code+12) == word4) { 9331 /* Got a "Special" instruction preamble. Which one is it? */ 9332 if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) { 9333 /* %R3 = client_request ( %R4 ) */ 9334 DIP("r3 = client_request ( %%r4 )\n"); 9335 delta += 20; 9336 irsb->next = mkSzImm( ty, guest_CIA_bbstart + delta ); 9337 irsb->jumpkind = Ijk_ClientReq; 9338 dres.whatNext = Dis_StopHere; 9339 goto decode_success; 9340 } 9341 else 9342 if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) { 9343 /* %R3 = guest_NRADDR */ 9344 DIP("r3 = guest_NRADDR\n"); 9345 delta += 20; 9346 dres.len = 20; 9347 putIReg(3, IRExpr_Get( OFFB_NRADDR, ty )); 9348 goto decode_success; 9349 } 9350 else 9351 if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) { 9352 /* branch-and-link-to-noredir %R11 */ 9353 DIP("branch-and-link-to-noredir r11\n"); 9354 delta += 20; 9355 putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) ); 9356 irsb->next = getIReg(11); 9357 irsb->jumpkind = Ijk_NoRedir; 9358 dres.whatNext = Dis_StopHere; 9359 goto decode_success; 9360 } 9361 else 9362 if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { 9363 /* %R3 = guest_NRADDR_GPR2 */ 9364 DIP("r3 = guest_NRADDR_GPR2\n"); 9365 delta += 20; 9366 dres.len = 20; 9367 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty )); 9368 goto decode_success; 9369 } 9370 /* We don't know what it is. Set opc1/opc2 so decode_failure 9371 can print the insn following the Special-insn preamble. */ 9372 theInstr = getUIntBigendianly(code+16); 9373 opc1 = ifieldOPC(theInstr); 9374 opc2 = ifieldOPClo10(theInstr); 9375 goto decode_failure; 9376 /*NOTREACHED*/ 9377 } 9378 } 9379 9380 opc1 = ifieldOPC(theInstr); 9381 opc2 = ifieldOPClo10(theInstr); 9382 9383 // Note: all 'reserved' bits must be cleared, else invalid 9384 switch (opc1) { 9385 9386 /* Integer Arithmetic Instructions */ 9387 case 0x0C: case 0x0D: case 0x0E: // addic, addic., addi 9388 case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic 9389 if (dis_int_arith( theInstr )) goto decode_success; 9390 goto decode_failure; 9391 9392 /* Integer Compare Instructions */ 9393 case 0x0B: case 0x0A: // cmpi, cmpli 9394 if (dis_int_cmp( theInstr )) goto decode_success; 9395 goto decode_failure; 9396 9397 /* Integer Logical Instructions */ 9398 case 0x1C: case 0x1D: case 0x18: // andi., andis., ori 9399 case 0x19: case 0x1A: case 0x1B: // oris, xori, xoris 9400 if (dis_int_logic( theInstr )) goto decode_success; 9401 goto decode_failure; 9402 9403 /* Integer Rotate Instructions */ 9404 case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm 9405 if (dis_int_rot( theInstr )) goto decode_success; 9406 goto decode_failure; 9407 9408 /* 64bit Integer Rotate Instructions */ 9409 case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi 9410 if (dis_int_rot( theInstr )) goto decode_success; 9411 goto decode_failure; 9412 9413 /* Integer Load Instructions */ 9414 case 0x22: case 0x23: case 0x2A: // lbz, lbzu, lha 9415 case 0x2B: case 0x28: case 0x29: // lhau, lhz, lhzu 9416 case 0x20: case 0x21: // lwz, lwzu 9417 if (dis_int_load( theInstr )) goto decode_success; 9418 goto decode_failure; 9419 9420 /* Integer Store Instructions */ 9421 case 0x26: case 0x27: case 0x2C: // stb, stbu, sth 9422 case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu 9423 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 9424 goto decode_failure; 9425 9426 /* Integer Load and Store Multiple Instructions */ 9427 case 0x2E: case 0x2F: // lmw, stmw 9428 if (dis_int_ldst_mult( theInstr )) goto decode_success; 9429 goto decode_failure; 9430 9431 /* Branch Instructions */ 9432 case 0x12: case 0x10: // b, bc 9433 if (dis_branch(theInstr, abiinfo, &dres, 9434 resteerOkFn, callback_opaque)) 9435 goto decode_success; 9436 goto decode_failure; 9437 9438 /* System Linkage Instructions */ 9439 case 0x11: // sc 9440 if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success; 9441 goto decode_failure; 9442 9443 /* Trap Instructions */ 9444 case 0x02: case 0x03: // tdi, twi 9445 if (dis_trapi(theInstr, &dres)) goto decode_success; 9446 goto decode_failure; 9447 9448 /* Floating Point Load Instructions */ 9449 case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd 9450 case 0x33: // lfdu 9451 if (!allow_F) goto decode_noF; 9452 if (dis_fp_load( theInstr )) goto decode_success; 9453 goto decode_failure; 9454 9455 /* Floating Point Store Instructions */ 9456 case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx 9457 case 0x37: // stfdux 9458 if (!allow_F) goto decode_noF; 9459 if (dis_fp_store( theInstr )) goto decode_success; 9460 goto decode_failure; 9461 9462 /* Floating Point Load Double Pair Instructions */ 9463 case 0x39: case 0x3D: 9464 if (!allow_F) goto decode_noF; 9465 if (dis_fp_pair( theInstr )) goto decode_success; 9466 goto decode_failure; 9467 9468 /* 64bit Integer Loads */ 9469 case 0x3A: // ld, ldu, lwa 9470 if (!mode64) goto decode_failure; 9471 if (dis_int_load( theInstr )) goto decode_success; 9472 goto decode_failure; 9473 9474 case 0x3B: 9475 if (!allow_F) goto decode_noF; 9476 opc2 = IFIELD(theInstr, 1, 5); 9477 switch (opc2) { 9478 /* Floating Point Arith Instructions */ 9479 case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds 9480 case 0x19: // fmuls 9481 if (dis_fp_arith(theInstr)) goto decode_success; 9482 goto decode_failure; 9483 case 0x16: // fsqrts 9484 if (!allow_FX) goto decode_noFX; 9485 if (dis_fp_arith(theInstr)) goto decode_success; 9486 goto decode_failure; 9487 case 0x18: // fres 9488 if (!allow_GX) goto decode_noGX; 9489 if (dis_fp_arith(theInstr)) goto decode_success; 9490 goto decode_failure; 9491 9492 /* Floating Point Mult-Add Instructions */ 9493 case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs 9494 case 0x1F: // fnmadds 9495 if (dis_fp_multadd(theInstr)) goto decode_success; 9496 goto decode_failure; 9497 9498 case 0x1A: // frsqrtes 9499 if (!allow_GX) goto decode_noGX; 9500 if (dis_fp_arith(theInstr)) goto decode_success; 9501 goto decode_failure; 9502 9503 default: 9504 goto decode_failure; 9505 } 9506 break; 9507 9508 /* 64bit Integer Stores */ 9509 case 0x3E: // std, stdu 9510 if (!mode64) goto decode_failure; 9511 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 9512 goto decode_failure; 9513 9514 case 0x3F: 9515 if (!allow_F) goto decode_noF; 9516 /* Instrs using opc[1:5] never overlap instrs using opc[1:10], 9517 so we can simply fall through the first switch statement */ 9518 9519 opc2 = IFIELD(theInstr, 1, 5); 9520 switch (opc2) { 9521 /* Floating Point Arith Instructions */ 9522 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd 9523 case 0x19: // fmul 9524 if (dis_fp_arith(theInstr)) goto decode_success; 9525 goto decode_failure; 9526 case 0x16: // fsqrt 9527 if (!allow_FX) goto decode_noFX; 9528 if (dis_fp_arith(theInstr)) goto decode_success; 9529 goto decode_failure; 9530 case 0x17: case 0x1A: // fsel, frsqrte 9531 if (!allow_GX) goto decode_noGX; 9532 if (dis_fp_arith(theInstr)) goto decode_success; 9533 goto decode_failure; 9534 9535 /* Floating Point Mult-Add Instructions */ 9536 case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub 9537 case 0x1F: // fnmadd 9538 if (dis_fp_multadd(theInstr)) goto decode_success; 9539 goto decode_failure; 9540 9541 case 0x18: // fre 9542 if (!allow_GX) goto decode_noGX; 9543 if (dis_fp_arith(theInstr)) goto decode_success; 9544 goto decode_failure; 9545 9546 default: 9547 break; // Fall through 9548 } 9549 9550 opc2 = IFIELD(theInstr, 1, 10); 9551 switch (opc2) { 9552 /* Floating Point Compare Instructions */ 9553 case 0x000: // fcmpu 9554 case 0x020: // fcmpo 9555 if (dis_fp_cmp(theInstr)) goto decode_success; 9556 goto decode_failure; 9557 9558 /* Floating Point Rounding/Conversion Instructions */ 9559 case 0x00C: // frsp 9560 case 0x00E: // fctiw 9561 case 0x00F: // fctiwz 9562 case 0x32E: // fctid 9563 case 0x32F: // fctidz 9564 case 0x34E: // fcfid 9565 if (dis_fp_round(theInstr)) goto decode_success; 9566 goto decode_failure; 9567 9568 /* Power6 rounding stuff */ 9569 case 0x1E8: // frim 9570 case 0x1C8: // frip 9571 case 0x188: // frin 9572 case 0x1A8: // friz 9573 /* A hack to check for P6 capability . . . */ 9574 if ((allow_F && allow_V && allow_FX && allow_GX) && 9575 (dis_fp_round(theInstr))) 9576 goto decode_success; 9577 goto decode_failure; 9578 9579 /* Floating Point Move Instructions */ 9580 case 0x008: // fcpsgn 9581 case 0x028: // fneg 9582 case 0x048: // fmr 9583 case 0x088: // fnabs 9584 case 0x108: // fabs 9585 if (dis_fp_move( theInstr )) goto decode_success; 9586 goto decode_failure; 9587 9588 /* Floating Point Status/Control Register Instructions */ 9589 case 0x026: // mtfsb1 9590 case 0x040: // mcrfs 9591 case 0x046: // mtfsb0 9592 case 0x086: // mtfsfi 9593 case 0x247: // mffs 9594 case 0x2C7: // mtfsf 9595 if (dis_fp_scr( theInstr )) goto decode_success; 9596 goto decode_failure; 9597 9598 default: 9599 goto decode_failure; 9600 } 9601 break; 9602 9603 case 0x13: 9604 switch (opc2) { 9605 9606 /* Condition Register Logical Instructions */ 9607 case 0x101: case 0x081: case 0x121: // crand, crandc, creqv 9608 case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror 9609 case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf 9610 if (dis_cond_logic( theInstr )) goto decode_success; 9611 goto decode_failure; 9612 9613 /* Branch Instructions */ 9614 case 0x210: case 0x010: // bcctr, bclr 9615 if (dis_branch(theInstr, abiinfo, &dres, 9616 resteerOkFn, callback_opaque)) 9617 goto decode_success; 9618 goto decode_failure; 9619 9620 /* Memory Synchronization Instructions */ 9621 case 0x096: // isync 9622 if (dis_memsync( theInstr )) goto decode_success; 9623 goto decode_failure; 9624 9625 default: 9626 goto decode_failure; 9627 } 9628 break; 9629 9630 9631 case 0x1F: 9632 9633 /* For arith instns, bit10 is the OE flag (overflow enable) */ 9634 9635 opc2 = IFIELD(theInstr, 1, 9); 9636 switch (opc2) { 9637 /* Integer Arithmetic Instructions */ 9638 case 0x10A: case 0x00A: case 0x08A: // add, addc, adde 9639 case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw 9640 case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu 9641 case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf 9642 case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme 9643 case 0x0C8: // subfze 9644 if (dis_int_arith( theInstr )) goto decode_success; 9645 goto decode_failure; 9646 9647 /* 64bit Integer Arithmetic */ 9648 case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld 9649 case 0x1C9: case 0x1E9: // divdu, divd 9650 if (!mode64) goto decode_failure; 9651 if (dis_int_arith( theInstr )) goto decode_success; 9652 goto decode_failure; 9653 9654 case 0x1FC: // cmpb 9655 if (dis_int_logic( theInstr )) goto decode_success; 9656 goto decode_failure; 9657 9658 default: 9659 break; // Fall through... 9660 } 9661 9662 /* All remaining opcodes use full 10 bits. */ 9663 9664 opc2 = IFIELD(theInstr, 1, 10); 9665 switch (opc2) { 9666 /* Integer Compare Instructions */ 9667 case 0x000: case 0x020: // cmp, cmpl 9668 if (dis_int_cmp( theInstr )) goto decode_success; 9669 goto decode_failure; 9670 9671 /* Integer Logical Instructions */ 9672 case 0x01C: case 0x03C: case 0x01A: // and, andc, cntlzw 9673 case 0x11C: case 0x3BA: case 0x39A: // eqv, extsb, extsh 9674 case 0x1DC: case 0x07C: case 0x1BC: // nand, nor, or 9675 case 0x19C: case 0x13C: // orc, xor 9676 case 0x2DF: case 0x25F: // mftgpr, mffgpr 9677 if (dis_int_logic( theInstr )) goto decode_success; 9678 goto decode_failure; 9679 9680 /* 64bit Integer Logical Instructions */ 9681 case 0x3DA: case 0x03A: // extsw, cntlzd 9682 if (!mode64) goto decode_failure; 9683 if (dis_int_logic( theInstr )) goto decode_success; 9684 goto decode_failure; 9685 9686 /* 64bit Integer Parity Instructions */ 9687 case 0xba: case 0x9a: // prtyd, prtyw 9688 if (dis_int_parity( theInstr )) goto decode_success; 9689 goto decode_failure; 9690 9691 /* Integer Shift Instructions */ 9692 case 0x018: case 0x318: case 0x338: // slw, sraw, srawi 9693 case 0x218: // srw 9694 if (dis_int_shift( theInstr )) goto decode_success; 9695 goto decode_failure; 9696 9697 /* 64bit Integer Shift Instructions */ 9698 case 0x01B: case 0x31A: // sld, srad 9699 case 0x33A: case 0x33B: // sradi 9700 case 0x21B: // srd 9701 if (!mode64) goto decode_failure; 9702 if (dis_int_shift( theInstr )) goto decode_success; 9703 goto decode_failure; 9704 9705 /* Integer Load Instructions */ 9706 case 0x057: case 0x077: case 0x157: // lbzx, lbzux, lhax 9707 case 0x177: case 0x117: case 0x137: // lhaux, lhzx, lhzux 9708 case 0x017: case 0x037: // lwzx, lwzux 9709 if (dis_int_load( theInstr )) goto decode_success; 9710 goto decode_failure; 9711 9712 /* 64bit Integer Load Instructions */ 9713 case 0x035: case 0x015: // ldux, ldx 9714 case 0x175: case 0x155: // lwaux, lwax 9715 if (!mode64) goto decode_failure; 9716 if (dis_int_load( theInstr )) goto decode_success; 9717 goto decode_failure; 9718 9719 /* Integer Store Instructions */ 9720 case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux 9721 case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx 9722 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 9723 goto decode_failure; 9724 9725 /* 64bit Integer Store Instructions */ 9726 case 0x0B5: case 0x095: // stdux, stdx 9727 if (!mode64) goto decode_failure; 9728 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 9729 goto decode_failure; 9730 9731 /* Integer Load and Store with Byte Reverse Instructions */ 9732 case 0x316: case 0x216: case 0x396: // lhbrx, lwbrx, sthbrx 9733 case 0x296: // stwbrx 9734 if (dis_int_ldst_rev( theInstr )) goto decode_success; 9735 goto decode_failure; 9736 9737 /* Integer Load and Store String Instructions */ 9738 case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi 9739 case 0x295: { // stswx 9740 Bool stopHere = False; 9741 Bool ok = dis_int_ldst_str( theInstr, &stopHere ); 9742 if (!ok) goto decode_failure; 9743 if (stopHere) { 9744 irsb->next = mkSzImm(ty, nextInsnAddr()); 9745 irsb->jumpkind = Ijk_Boring; 9746 dres.whatNext = Dis_StopHere; 9747 } 9748 goto decode_success; 9749 } 9750 9751 /* Memory Synchronization Instructions */ 9752 case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx. 9753 case 0x256: // sync 9754 if (dis_memsync( theInstr )) goto decode_success; 9755 goto decode_failure; 9756 9757 /* 64bit Memory Synchronization Instructions */ 9758 case 0x054: case 0x0D6: // ldarx, stdcx. 9759 if (!mode64) goto decode_failure; 9760 if (dis_memsync( theInstr )) goto decode_success; 9761 goto decode_failure; 9762 9763 /* Processor Control Instructions */ 9764 case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr 9765 case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr 9766 if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success; 9767 goto decode_failure; 9768 9769 /* Cache Management Instructions */ 9770 case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst 9771 case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz 9772 case 0x3D6: // icbi 9773 if (dis_cache_manage( theInstr, &dres, archinfo )) 9774 goto decode_success; 9775 goto decode_failure; 9776 9777 //zz /* External Control Instructions */ 9778 //zz case 0x136: case 0x1B6: // eciwx, ecowx 9779 //zz DIP("external control op => not implemented\n"); 9780 //zz goto decode_failure; 9781 9782 /* Trap Instructions */ 9783 case 0x004: case 0x044: // tw, td 9784 if (dis_trap(theInstr, &dres)) goto decode_success; 9785 goto decode_failure; 9786 9787 /* Floating Point Load Instructions */ 9788 case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx 9789 case 0x277: // lfdux 9790 if (!allow_F) goto decode_noF; 9791 if (dis_fp_load( theInstr )) goto decode_success; 9792 goto decode_failure; 9793 9794 /* Floating Point Store Instructions */ 9795 case 0x297: case 0x2B7: case 0x2D7: // stfs, stfsu, stfd 9796 case 0x2F7: // stfdu, stfiwx 9797 if (!allow_F) goto decode_noF; 9798 if (dis_fp_store( theInstr )) goto decode_success; 9799 goto decode_failure; 9800 case 0x3D7: // stfiwx 9801 if (!allow_F) goto decode_noF; 9802 if (!allow_GX) goto decode_noGX; 9803 if (dis_fp_store( theInstr )) goto decode_success; 9804 goto decode_failure; 9805 9806 /* Floating Point Double Pair Indexed Instructions */ 9807 case 0x317: // lfdpx (Power6) 9808 case 0x397: // stfdpx (Power6) 9809 if (!allow_F) goto decode_noF; 9810 if (dis_fp_pair(theInstr)) goto decode_success; 9811 goto decode_failure; 9812 9813 case 0x357: // lfiwax 9814 if (!allow_F) goto decode_noF; 9815 if (dis_fp_load( theInstr )) goto decode_success; 9816 goto decode_failure; 9817 9818 /* AltiVec instructions */ 9819 9820 /* AV Cache Control - Data streams */ 9821 case 0x156: case 0x176: case 0x336: // dst, dstst, dss 9822 if (!allow_V) goto decode_noV; 9823 if (dis_av_datastream( theInstr )) goto decode_success; 9824 goto decode_failure; 9825 9826 /* AV Load */ 9827 case 0x006: case 0x026: // lvsl, lvsr 9828 case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx 9829 case 0x067: case 0x167: // lvx, lvxl 9830 if (!allow_V) goto decode_noV; 9831 if (dis_av_load( abiinfo, theInstr )) goto decode_success; 9832 goto decode_failure; 9833 9834 /* AV Store */ 9835 case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx 9836 case 0x0E7: case 0x1E7: // stvx, stvxl 9837 if (!allow_V) goto decode_noV; 9838 if (dis_av_store( theInstr )) goto decode_success; 9839 goto decode_failure; 9840 9841 default: 9842 /* Deal with some other cases that we would otherwise have 9843 punted on. */ 9844 /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */ 9845 /* only decode this insn when reserved bit 0 (31 in IBM's 9846 notation) is zero */ 9847 if (IFIELD(theInstr, 0, 6) == (15<<1)) { 9848 UInt rT = ifieldRegDS( theInstr ); 9849 UInt rA = ifieldRegA( theInstr ); 9850 UInt rB = ifieldRegB( theInstr ); 9851 UInt bi = ifieldRegC( theInstr ); 9852 putIReg( 9853 rT, 9854 IRExpr_Mux0X( unop(Iop_32to8,getCRbit( bi )), 9855 getIReg(rB), 9856 rA == 0 ? (mode64 ? mkU64(0) : mkU32(0)) 9857 : getIReg(rA) ) 9858 ); 9859 DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi); 9860 goto decode_success; 9861 } 9862 goto decode_failure; 9863 } 9864 break; 9865 9866 9867 case 0x04: 9868 /* AltiVec instructions */ 9869 9870 opc2 = IFIELD(theInstr, 0, 6); 9871 switch (opc2) { 9872 /* AV Mult-Add, Mult-Sum */ 9873 case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm 9874 case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm 9875 case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs 9876 if (!allow_V) goto decode_noV; 9877 if (dis_av_multarith( theInstr )) goto decode_success; 9878 goto decode_failure; 9879 9880 /* AV Permutations */ 9881 case 0x2A: // vsel 9882 case 0x2B: // vperm 9883 case 0x2C: // vsldoi 9884 if (!allow_V) goto decode_noV; 9885 if (dis_av_permute( theInstr )) goto decode_success; 9886 goto decode_failure; 9887 9888 /* AV Floating Point Mult-Add/Sub */ 9889 case 0x2E: case 0x2F: // vmaddfp, vnmsubfp 9890 if (!allow_V) goto decode_noV; 9891 if (dis_av_fp_arith( theInstr )) goto decode_success; 9892 goto decode_failure; 9893 9894 default: 9895 break; // Fall through... 9896 } 9897 9898 opc2 = IFIELD(theInstr, 0, 11); 9899 switch (opc2) { 9900 /* AV Arithmetic */ 9901 case 0x180: // vaddcuw 9902 case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm 9903 case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws 9904 case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws 9905 case 0x580: // vsubcuw 9906 case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm 9907 case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws 9908 case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws 9909 case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw 9910 case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw 9911 case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw 9912 case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw 9913 case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw 9914 case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw 9915 case 0x008: case 0x048: // vmuloub, vmulouh 9916 case 0x108: case 0x148: // vmulosb, vmulosh 9917 case 0x208: case 0x248: // vmuleub, vmuleuh 9918 case 0x308: case 0x348: // vmulesb, vmulesh 9919 case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs 9920 case 0x688: case 0x788: // vsum2sws, vsumsws 9921 if (!allow_V) goto decode_noV; 9922 if (dis_av_arith( theInstr )) goto decode_success; 9923 goto decode_failure; 9924 9925 /* AV Rotate, Shift */ 9926 case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw 9927 case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw 9928 case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw 9929 case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw 9930 case 0x1C4: case 0x2C4: // vsl, vsr 9931 case 0x40C: case 0x44C: // vslo, vsro 9932 if (!allow_V) goto decode_noV; 9933 if (dis_av_shift( theInstr )) goto decode_success; 9934 goto decode_failure; 9935 9936 /* AV Logic */ 9937 case 0x404: case 0x444: case 0x484: // vand, vandc, vor 9938 case 0x4C4: case 0x504: // vxor, vnor 9939 if (!allow_V) goto decode_noV; 9940 if (dis_av_logic( theInstr )) goto decode_success; 9941 goto decode_failure; 9942 9943 /* AV Processor Control */ 9944 case 0x604: case 0x644: // mfvscr, mtvscr 9945 if (!allow_V) goto decode_noV; 9946 if (dis_av_procctl( theInstr )) goto decode_success; 9947 goto decode_failure; 9948 9949 /* AV Floating Point Arithmetic */ 9950 case 0x00A: case 0x04A: // vaddfp, vsubfp 9951 case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp 9952 case 0x1CA: // vlogefp 9953 case 0x40A: case 0x44A: // vmaxfp, vminfp 9954 if (!allow_V) goto decode_noV; 9955 if (dis_av_fp_arith( theInstr )) goto decode_success; 9956 goto decode_failure; 9957 9958 /* AV Floating Point Round/Convert */ 9959 case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip 9960 case 0x2CA: // vrfim 9961 case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs 9962 case 0x3CA: // vctsxs 9963 if (!allow_V) goto decode_noV; 9964 if (dis_av_fp_convert( theInstr )) goto decode_success; 9965 goto decode_failure; 9966 9967 /* AV Merge, Splat */ 9968 case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw 9969 case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw 9970 case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw 9971 case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw 9972 if (!allow_V) goto decode_noV; 9973 if (dis_av_permute( theInstr )) goto decode_success; 9974 goto decode_failure; 9975 9976 /* AV Pack, Unpack */ 9977 case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus 9978 case 0x0CE: // vpkuwus 9979 case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss 9980 case 0x1CE: // vpkswss 9981 case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb 9982 case 0x2CE: // vupklsh 9983 case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx 9984 if (!allow_V) goto decode_noV; 9985 if (dis_av_pack( theInstr )) goto decode_success; 9986 goto decode_failure; 9987 9988 default: 9989 break; // Fall through... 9990 } 9991 9992 opc2 = IFIELD(theInstr, 0, 10); 9993 switch (opc2) { 9994 9995 /* AV Compare */ 9996 case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw 9997 case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw 9998 case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw 9999 if (!allow_V) goto decode_noV; 10000 if (dis_av_cmp( theInstr )) goto decode_success; 10001 goto decode_failure; 10002 10003 /* AV Floating Point Compare */ 10004 case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp 10005 case 0x3C6: // vcmpbfp 10006 if (!allow_V) goto decode_noV; 10007 if (dis_av_fp_cmp( theInstr )) goto decode_success; 10008 goto decode_failure; 10009 10010 default: 10011 goto decode_failure; 10012 } 10013 break; 10014 10015 default: 10016 goto decode_failure; 10017 10018 decode_noF: 10019 vassert(!allow_F); 10020 vex_printf("disInstr(ppc): declined to decode an FP insn.\n"); 10021 goto decode_failure; 10022 decode_noV: 10023 vassert(!allow_V); 10024 vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n"); 10025 goto decode_failure; 10026 decode_noFX: 10027 vassert(!allow_FX); 10028 vex_printf("disInstr(ppc): " 10029 "declined to decode a GeneralPurpose-Optional insn.\n"); 10030 goto decode_failure; 10031 decode_noGX: 10032 vassert(!allow_GX); 10033 vex_printf("disInstr(ppc): " 10034 "declined to decode a Graphics-Optional insn.\n"); 10035 goto decode_failure; 10036 10037 decode_failure: 10038 /* All decode failures end up here. */ 10039 opc2 = (theInstr) & 0x7FF; 10040 vex_printf("disInstr(ppc): unhandled instruction: " 10041 "0x%x\n", theInstr); 10042 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n", 10043 opc1, opc1, opc2, opc2); 10044 10045 /* Tell the dispatcher that this insn cannot be decoded, and so has 10046 not been executed, and (is currently) the next to be executed. 10047 CIA should be up-to-date since it made so at the start of each 10048 insn, but nevertheless be paranoid and update it again right 10049 now. */ 10050 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) ); 10051 irsb->next = mkSzImm(ty, guest_CIA_curr_instr); 10052 irsb->jumpkind = Ijk_NoDecode; 10053 dres.whatNext = Dis_StopHere; 10054 dres.len = 0; 10055 return dres; 10056 10057 } /* switch (opc) for the main (primary) opcode switch. */ 10058 10059 decode_success: 10060 /* All decode successes end up here. */ 10061 DIP("\n"); 10062 10063 if (dres.len == 0) { 10064 dres.len = 4; 10065 } else { 10066 vassert(dres.len == 20); 10067 } 10068 return dres; 10069 } 10070 10071 #undef DIP 10072 #undef DIS 10073 10074 10075 /*------------------------------------------------------------*/ 10076 /*--- Top-level fn ---*/ 10077 /*------------------------------------------------------------*/ 10078 10079 /* Disassemble a single instruction into IR. The instruction 10080 is located in host memory at &guest_code[delta]. */ 10081 10082 DisResult disInstr_PPC ( IRSB* irsb_IN, 10083 Bool put_IP, 10084 Bool (*resteerOkFn) ( void*, Addr64 ), 10085 Bool resteerCisOk, 10086 void* callback_opaque, 10087 UChar* guest_code_IN, 10088 Long delta, 10089 Addr64 guest_IP, 10090 VexArch guest_arch, 10091 VexArchInfo* archinfo, 10092 VexAbiInfo* abiinfo, 10093 Bool host_bigendian_IN ) 10094 { 10095 IRType ty; 10096 DisResult dres; 10097 UInt mask32, mask64; 10098 UInt hwcaps_guest = archinfo->hwcaps; 10099 10100 vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64); 10101 10102 /* global -- ick */ 10103 mode64 = guest_arch == VexArchPPC64; 10104 ty = mode64 ? Ity_I64 : Ity_I32; 10105 10106 /* do some sanity checks */ 10107 mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V 10108 | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX; 10109 10110 mask64 = VEX_HWCAPS_PPC64_V 10111 | VEX_HWCAPS_PPC64_FX | VEX_HWCAPS_PPC64_GX; 10112 10113 if (mode64) { 10114 vassert((hwcaps_guest & mask32) == 0); 10115 } else { 10116 vassert((hwcaps_guest & mask64) == 0); 10117 } 10118 10119 /* Set globals (see top of this file) */ 10120 guest_code = guest_code_IN; 10121 irsb = irsb_IN; 10122 host_is_bigendian = host_bigendian_IN; 10123 10124 guest_CIA_curr_instr = mkSzAddr(ty, guest_IP); 10125 guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta); 10126 10127 dres = disInstr_PPC_WRK ( put_IP, 10128 resteerOkFn, resteerCisOk, callback_opaque, 10129 delta, archinfo, abiinfo ); 10130 10131 return dres; 10132 } 10133 10134 10135 /*------------------------------------------------------------*/ 10136 /*--- Unused stuff ---*/ 10137 /*------------------------------------------------------------*/ 10138 10139 ///* A potentially more memcheck-friendly implementation of Clz32, with 10140 // the boundary case Clz32(0) = 32, which is what ppc requires. */ 10141 // 10142 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg ) 10143 //{ 10144 // /* Welcome ... to SSA R Us. */ 10145 // IRTemp n1 = newTemp(Ity_I32); 10146 // IRTemp n2 = newTemp(Ity_I32); 10147 // IRTemp n3 = newTemp(Ity_I32); 10148 // IRTemp n4 = newTemp(Ity_I32); 10149 // IRTemp n5 = newTemp(Ity_I32); 10150 // IRTemp n6 = newTemp(Ity_I32); 10151 // IRTemp n7 = newTemp(Ity_I32); 10152 // IRTemp n8 = newTemp(Ity_I32); 10153 // IRTemp n9 = newTemp(Ity_I32); 10154 // IRTemp n10 = newTemp(Ity_I32); 10155 // IRTemp n11 = newTemp(Ity_I32); 10156 // IRTemp n12 = newTemp(Ity_I32); 10157 // 10158 // /* First, propagate the most significant 1-bit into all lower 10159 // positions in the word. */ 10160 // /* unsigned int clz ( unsigned int n ) 10161 // { 10162 // n |= (n >> 1); 10163 // n |= (n >> 2); 10164 // n |= (n >> 4); 10165 // n |= (n >> 8); 10166 // n |= (n >> 16); 10167 // return bitcount(~n); 10168 // } 10169 // */ 10170 // assign(n1, mkexpr(arg)); 10171 // assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1)))); 10172 // assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2)))); 10173 // assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4)))); 10174 // assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8)))); 10175 // assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16)))); 10176 // /* This gives a word of the form 0---01---1. Now invert it, giving 10177 // a word of the form 1---10---0, then do a population-count idiom 10178 // (to count the 1s, which is the number of leading zeroes, or 32 10179 // if the original word was 0. */ 10180 // assign(n7, unop(Iop_Not32, mkexpr(n6))); 10181 // 10182 // /* unsigned int bitcount ( unsigned int n ) 10183 // { 10184 // n = n - ((n >> 1) & 0x55555555); 10185 // n = (n & 0x33333333) + ((n >> 2) & 0x33333333); 10186 // n = (n + (n >> 4)) & 0x0F0F0F0F; 10187 // n = n + (n >> 8); 10188 // n = (n + (n >> 16)) & 0x3F; 10189 // return n; 10190 // } 10191 // */ 10192 // assign(n8, 10193 // binop(Iop_Sub32, 10194 // mkexpr(n7), 10195 // binop(Iop_And32, 10196 // binop(Iop_Shr32, mkexpr(n7), mkU8(1)), 10197 // mkU32(0x55555555)))); 10198 // assign(n9, 10199 // binop(Iop_Add32, 10200 // binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)), 10201 // binop(Iop_And32, 10202 // binop(Iop_Shr32, mkexpr(n8), mkU8(2)), 10203 // mkU32(0x33333333)))); 10204 // assign(n10, 10205 // binop(Iop_And32, 10206 // binop(Iop_Add32, 10207 // mkexpr(n9), 10208 // binop(Iop_Shr32, mkexpr(n9), mkU8(4))), 10209 // mkU32(0x0F0F0F0F))); 10210 // assign(n11, 10211 // binop(Iop_Add32, 10212 // mkexpr(n10), 10213 // binop(Iop_Shr32, mkexpr(n10), mkU8(8)))); 10214 // assign(n12, 10215 // binop(Iop_Add32, 10216 // mkexpr(n11), 10217 // binop(Iop_Shr32, mkexpr(n11), mkU8(16)))); 10218 // return 10219 // binop(Iop_And32, mkexpr(n12), mkU32(0x3F)); 10220 //} 10221 10222 /*--------------------------------------------------------------------*/ 10223 /*--- end guest_ppc_toIR.c ---*/ 10224 /*--------------------------------------------------------------------*/ 10225