1 2 3/*--------------------------------------------------------------------*/ 4/*--- begin guest_ppc_toIR.c ---*/ 5/*--------------------------------------------------------------------*/ 6 7/* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright (C) 2004-2011 OpenWorks LLP 12 info@open-works.net 13 14 This program is free software; you can redistribute it and/or 15 modify it under the terms of the GNU General Public License as 16 published by the Free Software Foundation; either version 2 of the 17 License, or (at your option) any later version. 18 19 This program is distributed in the hope that it will be useful, but 20 WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 General Public License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; if not, write to the Free Software 26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 27 02110-1301, USA. 28 29 The GNU General Public License is contained in the file COPYING. 30 31 Neither the names of the U.S. Department of Energy nor the 32 University of California nor the names of its contributors may be 33 used to endorse or promote products derived from this software 34 without prior written permission. 35*/ 36 37/* TODO 18/Nov/05: 38 39 Spot rld... cases which are simply left/right shifts and emit 40 Shl64/Shr64 accordingly. 41 42 Altivec 43 - datastream insns 44 - lvxl,stvxl: load/store with 'least recently used' hint 45 - vexptefp, vlogefp 46 47 LIMITATIONS: 48 49 Various, including: 50 51 - Some invalid forms of lswi and lswx are accepted when they should 52 not be. 53 54 - Floating Point: 55 - All exceptions disabled in FPSCR 56 - condition codes not set in FPSCR 57 58 - Altivec floating point: 59 - vmaddfp, vnmsubfp 60 Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the 61 system default of Non-Java mode, we get some small errors 62 (lowest bit only). 63 This is because Non-Java mode brutally hacks denormalised results 64 to zero, whereas we keep maximum accuracy. However, using 65 Non-Java mode would give us more inaccuracy, as our intermediate 66 results would then be zeroed, too. 67 68 - AbiHints for the stack red zone are only emitted for 69 unconditional calls and returns (bl, blr). They should also be 70 emitted for conditional calls and returns, but we don't have a 71 way to express that right now. Ah well. 72*/ 73 74/* "Special" instructions. 75 76 This instruction decoder can decode four special instructions 77 which mean nothing natively (are no-ops as far as regs/mem are 78 concerned) but have meaning for supporting Valgrind. A special 79 instruction is flagged by a 16-byte preamble: 80 81 32-bit mode: 54001800 54006800 5400E800 54009800 82 (rlwinm 0,0,3,0,0; rlwinm 0,0,13,0,0; 83 rlwinm 0,0,29,0,0; rlwinm 0,0,19,0,0) 84 85 64-bit mode: 78001800 78006800 7800E802 78009802 86 (rotldi 0,0,3; rotldi 0,0,13; 87 rotldi 0,0,61; rotldi 0,0,51) 88 89 Following that, one of the following 3 are allowed 90 (standard interpretation in parentheses): 91 92 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 ) 93 7C421378 (or 2,2,2) %R3 = guest_NRADDR 94 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 95 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2 96 97 Any other bytes following the 16-byte preamble are illegal and 98 constitute a failure in instruction decoding. This all assumes 99 that the preamble will never occur except in specific code 100 fragments designed for Valgrind to catch. 101*/ 102 103 104/* Translates PPC32/64 code to IR. */ 105 106/* References 107 108#define PPC32 109 "PowerPC Microprocessor Family: 110 The Programming Environments Manual for 32-Bit Microprocessors" 111 02/21/2000 112 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2 113 114#define PPC64 115 "PowerPC Microprocessor Family: 116 Programming Environments Manual for 64-Bit Microprocessors" 117 06/10/2003 118 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797 119 120#define AV 121 "PowerPC Microprocessor Family: 122 AltiVec(TM) Technology Programming Environments Manual" 123 07/10/2003 124 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D 125*/ 126 127#include "libvex_basictypes.h" 128#include "libvex_ir.h" 129#include "libvex.h" 130#include "libvex_guest_ppc32.h" 131#include "libvex_guest_ppc64.h" 132 133#include "main_util.h" 134#include "main_globals.h" 135#include "guest_generic_bb_to_IR.h" 136#include "guest_ppc_defs.h" 137 138 139/*------------------------------------------------------------*/ 140/*--- Globals ---*/ 141/*------------------------------------------------------------*/ 142 143/* These are set at the start of the translation of an insn, right 144 down in disInstr_PPC, so that we don't have to pass them around 145 endlessly. They are all constant during the translation of any 146 given insn. */ 147 148/* We need to know this to do sub-register accesses correctly. */ 149static Bool host_is_bigendian; 150 151/* Pointer to the guest code area. */ 152static UChar* guest_code; 153 154/* The guest address corresponding to guest_code[0]. */ 155static Addr64 guest_CIA_bbstart; 156 157/* The guest address for the instruction currently being 158 translated. */ 159static Addr64 guest_CIA_curr_instr; 160 161/* The IRSB* into which we're generating code. */ 162static IRSB* irsb; 163 164/* Is our guest binary 32 or 64bit? Set at each call to 165 disInstr_PPC below. */ 166static Bool mode64 = False; 167 168// Given a pointer to a function as obtained by "& functionname" in C, 169// produce a pointer to the actual entry point for the function. For 170// most platforms it's the identity function. Unfortunately, on 171// ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and 172// ppc64-aix5. 173static void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f ) 174{ 175 if (vbi->host_ppc_calls_use_fndescrs) { 176 /* f is a pointer to a 3-word function descriptor, of which the 177 first word is the entry address. */ 178 /* note, this is correct even with cross-jitting, since this is 179 purely a host issue, not a guest one. */ 180 HWord* fdescr = (HWord*)f; 181 return (void*)(fdescr[0]); 182 } else { 183 /* Simple; "& f" points directly at the code for f. */ 184 return f; 185 } 186} 187 188#define SIGN_BIT 0x8000000000000000ULL 189#define SIGN_MASK 0x7fffffffffffffffULL 190#define SIGN_BIT32 0x80000000 191#define SIGN_MASK32 0x7fffffff 192 193 194/*------------------------------------------------------------*/ 195/*--- Debugging output ---*/ 196/*------------------------------------------------------------*/ 197 198#define DIP(format, args...) \ 199 if (vex_traceflags & VEX_TRACE_FE) \ 200 vex_printf(format, ## args) 201 202#define DIS(buf, format, args...) \ 203 if (vex_traceflags & VEX_TRACE_FE) \ 204 vex_sprintf(buf, format, ## args) 205 206 207/*------------------------------------------------------------*/ 208/*--- Offsets of various parts of the ppc32/64 guest state ---*/ 209/*------------------------------------------------------------*/ 210 211#define offsetofPPCGuestState(_x) \ 212 (mode64 ? offsetof(VexGuestPPC64State, _x) : \ 213 offsetof(VexGuestPPC32State, _x)) 214 215#define OFFB_CIA offsetofPPCGuestState(guest_CIA) 216#define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL) 217#define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO) 218#define OFFB_LR offsetofPPCGuestState(guest_LR) 219#define OFFB_CTR offsetofPPCGuestState(guest_CTR) 220#define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO) 221#define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV) 222#define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA) 223#define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC) 224#define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND) 225#define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE) 226#define OFFB_VSCR offsetofPPCGuestState(guest_VSCR) 227#define OFFB_EMWARN offsetofPPCGuestState(guest_EMWARN) 228#define OFFB_TISTART offsetofPPCGuestState(guest_TISTART) 229#define OFFB_TILEN offsetofPPCGuestState(guest_TILEN) 230#define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) 231#define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2) 232 233 234/*------------------------------------------------------------*/ 235/*--- Extract instruction fields --- */ 236/*------------------------------------------------------------*/ 237 238/* Extract field from insn, given idx (zero = lsb) and field length */ 239#define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1)) 240 241/* Extract primary opcode, instr[31:26] */ 242static UChar ifieldOPC( UInt instr ) { 243 return toUChar( IFIELD( instr, 26, 6 ) ); 244} 245 246/* Extract 10-bit secondary opcode, instr[10:1] */ 247static UInt ifieldOPClo10 ( UInt instr) { 248 return IFIELD( instr, 1, 10 ); 249} 250 251/* Extract 9-bit secondary opcode, instr[9:1] */ 252static UInt ifieldOPClo9 ( UInt instr) { 253 return IFIELD( instr, 1, 9 ); 254} 255 256/* Extract 5-bit secondary opcode, instr[5:1] */ 257static UInt ifieldOPClo5 ( UInt instr) { 258 return IFIELD( instr, 1, 5 ); 259} 260 261/* Extract RD (destination register) field, instr[25:21] */ 262static UChar ifieldRegDS( UInt instr ) { 263 return toUChar( IFIELD( instr, 21, 5 ) ); 264} 265 266/* Extract XT (destination register) field, instr[0,25:21] */ 267static UChar ifieldRegXT ( UInt instr ) 268{ 269 UChar upper_bit = toUChar (IFIELD (instr, 0, 1)); 270 UChar lower_bits = toUChar (IFIELD (instr, 21, 5)); 271 return (upper_bit << 5) | lower_bits; 272} 273 274/* Extract XS (store source register) field, instr[0,25:21] */ 275static inline UChar ifieldRegXS ( UInt instr ) 276{ 277 return ifieldRegXT ( instr ); 278} 279 280/* Extract RA (1st source register) field, instr[20:16] */ 281static UChar ifieldRegA ( UInt instr ) { 282 return toUChar( IFIELD( instr, 16, 5 ) ); 283} 284 285/* Extract XA (1st source register) field, instr[2,20:16] */ 286static UChar ifieldRegXA ( UInt instr ) 287{ 288 UChar upper_bit = toUChar (IFIELD (instr, 2, 1)); 289 UChar lower_bits = toUChar (IFIELD (instr, 16, 5)); 290 return (upper_bit << 5) | lower_bits; 291} 292 293/* Extract RB (2nd source register) field, instr[15:11] */ 294static UChar ifieldRegB ( UInt instr ) { 295 return toUChar( IFIELD( instr, 11, 5 ) ); 296} 297 298/* Extract XB (2nd source register) field, instr[1,15:11] */ 299static UChar ifieldRegXB ( UInt instr ) 300{ 301 UChar upper_bit = toUChar (IFIELD (instr, 1, 1)); 302 UChar lower_bits = toUChar (IFIELD (instr, 11, 5)); 303 return (upper_bit << 5) | lower_bits; 304} 305 306/* Extract RC (3rd source register) field, instr[10:6] */ 307static UChar ifieldRegC ( UInt instr ) { 308 return toUChar( IFIELD( instr, 6, 5 ) ); 309} 310 311/* Extract XC (3rd source register) field, instr[3,10:6] */ 312static UChar ifieldRegXC ( UInt instr ) 313{ 314 UChar upper_bit = toUChar (IFIELD (instr, 3, 1)); 315 UChar lower_bits = toUChar (IFIELD (instr, 6, 5)); 316 return (upper_bit << 5) | lower_bits; 317} 318 319/* Extract bit 10, instr[10] */ 320static UChar ifieldBIT10 ( UInt instr ) { 321 return toUChar( IFIELD( instr, 10, 1 ) ); 322} 323 324/* Extract 2nd lowest bit, instr[1] */ 325static UChar ifieldBIT1 ( UInt instr ) { 326 return toUChar( IFIELD( instr, 1, 1 ) ); 327} 328 329/* Extract lowest bit, instr[0] */ 330static UChar ifieldBIT0 ( UInt instr ) { 331 return toUChar( instr & 0x1 ); 332} 333 334/* Extract unsigned bottom half, instr[15:0] */ 335static UInt ifieldUIMM16 ( UInt instr ) { 336 return instr & 0xFFFF; 337} 338 339/* Extract unsigned bottom 26 bits, instr[25:0] */ 340static UInt ifieldUIMM26 ( UInt instr ) { 341 return instr & 0x3FFFFFF; 342} 343 344/* Extract DM field, instr[9:8] */ 345static UChar ifieldDM ( UInt instr ) { 346 return toUChar( IFIELD( instr, 8, 2 ) ); 347} 348 349/* Extract SHW field, instr[9:8] */ 350static inline UChar ifieldSHW ( UInt instr ) 351{ 352 return ifieldDM ( instr ); 353} 354 355/*------------------------------------------------------------*/ 356/*--- Guest-state identifiers ---*/ 357/*------------------------------------------------------------*/ 358 359typedef enum { 360 PPC_GST_CIA, // Current Instruction Address 361 PPC_GST_LR, // Link Register 362 PPC_GST_CTR, // Count Register 363 PPC_GST_XER, // Overflow, carry flags, byte count 364 PPC_GST_CR, // Condition Register 365 PPC_GST_FPSCR, // Floating Point Status/Control Register 366 PPC_GST_VRSAVE, // Vector Save/Restore Register 367 PPC_GST_VSCR, // Vector Status and Control Register 368 PPC_GST_EMWARN, // Emulation warnings 369 PPC_GST_TISTART,// For icbi: start of area to invalidate 370 PPC_GST_TILEN, // For icbi: length of area to invalidate 371 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn 372 PPC_GST_SPRG3_RO, // SPRG3 373 PPC_GST_MAX 374} PPC_GST; 375 376#define MASK_FPSCR_RN 0x3 377#define MASK_FPSCR_FPRF 0x1F000 378#define MASK_VSCR_VALID 0x00010001 379 380 381/*------------------------------------------------------------*/ 382/*--- FP Helpers ---*/ 383/*------------------------------------------------------------*/ 384 385/* Produce the 32-bit pattern corresponding to the supplied 386 float. */ 387static UInt float_to_bits ( Float f ) 388{ 389 union { UInt i; Float f; } u; 390 vassert(4 == sizeof(UInt)); 391 vassert(4 == sizeof(Float)); 392 vassert(4 == sizeof(u)); 393 u.f = f; 394 return u.i; 395} 396 397 398/*------------------------------------------------------------*/ 399/*--- Misc Helpers ---*/ 400/*------------------------------------------------------------*/ 401 402/* Generate mask with 1's from 'begin' through 'end', 403 wrapping if begin > end. 404 begin->end works from right to left, 0=lsb 405*/ 406static UInt MASK32( UInt begin, UInt end ) 407{ 408 UInt m1, m2, mask; 409 vassert(begin < 32); 410 vassert(end < 32); 411 m1 = ((UInt)(-1)) << begin; 412 m2 = ((UInt)(-1)) << end << 1; 413 mask = m1 ^ m2; 414 if (begin > end) mask = ~mask; // wrap mask 415 return mask; 416} 417 418/* ditto for 64bit mask */ 419static ULong MASK64( UInt begin, UInt end ) 420{ 421 ULong m1, m2, mask; 422 vassert(begin < 64); 423 vassert(end < 64); 424 m1 = ((ULong)(-1)) << begin; 425 m2 = ((ULong)(-1)) << end << 1; 426 mask = m1 ^ m2; 427 if (begin > end) mask = ~mask; // wrap mask 428 return mask; 429} 430 431static Addr64 nextInsnAddr( void ) 432{ 433 return guest_CIA_curr_instr + 4; 434} 435 436 437/*------------------------------------------------------------*/ 438/*--- Helper bits and pieces for deconstructing the ---*/ 439/*--- ppc32/64 insn stream. ---*/ 440/*------------------------------------------------------------*/ 441 442/* Add a statement to the list held by "irsb". */ 443static void stmt ( IRStmt* st ) 444{ 445 addStmtToIRSB( irsb, st ); 446} 447 448/* Generate a new temporary of the given type. */ 449static IRTemp newTemp ( IRType ty ) 450{ 451 vassert(isPlausibleIRType(ty)); 452 return newIRTemp( irsb->tyenv, ty ); 453} 454 455/* Various simple conversions */ 456 457static UChar extend_s_5to8 ( UChar x ) 458{ 459 return toUChar((((Int)x) << 27) >> 27); 460} 461 462static UInt extend_s_8to32( UChar x ) 463{ 464 return (UInt)((((Int)x) << 24) >> 24); 465} 466 467static UInt extend_s_16to32 ( UInt x ) 468{ 469 return (UInt)((((Int)x) << 16) >> 16); 470} 471 472static ULong extend_s_16to64 ( UInt x ) 473{ 474 return (ULong)((((Long)x) << 48) >> 48); 475} 476 477static ULong extend_s_26to64 ( UInt x ) 478{ 479 return (ULong)((((Long)x) << 38) >> 38); 480} 481 482static ULong extend_s_32to64 ( UInt x ) 483{ 484 return (ULong)((((Long)x) << 32) >> 32); 485} 486 487/* Do a big-endian load of a 32-bit word, regardless of the endianness 488 of the underlying host. */ 489static UInt getUIntBigendianly ( UChar* p ) 490{ 491 UInt w = 0; 492 w = (w << 8) | p[0]; 493 w = (w << 8) | p[1]; 494 w = (w << 8) | p[2]; 495 w = (w << 8) | p[3]; 496 return w; 497} 498 499 500/*------------------------------------------------------------*/ 501/*--- Helpers for constructing IR. ---*/ 502/*------------------------------------------------------------*/ 503 504static void assign ( IRTemp dst, IRExpr* e ) 505{ 506 stmt( IRStmt_WrTmp(dst, e) ); 507} 508 509/* This generates a normal (non store-conditional) store. */ 510static void storeBE ( IRExpr* addr, IRExpr* data ) 511{ 512 IRType tyA = typeOfIRExpr(irsb->tyenv, addr); 513 vassert(tyA == Ity_I32 || tyA == Ity_I64); 514 stmt( IRStmt_Store(Iend_BE, addr, data) ); 515} 516 517static IRExpr* unop ( IROp op, IRExpr* a ) 518{ 519 return IRExpr_Unop(op, a); 520} 521 522static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 523{ 524 return IRExpr_Binop(op, a1, a2); 525} 526 527static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 528{ 529 return IRExpr_Triop(op, a1, a2, a3); 530} 531 532static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2, 533 IRExpr* a3, IRExpr* a4 ) 534{ 535 return IRExpr_Qop(op, a1, a2, a3, a4); 536} 537 538static IRExpr* mkexpr ( IRTemp tmp ) 539{ 540 return IRExpr_RdTmp(tmp); 541} 542 543static IRExpr* mkU8 ( UChar i ) 544{ 545 return IRExpr_Const(IRConst_U8(i)); 546} 547 548static IRExpr* mkU16 ( UInt i ) 549{ 550 return IRExpr_Const(IRConst_U16(i)); 551} 552 553static IRExpr* mkU32 ( UInt i ) 554{ 555 return IRExpr_Const(IRConst_U32(i)); 556} 557 558static IRExpr* mkU64 ( ULong i ) 559{ 560 return IRExpr_Const(IRConst_U64(i)); 561} 562 563static IRExpr* mkV128 ( UShort i ) 564{ 565 vassert(i == 0 || i == 0xffff); 566 return IRExpr_Const(IRConst_V128(i)); 567} 568 569/* This generates a normal (non load-linked) load. */ 570static IRExpr* loadBE ( IRType ty, IRExpr* addr ) 571{ 572 return IRExpr_Load(Iend_BE, ty, addr); 573} 574 575static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 ) 576{ 577 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 578 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 579 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1), 580 unop(Iop_1Uto32, arg2))); 581} 582 583static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 ) 584{ 585 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 586 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 587 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1), 588 unop(Iop_1Uto32, arg2))); 589} 590 591/* expand V128_8Ux16 to 2x V128_16Ux8's */ 592static void expand8Ux16( IRExpr* vIn, 593 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 594{ 595 IRTemp ones8x16 = newTemp(Ity_V128); 596 597 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 598 vassert(vEvn && *vEvn == IRTemp_INVALID); 599 vassert(vOdd && *vOdd == IRTemp_INVALID); 600 *vEvn = newTemp(Ity_V128); 601 *vOdd = newTemp(Ity_V128); 602 603 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 604 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) ); 605 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 606 binop(Iop_ShrV128, vIn, mkU8(8))) ); 607} 608 609/* expand V128_8Sx16 to 2x V128_16Sx8's */ 610static void expand8Sx16( IRExpr* vIn, 611 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 612{ 613 IRTemp ones8x16 = newTemp(Ity_V128); 614 615 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 616 vassert(vEvn && *vEvn == IRTemp_INVALID); 617 vassert(vOdd && *vOdd == IRTemp_INVALID); 618 *vEvn = newTemp(Ity_V128); 619 *vOdd = newTemp(Ity_V128); 620 621 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 622 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) ); 623 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 624 binop(Iop_ShrV128, vIn, mkU8(8))) ); 625} 626 627/* expand V128_16Uto8 to 2x V128_32Ux4's */ 628static void expand16Ux8( IRExpr* vIn, 629 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 630{ 631 IRTemp ones16x8 = newTemp(Ity_V128); 632 633 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 634 vassert(vEvn && *vEvn == IRTemp_INVALID); 635 vassert(vOdd && *vOdd == IRTemp_INVALID); 636 *vEvn = newTemp(Ity_V128); 637 *vOdd = newTemp(Ity_V128); 638 639 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 640 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) ); 641 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 642 binop(Iop_ShrV128, vIn, mkU8(16))) ); 643} 644 645/* expand V128_16Sto8 to 2x V128_32Sx4's */ 646static void expand16Sx8( IRExpr* vIn, 647 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 648{ 649 IRTemp ones16x8 = newTemp(Ity_V128); 650 651 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 652 vassert(vEvn && *vEvn == IRTemp_INVALID); 653 vassert(vOdd && *vOdd == IRTemp_INVALID); 654 *vEvn = newTemp(Ity_V128); 655 *vOdd = newTemp(Ity_V128); 656 657 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 658 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) ); 659 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 660 binop(Iop_ShrV128, vIn, mkU8(16))) ); 661} 662 663/* break V128 to 4xF64's*/ 664static void breakV128to4xF64( IRExpr* t128, 665 /*OUTs*/ 666 IRTemp* t3, IRTemp* t2, 667 IRTemp* t1, IRTemp* t0 ) 668{ 669 IRTemp hi64 = newTemp(Ity_I64); 670 IRTemp lo64 = newTemp(Ity_I64); 671 672 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 673 vassert(t0 && *t0 == IRTemp_INVALID); 674 vassert(t1 && *t1 == IRTemp_INVALID); 675 vassert(t2 && *t2 == IRTemp_INVALID); 676 vassert(t3 && *t3 == IRTemp_INVALID); 677 *t0 = newTemp(Ity_F64); 678 *t1 = newTemp(Ity_F64); 679 *t2 = newTemp(Ity_F64); 680 *t3 = newTemp(Ity_F64); 681 682 assign( hi64, unop(Iop_V128HIto64, t128) ); 683 assign( lo64, unop(Iop_V128to64, t128) ); 684 assign( *t3, 685 unop( Iop_F32toF64, 686 unop( Iop_ReinterpI32asF32, 687 unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) ); 688 assign( *t2, 689 unop( Iop_F32toF64, 690 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) ); 691 assign( *t1, 692 unop( Iop_F32toF64, 693 unop( Iop_ReinterpI32asF32, 694 unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) ); 695 assign( *t0, 696 unop( Iop_F32toF64, 697 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) ); 698} 699 700 701/* break V128 to 4xI32's, then sign-extend to I64's */ 702static void breakV128to4x64S( IRExpr* t128, 703 /*OUTs*/ 704 IRTemp* t3, IRTemp* t2, 705 IRTemp* t1, IRTemp* t0 ) 706{ 707 IRTemp hi64 = newTemp(Ity_I64); 708 IRTemp lo64 = newTemp(Ity_I64); 709 710 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 711 vassert(t0 && *t0 == IRTemp_INVALID); 712 vassert(t1 && *t1 == IRTemp_INVALID); 713 vassert(t2 && *t2 == IRTemp_INVALID); 714 vassert(t3 && *t3 == IRTemp_INVALID); 715 *t0 = newTemp(Ity_I64); 716 *t1 = newTemp(Ity_I64); 717 *t2 = newTemp(Ity_I64); 718 *t3 = newTemp(Ity_I64); 719 720 assign( hi64, unop(Iop_V128HIto64, t128) ); 721 assign( lo64, unop(Iop_V128to64, t128) ); 722 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 723 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) ); 724 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 725 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) ); 726} 727 728/* break V128 to 4xI32's, then zero-extend to I64's */ 729static void breakV128to4x64U ( IRExpr* t128, 730 /*OUTs*/ 731 IRTemp* t3, IRTemp* t2, 732 IRTemp* t1, IRTemp* t0 ) 733{ 734 IRTemp hi64 = newTemp(Ity_I64); 735 IRTemp lo64 = newTemp(Ity_I64); 736 737 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 738 vassert(t0 && *t0 == IRTemp_INVALID); 739 vassert(t1 && *t1 == IRTemp_INVALID); 740 vassert(t2 && *t2 == IRTemp_INVALID); 741 vassert(t3 && *t3 == IRTemp_INVALID); 742 *t0 = newTemp(Ity_I64); 743 *t1 = newTemp(Ity_I64); 744 *t2 = newTemp(Ity_I64); 745 *t3 = newTemp(Ity_I64); 746 747 assign( hi64, unop(Iop_V128HIto64, t128) ); 748 assign( lo64, unop(Iop_V128to64, t128) ); 749 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 750 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) ); 751 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 752 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) ); 753} 754 755static void breakV128to4x32( IRExpr* t128, 756 /*OUTs*/ 757 IRTemp* t3, IRTemp* t2, 758 IRTemp* t1, IRTemp* t0 ) 759{ 760 IRTemp hi64 = newTemp(Ity_I64); 761 IRTemp lo64 = newTemp(Ity_I64); 762 763 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 764 vassert(t0 && *t0 == IRTemp_INVALID); 765 vassert(t1 && *t1 == IRTemp_INVALID); 766 vassert(t2 && *t2 == IRTemp_INVALID); 767 vassert(t3 && *t3 == IRTemp_INVALID); 768 *t0 = newTemp(Ity_I32); 769 *t1 = newTemp(Ity_I32); 770 *t2 = newTemp(Ity_I32); 771 *t3 = newTemp(Ity_I32); 772 773 assign( hi64, unop(Iop_V128HIto64, t128) ); 774 assign( lo64, unop(Iop_V128to64, t128) ); 775 assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) ); 776 assign( *t2, unop(Iop_64to32, mkexpr(hi64)) ); 777 assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) ); 778 assign( *t0, unop(Iop_64to32, mkexpr(lo64)) ); 779} 780 781 782/* Signed saturating narrow 64S to 32 */ 783static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 ) 784{ 785 IRTemp hi32 = newTemp(Ity_I32); 786 IRTemp lo32 = newTemp(Ity_I32); 787 788 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 789 790 assign( hi32, unop(Iop_64HIto32, t64)); 791 assign( lo32, unop(Iop_64to32, t64)); 792 793 return IRExpr_Mux0X( 794 /* if (hi32 == (lo32 >>s 31)) */ 795 unop(Iop_1Uto8, 796 binop(Iop_CmpEQ32, mkexpr(hi32), 797 binop( Iop_Sar32, mkexpr(lo32), mkU8(31)))), 798 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */ 799 binop(Iop_Add32, mkU32(0x7FFFFFFF), 800 binop(Iop_Shr32, mkexpr(hi32), mkU8(31))), 801 /* then: within signed-32 range: lo half good enough */ 802 mkexpr(lo32) ); 803} 804 805/* Unsigned saturating narrow 64S to 32 */ 806static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 ) 807{ 808 IRTemp hi32 = newTemp(Ity_I32); 809 IRTemp lo32 = newTemp(Ity_I32); 810 811 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 812 813 assign( hi32, unop(Iop_64HIto32, t64)); 814 assign( lo32, unop(Iop_64to32, t64)); 815 816 return IRExpr_Mux0X( 817 /* if (top 32 bits of t64 are 0) */ 818 unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0))), 819 /* else: positive saturate -> 0xFFFFFFFF */ 820 mkU32(0xFFFFFFFF), 821 /* then: within unsigned-32 range: lo half good enough */ 822 mkexpr(lo32) ); 823} 824 825/* Signed saturate narrow 64->32, combining to V128 */ 826static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2, 827 IRExpr* t1, IRExpr* t0 ) 828{ 829 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 830 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 831 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 832 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 833 return binop(Iop_64HLtoV128, 834 binop(Iop_32HLto64, 835 mkQNarrow64Sto32( t3 ), 836 mkQNarrow64Sto32( t2 )), 837 binop(Iop_32HLto64, 838 mkQNarrow64Sto32( t1 ), 839 mkQNarrow64Sto32( t0 ))); 840} 841 842/* Unsigned saturate narrow 64->32, combining to V128 */ 843static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2, 844 IRExpr* t1, IRExpr* t0 ) 845{ 846 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 847 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 848 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 849 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 850 return binop(Iop_64HLtoV128, 851 binop(Iop_32HLto64, 852 mkQNarrow64Uto32( t3 ), 853 mkQNarrow64Uto32( t2 )), 854 binop(Iop_32HLto64, 855 mkQNarrow64Uto32( t1 ), 856 mkQNarrow64Uto32( t0 ))); 857} 858 859/* Simulate irops Iop_MullOdd*, since we don't have them */ 860#define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \ 861 binop(Iop_MullEven8Ux16, \ 862 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 863 binop(Iop_ShrV128, expr_vB, mkU8(8))) 864 865#define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \ 866 binop(Iop_MullEven8Sx16, \ 867 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 868 binop(Iop_ShrV128, expr_vB, mkU8(8))) 869 870#define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \ 871 binop(Iop_MullEven16Ux8, \ 872 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 873 binop(Iop_ShrV128, expr_vB, mkU8(16))) 874 875#define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \ 876 binop(Iop_MullEven16Sx8, \ 877 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 878 binop(Iop_ShrV128, expr_vB, mkU8(16))) 879 880static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src ) 881{ 882 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 883 return unop(Iop_32Sto64, unop(Iop_64to32, src)); 884} 885 886static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src ) 887{ 888 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 889 return unop(Iop_32Uto64, unop(Iop_64to32, src)); 890} 891 892static IROp mkSzOp ( IRType ty, IROp op8 ) 893{ 894 Int adj; 895 vassert(ty == Ity_I8 || ty == Ity_I16 || 896 ty == Ity_I32 || ty == Ity_I64); 897 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || 898 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 || 899 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 || 900 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || 901 op8 == Iop_Not8 ); 902 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3)); 903 return adj + op8; 904} 905 906/* Make sure we get valid 32 and 64bit addresses */ 907static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 908{ 909 vassert(ty == Ity_I32 || ty == Ity_I64); 910 return ( ty == Ity_I64 ? 911 (Addr64)addr : 912 (Addr64)extend_s_32to64( toUInt(addr) ) ); 913} 914 915/* sz, ULong -> IRExpr */ 916static IRExpr* mkSzImm ( IRType ty, ULong imm64 ) 917{ 918 vassert(ty == Ity_I32 || ty == Ity_I64); 919 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64); 920} 921 922/* sz, ULong -> IRConst */ 923static IRConst* mkSzConst ( IRType ty, ULong imm64 ) 924{ 925 vassert(ty == Ity_I32 || ty == Ity_I64); 926 return ( ty == Ity_I64 ? 927 IRConst_U64(imm64) : 928 IRConst_U32((UInt)imm64) ); 929} 930 931/* Sign extend imm16 -> IRExpr* */ 932static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 ) 933{ 934 vassert(ty == Ity_I32 || ty == Ity_I64); 935 return ( ty == Ity_I64 ? 936 mkU64(extend_s_16to64(imm16)) : 937 mkU32(extend_s_16to32(imm16)) ); 938} 939 940/* Sign extend imm32 -> IRExpr* */ 941static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 ) 942{ 943 vassert(ty == Ity_I32 || ty == Ity_I64); 944 return ( ty == Ity_I64 ? 945 mkU64(extend_s_32to64(imm32)) : 946 mkU32(imm32) ); 947} 948 949/* IR narrows I32/I64 -> I8/I16/I32 */ 950static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src ) 951{ 952 vassert(ty == Ity_I32 || ty == Ity_I64); 953 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 954} 955 956static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src ) 957{ 958 vassert(ty == Ity_I32 || ty == Ity_I64); 959 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src); 960} 961 962static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src ) 963{ 964 vassert(ty == Ity_I32 || ty == Ity_I64); 965 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 966} 967 968/* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */ 969static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined ) 970{ 971 IROp op; 972 vassert(ty == Ity_I32 || ty == Ity_I64); 973 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64; 974 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64; 975 return unop(op, src); 976} 977 978static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined ) 979{ 980 IROp op; 981 vassert(ty == Ity_I32 || ty == Ity_I64); 982 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64; 983 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64; 984 return unop(op, src); 985} 986 987static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined ) 988{ 989 vassert(ty == Ity_I32 || ty == Ity_I64); 990 if (ty == Ity_I32) 991 return src; 992 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 993} 994 995 996static Int integerGuestRegOffset ( UInt archreg ) 997{ 998 vassert(archreg < 32); 999 1000 // jrs: probably not necessary; only matters if we reference sub-parts 1001 // of the ppc registers, but that isn't the case 1002 // later: this might affect Altivec though? 1003 vassert(host_is_bigendian); 1004 1005 switch (archreg) { 1006 case 0: return offsetofPPCGuestState(guest_GPR0); 1007 case 1: return offsetofPPCGuestState(guest_GPR1); 1008 case 2: return offsetofPPCGuestState(guest_GPR2); 1009 case 3: return offsetofPPCGuestState(guest_GPR3); 1010 case 4: return offsetofPPCGuestState(guest_GPR4); 1011 case 5: return offsetofPPCGuestState(guest_GPR5); 1012 case 6: return offsetofPPCGuestState(guest_GPR6); 1013 case 7: return offsetofPPCGuestState(guest_GPR7); 1014 case 8: return offsetofPPCGuestState(guest_GPR8); 1015 case 9: return offsetofPPCGuestState(guest_GPR9); 1016 case 10: return offsetofPPCGuestState(guest_GPR10); 1017 case 11: return offsetofPPCGuestState(guest_GPR11); 1018 case 12: return offsetofPPCGuestState(guest_GPR12); 1019 case 13: return offsetofPPCGuestState(guest_GPR13); 1020 case 14: return offsetofPPCGuestState(guest_GPR14); 1021 case 15: return offsetofPPCGuestState(guest_GPR15); 1022 case 16: return offsetofPPCGuestState(guest_GPR16); 1023 case 17: return offsetofPPCGuestState(guest_GPR17); 1024 case 18: return offsetofPPCGuestState(guest_GPR18); 1025 case 19: return offsetofPPCGuestState(guest_GPR19); 1026 case 20: return offsetofPPCGuestState(guest_GPR20); 1027 case 21: return offsetofPPCGuestState(guest_GPR21); 1028 case 22: return offsetofPPCGuestState(guest_GPR22); 1029 case 23: return offsetofPPCGuestState(guest_GPR23); 1030 case 24: return offsetofPPCGuestState(guest_GPR24); 1031 case 25: return offsetofPPCGuestState(guest_GPR25); 1032 case 26: return offsetofPPCGuestState(guest_GPR26); 1033 case 27: return offsetofPPCGuestState(guest_GPR27); 1034 case 28: return offsetofPPCGuestState(guest_GPR28); 1035 case 29: return offsetofPPCGuestState(guest_GPR29); 1036 case 30: return offsetofPPCGuestState(guest_GPR30); 1037 case 31: return offsetofPPCGuestState(guest_GPR31); 1038 default: break; 1039 } 1040 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/ 1041} 1042 1043static IRExpr* getIReg ( UInt archreg ) 1044{ 1045 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1046 vassert(archreg < 32); 1047 return IRExpr_Get( integerGuestRegOffset(archreg), ty ); 1048} 1049 1050/* Ditto, but write to a reg instead. */ 1051static void putIReg ( UInt archreg, IRExpr* e ) 1052{ 1053 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1054 vassert(archreg < 32); 1055 vassert(typeOfIRExpr(irsb->tyenv, e) == ty ); 1056 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) ); 1057} 1058 1059 1060/* Floating point egisters are mapped to VSX registers[0..31]. */ 1061static Int floatGuestRegOffset ( UInt archreg ) 1062{ 1063 vassert(archreg < 32); 1064 1065 switch (archreg) { 1066 case 0: return offsetofPPCGuestState(guest_VSR0); 1067 case 1: return offsetofPPCGuestState(guest_VSR1); 1068 case 2: return offsetofPPCGuestState(guest_VSR2); 1069 case 3: return offsetofPPCGuestState(guest_VSR3); 1070 case 4: return offsetofPPCGuestState(guest_VSR4); 1071 case 5: return offsetofPPCGuestState(guest_VSR5); 1072 case 6: return offsetofPPCGuestState(guest_VSR6); 1073 case 7: return offsetofPPCGuestState(guest_VSR7); 1074 case 8: return offsetofPPCGuestState(guest_VSR8); 1075 case 9: return offsetofPPCGuestState(guest_VSR9); 1076 case 10: return offsetofPPCGuestState(guest_VSR10); 1077 case 11: return offsetofPPCGuestState(guest_VSR11); 1078 case 12: return offsetofPPCGuestState(guest_VSR12); 1079 case 13: return offsetofPPCGuestState(guest_VSR13); 1080 case 14: return offsetofPPCGuestState(guest_VSR14); 1081 case 15: return offsetofPPCGuestState(guest_VSR15); 1082 case 16: return offsetofPPCGuestState(guest_VSR16); 1083 case 17: return offsetofPPCGuestState(guest_VSR17); 1084 case 18: return offsetofPPCGuestState(guest_VSR18); 1085 case 19: return offsetofPPCGuestState(guest_VSR19); 1086 case 20: return offsetofPPCGuestState(guest_VSR20); 1087 case 21: return offsetofPPCGuestState(guest_VSR21); 1088 case 22: return offsetofPPCGuestState(guest_VSR22); 1089 case 23: return offsetofPPCGuestState(guest_VSR23); 1090 case 24: return offsetofPPCGuestState(guest_VSR24); 1091 case 25: return offsetofPPCGuestState(guest_VSR25); 1092 case 26: return offsetofPPCGuestState(guest_VSR26); 1093 case 27: return offsetofPPCGuestState(guest_VSR27); 1094 case 28: return offsetofPPCGuestState(guest_VSR28); 1095 case 29: return offsetofPPCGuestState(guest_VSR29); 1096 case 30: return offsetofPPCGuestState(guest_VSR30); 1097 case 31: return offsetofPPCGuestState(guest_VSR31); 1098 default: break; 1099 } 1100 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/ 1101} 1102 1103static IRExpr* getFReg ( UInt archreg ) 1104{ 1105 vassert(archreg < 32); 1106 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 ); 1107} 1108 1109/* Ditto, but write to a reg instead. */ 1110static void putFReg ( UInt archreg, IRExpr* e ) 1111{ 1112 vassert(archreg < 32); 1113 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1114 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) ); 1115} 1116 1117static Int vsxGuestRegOffset ( UInt archreg ) 1118{ 1119 vassert(archreg < 64); 1120 switch (archreg) { 1121 case 0: return offsetofPPCGuestState(guest_VSR0); 1122 case 1: return offsetofPPCGuestState(guest_VSR1); 1123 case 2: return offsetofPPCGuestState(guest_VSR2); 1124 case 3: return offsetofPPCGuestState(guest_VSR3); 1125 case 4: return offsetofPPCGuestState(guest_VSR4); 1126 case 5: return offsetofPPCGuestState(guest_VSR5); 1127 case 6: return offsetofPPCGuestState(guest_VSR6); 1128 case 7: return offsetofPPCGuestState(guest_VSR7); 1129 case 8: return offsetofPPCGuestState(guest_VSR8); 1130 case 9: return offsetofPPCGuestState(guest_VSR9); 1131 case 10: return offsetofPPCGuestState(guest_VSR10); 1132 case 11: return offsetofPPCGuestState(guest_VSR11); 1133 case 12: return offsetofPPCGuestState(guest_VSR12); 1134 case 13: return offsetofPPCGuestState(guest_VSR13); 1135 case 14: return offsetofPPCGuestState(guest_VSR14); 1136 case 15: return offsetofPPCGuestState(guest_VSR15); 1137 case 16: return offsetofPPCGuestState(guest_VSR16); 1138 case 17: return offsetofPPCGuestState(guest_VSR17); 1139 case 18: return offsetofPPCGuestState(guest_VSR18); 1140 case 19: return offsetofPPCGuestState(guest_VSR19); 1141 case 20: return offsetofPPCGuestState(guest_VSR20); 1142 case 21: return offsetofPPCGuestState(guest_VSR21); 1143 case 22: return offsetofPPCGuestState(guest_VSR22); 1144 case 23: return offsetofPPCGuestState(guest_VSR23); 1145 case 24: return offsetofPPCGuestState(guest_VSR24); 1146 case 25: return offsetofPPCGuestState(guest_VSR25); 1147 case 26: return offsetofPPCGuestState(guest_VSR26); 1148 case 27: return offsetofPPCGuestState(guest_VSR27); 1149 case 28: return offsetofPPCGuestState(guest_VSR28); 1150 case 29: return offsetofPPCGuestState(guest_VSR29); 1151 case 30: return offsetofPPCGuestState(guest_VSR30); 1152 case 31: return offsetofPPCGuestState(guest_VSR31); 1153 case 32: return offsetofPPCGuestState(guest_VSR32); 1154 case 33: return offsetofPPCGuestState(guest_VSR33); 1155 case 34: return offsetofPPCGuestState(guest_VSR34); 1156 case 35: return offsetofPPCGuestState(guest_VSR35); 1157 case 36: return offsetofPPCGuestState(guest_VSR36); 1158 case 37: return offsetofPPCGuestState(guest_VSR37); 1159 case 38: return offsetofPPCGuestState(guest_VSR38); 1160 case 39: return offsetofPPCGuestState(guest_VSR39); 1161 case 40: return offsetofPPCGuestState(guest_VSR40); 1162 case 41: return offsetofPPCGuestState(guest_VSR41); 1163 case 42: return offsetofPPCGuestState(guest_VSR42); 1164 case 43: return offsetofPPCGuestState(guest_VSR43); 1165 case 44: return offsetofPPCGuestState(guest_VSR44); 1166 case 45: return offsetofPPCGuestState(guest_VSR45); 1167 case 46: return offsetofPPCGuestState(guest_VSR46); 1168 case 47: return offsetofPPCGuestState(guest_VSR47); 1169 case 48: return offsetofPPCGuestState(guest_VSR48); 1170 case 49: return offsetofPPCGuestState(guest_VSR49); 1171 case 50: return offsetofPPCGuestState(guest_VSR50); 1172 case 51: return offsetofPPCGuestState(guest_VSR51); 1173 case 52: return offsetofPPCGuestState(guest_VSR52); 1174 case 53: return offsetofPPCGuestState(guest_VSR53); 1175 case 54: return offsetofPPCGuestState(guest_VSR54); 1176 case 55: return offsetofPPCGuestState(guest_VSR55); 1177 case 56: return offsetofPPCGuestState(guest_VSR56); 1178 case 57: return offsetofPPCGuestState(guest_VSR57); 1179 case 58: return offsetofPPCGuestState(guest_VSR58); 1180 case 59: return offsetofPPCGuestState(guest_VSR59); 1181 case 60: return offsetofPPCGuestState(guest_VSR60); 1182 case 61: return offsetofPPCGuestState(guest_VSR61); 1183 case 62: return offsetofPPCGuestState(guest_VSR62); 1184 case 63: return offsetofPPCGuestState(guest_VSR63); 1185 default: break; 1186 } 1187 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/ 1188} 1189 1190/* Vector registers are mapped to VSX registers[32..63]. */ 1191static Int vectorGuestRegOffset ( UInt archreg ) 1192{ 1193 vassert(archreg < 32); 1194 1195 switch (archreg) { 1196 case 0: return offsetofPPCGuestState(guest_VSR32); 1197 case 1: return offsetofPPCGuestState(guest_VSR33); 1198 case 2: return offsetofPPCGuestState(guest_VSR34); 1199 case 3: return offsetofPPCGuestState(guest_VSR35); 1200 case 4: return offsetofPPCGuestState(guest_VSR36); 1201 case 5: return offsetofPPCGuestState(guest_VSR37); 1202 case 6: return offsetofPPCGuestState(guest_VSR38); 1203 case 7: return offsetofPPCGuestState(guest_VSR39); 1204 case 8: return offsetofPPCGuestState(guest_VSR40); 1205 case 9: return offsetofPPCGuestState(guest_VSR41); 1206 case 10: return offsetofPPCGuestState(guest_VSR42); 1207 case 11: return offsetofPPCGuestState(guest_VSR43); 1208 case 12: return offsetofPPCGuestState(guest_VSR44); 1209 case 13: return offsetofPPCGuestState(guest_VSR45); 1210 case 14: return offsetofPPCGuestState(guest_VSR46); 1211 case 15: return offsetofPPCGuestState(guest_VSR47); 1212 case 16: return offsetofPPCGuestState(guest_VSR48); 1213 case 17: return offsetofPPCGuestState(guest_VSR49); 1214 case 18: return offsetofPPCGuestState(guest_VSR50); 1215 case 19: return offsetofPPCGuestState(guest_VSR51); 1216 case 20: return offsetofPPCGuestState(guest_VSR52); 1217 case 21: return offsetofPPCGuestState(guest_VSR53); 1218 case 22: return offsetofPPCGuestState(guest_VSR54); 1219 case 23: return offsetofPPCGuestState(guest_VSR55); 1220 case 24: return offsetofPPCGuestState(guest_VSR56); 1221 case 25: return offsetofPPCGuestState(guest_VSR57); 1222 case 26: return offsetofPPCGuestState(guest_VSR58); 1223 case 27: return offsetofPPCGuestState(guest_VSR59); 1224 case 28: return offsetofPPCGuestState(guest_VSR60); 1225 case 29: return offsetofPPCGuestState(guest_VSR61); 1226 case 30: return offsetofPPCGuestState(guest_VSR62); 1227 case 31: return offsetofPPCGuestState(guest_VSR63); 1228 default: break; 1229 } 1230 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/ 1231} 1232 1233static IRExpr* getVReg ( UInt archreg ) 1234{ 1235 vassert(archreg < 32); 1236 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 ); 1237} 1238 1239/* Ditto, but write to a reg instead. */ 1240static void putVReg ( UInt archreg, IRExpr* e ) 1241{ 1242 vassert(archreg < 32); 1243 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1244 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1245} 1246 1247/* Get contents of VSX guest register */ 1248static IRExpr* getVSReg ( UInt archreg ) 1249{ 1250 vassert(archreg < 64); 1251 return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 ); 1252} 1253 1254/* Ditto, but write to a VSX reg instead. */ 1255static void putVSReg ( UInt archreg, IRExpr* e ) 1256{ 1257 vassert(archreg < 64); 1258 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1259 stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) ); 1260} 1261 1262 1263static Int guestCR321offset ( UInt cr ) 1264{ 1265 switch (cr) { 1266 case 0: return offsetofPPCGuestState(guest_CR0_321 ); 1267 case 1: return offsetofPPCGuestState(guest_CR1_321 ); 1268 case 2: return offsetofPPCGuestState(guest_CR2_321 ); 1269 case 3: return offsetofPPCGuestState(guest_CR3_321 ); 1270 case 4: return offsetofPPCGuestState(guest_CR4_321 ); 1271 case 5: return offsetofPPCGuestState(guest_CR5_321 ); 1272 case 6: return offsetofPPCGuestState(guest_CR6_321 ); 1273 case 7: return offsetofPPCGuestState(guest_CR7_321 ); 1274 default: vpanic("guestCR321offset(ppc)"); 1275 } 1276} 1277 1278static Int guestCR0offset ( UInt cr ) 1279{ 1280 switch (cr) { 1281 case 0: return offsetofPPCGuestState(guest_CR0_0 ); 1282 case 1: return offsetofPPCGuestState(guest_CR1_0 ); 1283 case 2: return offsetofPPCGuestState(guest_CR2_0 ); 1284 case 3: return offsetofPPCGuestState(guest_CR3_0 ); 1285 case 4: return offsetofPPCGuestState(guest_CR4_0 ); 1286 case 5: return offsetofPPCGuestState(guest_CR5_0 ); 1287 case 6: return offsetofPPCGuestState(guest_CR6_0 ); 1288 case 7: return offsetofPPCGuestState(guest_CR7_0 ); 1289 default: vpanic("guestCR3offset(ppc)"); 1290 } 1291} 1292 1293/* Generate an IR sequence to do a popcount operation on the supplied 1294 IRTemp, and return a new IRTemp holding the result. 'ty' may be 1295 Ity_I32 or Ity_I64 only. */ 1296static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src ) 1297{ 1298 Int i, shift[6]; 1299 IRTemp mask[6]; 1300 IRTemp old = IRTemp_INVALID; 1301 IRTemp nyu = IRTemp_INVALID; 1302 1303 vassert(ty == Ity_I64 || ty == Ity_I32); 1304 1305 if (ty == Ity_I32) { 1306 for (i = 0; i < 5; i++) { 1307 mask[i] = newTemp(ty); 1308 shift[i] = 1 << i; 1309 } 1310 assign(mask[0], mkU32(0x55555555)); 1311 assign(mask[1], mkU32(0x33333333)); 1312 assign(mask[2], mkU32(0x0F0F0F0F)); 1313 assign(mask[3], mkU32(0x00FF00FF)); 1314 assign(mask[4], mkU32(0x0000FFFF)); 1315 old = src; 1316 for (i = 0; i < 5; i++) { 1317 nyu = newTemp(ty); 1318 assign(nyu, 1319 binop(Iop_Add32, 1320 binop(Iop_And32, 1321 mkexpr(old), 1322 mkexpr(mask[i])), 1323 binop(Iop_And32, 1324 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1325 mkexpr(mask[i])))); 1326 old = nyu; 1327 } 1328 return nyu; 1329 } 1330// else, ty == Ity_I64 1331 for (i = 0; i < 6; i++) { 1332 mask[i] = newTemp( Ity_I64 ); 1333 shift[i] = 1 << i; 1334 } 1335 assign( mask[0], mkU64( 0x5555555555555555ULL ) ); 1336 assign( mask[1], mkU64( 0x3333333333333333ULL ) ); 1337 assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) ); 1338 assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) ); 1339 assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) ); 1340 assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) ); 1341 old = src; 1342 for (i = 0; i < 6; i++) { 1343 nyu = newTemp( Ity_I64 ); 1344 assign( nyu, 1345 binop( Iop_Add64, 1346 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ), 1347 binop( Iop_And64, 1348 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ), 1349 mkexpr( mask[i] ) ) ) ); 1350 old = nyu; 1351 } 1352 return nyu; 1353} 1354 1355 1356// ROTL(src32/64, rot_amt5/6) 1357static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src, 1358 IRExpr* rot_amt ) 1359{ 1360 IRExpr *mask, *rot; 1361 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8); 1362 1363 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) { 1364 // rot = (src << rot_amt) | (src >> (64-rot_amt)) 1365 mask = binop(Iop_And8, rot_amt, mkU8(63)); 1366 rot = binop(Iop_Or64, 1367 binop(Iop_Shl64, src, mask), 1368 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask))); 1369 } else { 1370 // rot = (src << rot_amt) | (src >> (32-rot_amt)) 1371 mask = binop(Iop_And8, rot_amt, mkU8(31)); 1372 rot = binop(Iop_Or32, 1373 binop(Iop_Shl32, src, mask), 1374 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask))); 1375 } 1376 /* Note: the MuxOX is not merely an optimisation; it's needed 1377 because otherwise the Shr is a shift by the word size when 1378 mask denotes zero. For rotates by immediates, a lot of 1379 this junk gets folded out. */ 1380 return IRExpr_Mux0X( mask, /* zero rotate */ src, 1381 /* non-zero rotate */ rot ); 1382} 1383 1384/* Standard effective address calc: (rA + rB) */ 1385static IRExpr* ea_rA_idxd ( UInt rA, UInt rB ) 1386{ 1387 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1388 vassert(rA < 32); 1389 vassert(rB < 32); 1390 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB)); 1391} 1392 1393/* Standard effective address calc: (rA + simm) */ 1394static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 ) 1395{ 1396 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1397 vassert(rA < 32); 1398 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), 1399 mkSzExtendS16(ty, simm16)); 1400} 1401 1402/* Standard effective address calc: (rA|0) */ 1403static IRExpr* ea_rAor0 ( UInt rA ) 1404{ 1405 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1406 vassert(rA < 32); 1407 if (rA == 0) { 1408 return mkSzImm(ty, 0); 1409 } else { 1410 return getIReg(rA); 1411 } 1412} 1413 1414/* Standard effective address calc: (rA|0) + rB */ 1415static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB ) 1416{ 1417 vassert(rA < 32); 1418 vassert(rB < 32); 1419 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB ); 1420} 1421 1422/* Standard effective address calc: (rA|0) + simm16 */ 1423static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 ) 1424{ 1425 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1426 vassert(rA < 32); 1427 if (rA == 0) { 1428 return mkSzExtendS16(ty, simm16); 1429 } else { 1430 return ea_rA_simm( rA, simm16 ); 1431 } 1432} 1433 1434 1435/* Align effective address */ 1436static IRExpr* addr_align( IRExpr* addr, UChar align ) 1437{ 1438 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1439 Long mask; 1440 switch (align) { 1441 case 1: return addr; // byte aligned 1442 case 2: mask = ((Long)-1) << 1; break; // half-word aligned 1443 case 4: mask = ((Long)-1) << 2; break; // word aligned 1444 case 16: mask = ((Long)-1) << 4; break; // quad-word aligned 1445 default: 1446 vex_printf("addr_align: align = %u\n", align); 1447 vpanic("addr_align(ppc)"); 1448 } 1449 1450 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty); 1451 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) ); 1452} 1453 1454 1455/* Exit the trace if ADDR (intended to be a guest memory address) is 1456 not ALIGN-aligned, generating a request for a SIGBUS followed by a 1457 restart of the current insn. */ 1458static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align ) 1459{ 1460 vassert(align == 4 || align == 8); 1461 if (mode64) { 1462 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64); 1463 stmt( 1464 IRStmt_Exit( 1465 binop(Iop_CmpNE64, 1466 binop(Iop_And64, mkexpr(addr), mkU64(align-1)), 1467 mkU64(0)), 1468 Ijk_SigBUS, 1469 IRConst_U64( guest_CIA_curr_instr ) 1470 ) 1471 ); 1472 } else { 1473 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32); 1474 stmt( 1475 IRStmt_Exit( 1476 binop(Iop_CmpNE32, 1477 binop(Iop_And32, mkexpr(addr), mkU32(align-1)), 1478 mkU32(0)), 1479 Ijk_SigBUS, 1480 IRConst_U32( guest_CIA_curr_instr ) 1481 ) 1482 ); 1483 } 1484} 1485 1486 1487/* Generate AbiHints which mark points at which the ELF or PowerOpen 1488 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some 1489 N) becomes undefined. That is at function calls and returns. ELF 1490 ppc32 doesn't have this "feature" (how fortunate for it). nia is 1491 the address of the next instruction to be executed. 1492*/ 1493static void make_redzone_AbiHint ( VexAbiInfo* vbi, 1494 IRTemp nia, HChar* who ) 1495{ 1496 Int szB = vbi->guest_stack_redzone_size; 1497 if (0) vex_printf("AbiHint: %s\n", who); 1498 vassert(szB >= 0); 1499 if (szB > 0) { 1500 if (mode64) { 1501 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64); 1502 stmt( IRStmt_AbiHint( 1503 binop(Iop_Sub64, getIReg(1), mkU64(szB)), 1504 szB, 1505 mkexpr(nia) 1506 )); 1507 } else { 1508 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32); 1509 stmt( IRStmt_AbiHint( 1510 binop(Iop_Sub32, getIReg(1), mkU32(szB)), 1511 szB, 1512 mkexpr(nia) 1513 )); 1514 } 1515 } 1516} 1517 1518 1519/*------------------------------------------------------------*/ 1520/*--- Helpers for condition codes. ---*/ 1521/*------------------------------------------------------------*/ 1522 1523/* Condition register layout. 1524 1525 In the hardware, CR is laid out like this. The leftmost end is the 1526 most significant bit in the register; however the IBM documentation 1527 numbers the bits backwards for some reason. 1528 1529 CR0 CR1 .......... CR6 CR7 1530 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 1531 31 28 3 0 (normal bit numbering) 1532 1533 Each CR field is 4 bits: [<,>,==,SO] 1534 1535 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. 1536 1537 Indexing from BI to guest state: 1538 1539 let n = BI / 4 1540 off = BI % 4 1541 this references CR n: 1542 1543 off==0 -> guest_CRn_321 >> 3 1544 off==1 -> guest_CRn_321 >> 2 1545 off==2 -> guest_CRn_321 >> 1 1546 off==3 -> guest_CRn_SO 1547 1548 Bear in mind the only significant bit in guest_CRn_SO is bit 0 1549 (normal notation) and in guest_CRn_321 the significant bits are 1550 3, 2 and 1 (normal notation). 1551*/ 1552 1553static void putCR321 ( UInt cr, IRExpr* e ) 1554{ 1555 vassert(cr < 8); 1556 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1557 stmt( IRStmt_Put(guestCR321offset(cr), e) ); 1558} 1559 1560static void putCR0 ( UInt cr, IRExpr* e ) 1561{ 1562 vassert(cr < 8); 1563 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1564 stmt( IRStmt_Put(guestCR0offset(cr), e) ); 1565} 1566 1567static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) 1568{ 1569 vassert(cr < 8); 1570 return IRExpr_Get(guestCR0offset(cr), Ity_I8); 1571} 1572 1573static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) 1574{ 1575 vassert(cr < 8); 1576 return IRExpr_Get(guestCR321offset(cr), Ity_I8); 1577} 1578 1579/* Fetch the specified CR bit (as per IBM/hardware notation) and 1580 return it at the bottom of an I32; the top 31 bits are guaranteed 1581 to be zero. */ 1582static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi ) 1583{ 1584 UInt n = bi / 4; 1585 UInt off = bi % 4; 1586 vassert(bi < 32); 1587 if (off == 3) { 1588 /* Fetch the SO bit for this CR field */ 1589 /* Note: And32 is redundant paranoia iff guest state only has 0 1590 or 1 in that slot. */ 1591 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1592 } else { 1593 /* Fetch the <, > or == bit for this CR field */ 1594 return binop( Iop_And32, 1595 binop( Iop_Shr32, 1596 unop(Iop_8Uto32, getCR321(n)), 1597 mkU8(toUChar(3-off)) ), 1598 mkU32(1) ); 1599 } 1600} 1601 1602/* Dually, write the least significant bit of BIT to the specified CR 1603 bit. Indexing as per getCRbit. */ 1604static void putCRbit ( UInt bi, IRExpr* bit ) 1605{ 1606 UInt n, off; 1607 IRExpr* safe; 1608 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32); 1609 safe = binop(Iop_And32, bit, mkU32(1)); 1610 n = bi / 4; 1611 off = bi % 4; 1612 vassert(bi < 32); 1613 if (off == 3) { 1614 /* This is the SO bit for this CR field */ 1615 putCR0(n, unop(Iop_32to8, safe)); 1616 } else { 1617 off = 3 - off; 1618 vassert(off == 1 || off == 2 || off == 3); 1619 putCR321( 1620 n, 1621 unop( Iop_32to8, 1622 binop( Iop_Or32, 1623 /* old value with field masked out */ 1624 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)), 1625 mkU32(~(1 << off))), 1626 /* new value in the right place */ 1627 binop(Iop_Shl32, safe, mkU8(toUChar(off))) 1628 ) 1629 ) 1630 ); 1631 } 1632} 1633 1634/* Fetch the specified CR bit (as per IBM/hardware notation) and 1635 return it somewhere in an I32; it does not matter where, but 1636 whichever bit it is, all other bits are guaranteed to be zero. In 1637 other words, the I32-typed expression will be zero if the bit is 1638 zero and nonzero if the bit is 1. Write into *where the index 1639 of where the bit will be. */ 1640 1641static 1642IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ) 1643{ 1644 UInt n = bi / 4; 1645 UInt off = bi % 4; 1646 vassert(bi < 32); 1647 if (off == 3) { 1648 /* Fetch the SO bit for this CR field */ 1649 /* Note: And32 is redundant paranoia iff guest state only has 0 1650 or 1 in that slot. */ 1651 *where = 0; 1652 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1653 } else { 1654 /* Fetch the <, > or == bit for this CR field */ 1655 *where = 3-off; 1656 return binop( Iop_And32, 1657 unop(Iop_8Uto32, getCR321(n)), 1658 mkU32(1 << (3-off)) ); 1659 } 1660} 1661 1662/* Set the CR0 flags following an arithmetic operation. 1663 (Condition Register CR0 Field Definition, PPC32 p60) 1664*/ 1665static IRExpr* getXER_SO ( void ); 1666static void set_CR0 ( IRExpr* result ) 1667{ 1668 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 || 1669 typeOfIRExpr(irsb->tyenv,result) == Ity_I64); 1670 if (mode64) { 1671 putCR321( 0, unop(Iop_64to8, 1672 binop(Iop_CmpORD64S, result, mkU64(0))) ); 1673 } else { 1674 putCR321( 0, unop(Iop_32to8, 1675 binop(Iop_CmpORD32S, result, mkU32(0))) ); 1676 } 1677 putCR0( 0, getXER_SO() ); 1678} 1679 1680 1681/* Set the CR6 flags following an AltiVec compare operation. 1682 * NOTE: This also works for VSX single-precision compares. 1683 * */ 1684static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) 1685{ 1686 /* CR6[0:3] = {all_ones, 0, all_zeros, 0} 1687 all_ones = (v[0] && v[1] && v[2] && v[3]) 1688 all_zeros = ~(v[0] || v[1] || v[2] || v[3]) 1689 */ 1690 IRTemp v0 = newTemp(Ity_V128); 1691 IRTemp v1 = newTemp(Ity_V128); 1692 IRTemp v2 = newTemp(Ity_V128); 1693 IRTemp v3 = newTemp(Ity_V128); 1694 IRTemp rOnes = newTemp(Ity_I8); 1695 IRTemp rZeros = newTemp(Ity_I8); 1696 1697 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128); 1698 1699 assign( v0, result ); 1700 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); 1701 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); 1702 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); 1703 1704 assign( rZeros, unop(Iop_1Uto8, 1705 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1706 unop(Iop_Not32, 1707 unop(Iop_V128to32, 1708 binop(Iop_OrV128, 1709 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), 1710 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) 1711 ))) ); 1712 1713 if (test_all_ones) { 1714 assign( rOnes, unop(Iop_1Uto8, 1715 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1716 unop(Iop_V128to32, 1717 binop(Iop_AndV128, 1718 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), 1719 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))) 1720 ))) ); 1721 putCR321( 6, binop(Iop_Or8, 1722 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), 1723 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); 1724 } else { 1725 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); 1726 } 1727 putCR0( 6, mkU8(0) ); 1728} 1729 1730 1731 1732/*------------------------------------------------------------*/ 1733/*--- Helpers for XER flags. ---*/ 1734/*------------------------------------------------------------*/ 1735 1736static void putXER_SO ( IRExpr* e ) 1737{ 1738 IRExpr* so; 1739 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1740 so = binop(Iop_And8, e, mkU8(1)); 1741 stmt( IRStmt_Put( OFFB_XER_SO, so ) ); 1742} 1743 1744static void putXER_OV ( IRExpr* e ) 1745{ 1746 IRExpr* ov; 1747 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1748 ov = binop(Iop_And8, e, mkU8(1)); 1749 stmt( IRStmt_Put( OFFB_XER_OV, ov ) ); 1750} 1751 1752static void putXER_CA ( IRExpr* e ) 1753{ 1754 IRExpr* ca; 1755 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1756 ca = binop(Iop_And8, e, mkU8(1)); 1757 stmt( IRStmt_Put( OFFB_XER_CA, ca ) ); 1758} 1759 1760static void putXER_BC ( IRExpr* e ) 1761{ 1762 IRExpr* bc; 1763 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1764 bc = binop(Iop_And8, e, mkU8(0x7F)); 1765 stmt( IRStmt_Put( OFFB_XER_BC, bc ) ); 1766} 1767 1768static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) 1769{ 1770 return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); 1771} 1772 1773static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void ) 1774{ 1775 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) ); 1776} 1777 1778static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ) 1779{ 1780 return IRExpr_Get( OFFB_XER_OV, Ity_I8 ); 1781} 1782 1783static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void ) 1784{ 1785 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) ); 1786} 1787 1788static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void ) 1789{ 1790 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 ); 1791 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 1792} 1793 1794static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ) 1795{ 1796 return IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 1797} 1798 1799static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void ) 1800{ 1801 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 1802 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) ); 1803} 1804 1805 1806/* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and 1807 %XER.SO accordingly. */ 1808 1809static void set_XER_OV_32( UInt op, IRExpr* res, 1810 IRExpr* argL, IRExpr* argR ) 1811{ 1812 IRTemp t64; 1813 IRExpr* xer_ov; 1814 vassert(op < PPCG_FLAG_OP_NUMBER); 1815 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 1816 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 1817 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 1818 1819# define INT32_MIN 0x80000000 1820 1821# define XOR2(_aa,_bb) \ 1822 binop(Iop_Xor32,(_aa),(_bb)) 1823 1824# define XOR3(_cc,_dd,_ee) \ 1825 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee)) 1826 1827# define AND3(_ff,_gg,_hh) \ 1828 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh)) 1829 1830#define NOT(_jj) \ 1831 unop(Iop_Not32, (_jj)) 1832 1833 switch (op) { 1834 case /* 0 */ PPCG_FLAG_OP_ADD: 1835 case /* 1 */ PPCG_FLAG_OP_ADDE: 1836 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */ 1837 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 1838 xer_ov 1839 = AND3( XOR3(argL,argR,mkU32(-1)), 1840 XOR2(argL,res), 1841 mkU32(INT32_MIN) ); 1842 /* xer_ov can only be 0 or 1<<31 */ 1843 xer_ov 1844 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 1845 break; 1846 1847 case /* 2 */ PPCG_FLAG_OP_DIVW: 1848 /* (argL == INT32_MIN && argR == -1) || argR == 0 */ 1849 xer_ov 1850 = mkOR1( 1851 mkAND1( 1852 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)), 1853 binop(Iop_CmpEQ32, argR, mkU32(-1)) 1854 ), 1855 binop(Iop_CmpEQ32, argR, mkU32(0) ) 1856 ); 1857 xer_ov 1858 = unop(Iop_1Uto32, xer_ov); 1859 break; 1860 1861 case /* 3 */ PPCG_FLAG_OP_DIVWU: 1862 /* argR == 0 */ 1863 xer_ov 1864 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); 1865 break; 1866 1867 case /* 4 */ PPCG_FLAG_OP_MULLW: 1868 /* OV true if result can't be represented in 32 bits 1869 i.e sHi != sign extension of sLo */ 1870 t64 = newTemp(Ity_I64); 1871 assign( t64, binop(Iop_MullS32, argL, argR) ); 1872 xer_ov 1873 = binop( Iop_CmpNE32, 1874 unop(Iop_64HIto32, mkexpr(t64)), 1875 binop( Iop_Sar32, 1876 unop(Iop_64to32, mkexpr(t64)), 1877 mkU8(31)) 1878 ); 1879 xer_ov 1880 = unop(Iop_1Uto32, xer_ov); 1881 break; 1882 1883 case /* 5 */ PPCG_FLAG_OP_NEG: 1884 /* argL == INT32_MIN */ 1885 xer_ov 1886 = unop( Iop_1Uto32, 1887 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); 1888 break; 1889 1890 case /* 6 */ PPCG_FLAG_OP_SUBF: 1891 case /* 7 */ PPCG_FLAG_OP_SUBFC: 1892 case /* 8 */ PPCG_FLAG_OP_SUBFE: 1893 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */ 1894 xer_ov 1895 = AND3( XOR3(NOT(argL),argR,mkU32(-1)), 1896 XOR2(NOT(argL),res), 1897 mkU32(INT32_MIN) ); 1898 /* xer_ov can only be 0 or 1<<31 */ 1899 xer_ov 1900 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 1901 break; 1902 1903 case PPCG_FLAG_OP_DIVWEU: 1904 xer_ov 1905 = binop( Iop_Or32, 1906 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 1907 unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) ); 1908 break; 1909 1910 case PPCG_FLAG_OP_DIVWE: 1911 1912 /* If argR == 0 of if the result cannot fit in the 32-bit destination register, 1913 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero, 1914 * an overflow is implied. 1915 */ 1916 xer_ov = binop( Iop_Or32, 1917 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 1918 unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ), 1919 mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ), 1920 binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) ); 1921 break; 1922 1923 1924 1925 default: 1926 vex_printf("set_XER_OV: op = %u\n", op); 1927 vpanic("set_XER_OV(ppc)"); 1928 } 1929 1930 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 1931 putXER_OV( unop(Iop_32to8, xer_ov) ); 1932 1933 /* Update the summary overflow */ 1934 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 1935 1936# undef INT32_MIN 1937# undef AND3 1938# undef XOR3 1939# undef XOR2 1940# undef NOT 1941} 1942 1943static void set_XER_OV_64( UInt op, IRExpr* res, 1944 IRExpr* argL, IRExpr* argR ) 1945{ 1946 IRExpr* xer_ov; 1947 vassert(op < PPCG_FLAG_OP_NUMBER); 1948 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 1949 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 1950 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 1951 1952# define INT64_MIN 0x8000000000000000ULL 1953 1954# define XOR2(_aa,_bb) \ 1955 binop(Iop_Xor64,(_aa),(_bb)) 1956 1957# define XOR3(_cc,_dd,_ee) \ 1958 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee)) 1959 1960# define AND3(_ff,_gg,_hh) \ 1961 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh)) 1962 1963#define NOT(_jj) \ 1964 unop(Iop_Not64, (_jj)) 1965 1966 switch (op) { 1967 case /* 0 */ PPCG_FLAG_OP_ADD: 1968 case /* 1 */ PPCG_FLAG_OP_ADDE: 1969 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */ 1970 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 1971 xer_ov 1972 = AND3( XOR3(argL,argR,mkU64(-1)), 1973 XOR2(argL,res), 1974 mkU64(INT64_MIN) ); 1975 /* xer_ov can only be 0 or 1<<63 */ 1976 xer_ov 1977 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 1978 break; 1979 1980 case /* 2 */ PPCG_FLAG_OP_DIVW: 1981 /* (argL == INT64_MIN && argR == -1) || argR == 0 */ 1982 xer_ov 1983 = mkOR1( 1984 mkAND1( 1985 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)), 1986 binop(Iop_CmpEQ64, argR, mkU64(-1)) 1987 ), 1988 binop(Iop_CmpEQ64, argR, mkU64(0) ) 1989 ); 1990 break; 1991 1992 case /* 3 */ PPCG_FLAG_OP_DIVWU: 1993 /* argR == 0 */ 1994 xer_ov 1995 = binop(Iop_CmpEQ64, argR, mkU64(0)); 1996 break; 1997 1998 case /* 4 */ PPCG_FLAG_OP_MULLW: { 1999 /* OV true if result can't be represented in 64 bits 2000 i.e sHi != sign extension of sLo */ 2001 xer_ov 2002 = binop( Iop_CmpNE32, 2003 unop(Iop_64HIto32, res), 2004 binop( Iop_Sar32, 2005 unop(Iop_64to32, res), 2006 mkU8(31)) 2007 ); 2008 break; 2009 } 2010 2011 case /* 5 */ PPCG_FLAG_OP_NEG: 2012 /* argL == INT64_MIN */ 2013 xer_ov 2014 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)); 2015 break; 2016 2017 case /* 6 */ PPCG_FLAG_OP_SUBF: 2018 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2019 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2020 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */ 2021 xer_ov 2022 = AND3( XOR3(NOT(argL),argR,mkU64(-1)), 2023 XOR2(NOT(argL),res), 2024 mkU64(INT64_MIN) ); 2025 /* xer_ov can only be 0 or 1<<63 */ 2026 xer_ov 2027 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2028 break; 2029 2030 case PPCG_FLAG_OP_DIVDE: 2031 2032 /* If argR == 0, we must set the OV bit. But there's another condition 2033 * where we can get overflow set for divde . . . when the 2034 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND 2035 * both dividend and divisor are non-zero, it implies an overflow. 2036 */ 2037 xer_ov 2038 = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2039 mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ), 2040 mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ), 2041 binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) ); 2042 break; 2043 2044 case PPCG_FLAG_OP_DIVDEU: 2045 /* If argR == 0 or if argL >= argR, set OV. */ 2046 xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2047 binop( Iop_CmpLE64U, argR, argL ) ); 2048 break; 2049 2050 default: 2051 vex_printf("set_XER_OV: op = %u\n", op); 2052 vpanic("set_XER_OV(ppc64)"); 2053 } 2054 2055 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2056 putXER_OV( unop(Iop_1Uto8, xer_ov) ); 2057 2058 /* Update the summary overflow */ 2059 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2060 2061# undef INT64_MIN 2062# undef AND3 2063# undef XOR3 2064# undef XOR2 2065# undef NOT 2066} 2067 2068static void set_XER_OV ( IRType ty, UInt op, IRExpr* res, 2069 IRExpr* argL, IRExpr* argR ) 2070{ 2071 if (ty == Ity_I32) 2072 set_XER_OV_32( op, res, argL, argR ); 2073 else 2074 set_XER_OV_64( op, res, argL, argR ); 2075} 2076 2077 2078 2079/* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA 2080 value being OLDCA. Set %XER.CA accordingly. */ 2081 2082static void set_XER_CA_32 ( UInt op, IRExpr* res, 2083 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2084{ 2085 IRExpr* xer_ca; 2086 vassert(op < PPCG_FLAG_OP_NUMBER); 2087 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2088 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2089 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2090 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32); 2091 2092 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2093 seems reasonable given that it's always generated by 2094 getXER_CA32(), which masks it accordingly. In any case it being 2095 0 or 1 is an invariant of the ppc guest state representation; 2096 if it has any other value, that invariant has been violated. */ 2097 2098 switch (op) { 2099 case /* 0 */ PPCG_FLAG_OP_ADD: 2100 /* res <u argL */ 2101 xer_ca 2102 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); 2103 break; 2104 2105 case /* 1 */ PPCG_FLAG_OP_ADDE: 2106 /* res <u argL || (old_ca==1 && res==argL) */ 2107 xer_ca 2108 = mkOR1( 2109 binop(Iop_CmpLT32U, res, argL), 2110 mkAND1( 2111 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2112 binop(Iop_CmpEQ32, res, argL) 2113 ) 2114 ); 2115 xer_ca 2116 = unop(Iop_1Uto32, xer_ca); 2117 break; 2118 2119 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2120 /* res <u argR || (old_ca==1 && res==argR) */ 2121 xer_ca 2122 = mkOR1( 2123 binop(Iop_CmpLT32U, res, argR), 2124 mkAND1( 2125 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2126 binop(Iop_CmpEQ32, res, argR) 2127 ) 2128 ); 2129 xer_ca 2130 = unop(Iop_1Uto32, xer_ca); 2131 break; 2132 2133 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2134 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2135 /* res <=u argR */ 2136 xer_ca 2137 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); 2138 break; 2139 2140 case /* 10 */ PPCG_FLAG_OP_SRAW: 2141 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2142 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2143 bit of argL. */ 2144 /* This term valid for shift amount < 32 only */ 2145 xer_ca 2146 = binop( 2147 Iop_And32, 2148 binop(Iop_Sar32, argL, mkU8(31)), 2149 binop( Iop_And32, 2150 argL, 2151 binop( Iop_Sub32, 2152 binop(Iop_Shl32, mkU32(1), 2153 unop(Iop_32to8,argR)), 2154 mkU32(1) ) 2155 ) 2156 ); 2157 xer_ca 2158 = IRExpr_Mux0X( 2159 /* shift amt > 31 ? */ 2160 unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)), 2161 /* no -- be like srawi */ 2162 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))), 2163 /* yes -- get sign bit of argL */ 2164 binop(Iop_Shr32, argL, mkU8(31)) 2165 ); 2166 break; 2167 2168 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2169 /* xer_ca is 1 iff src was negative and bits_shifted_out != 2170 0. Since the shift amount is known to be in the range 2171 0 .. 31 inclusive the following seems viable: 2172 xer.ca == 1 iff the following is nonzero: 2173 (argL >>s 31) -- either all 0s or all 1s 2174 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2175 xer_ca 2176 = binop( 2177 Iop_And32, 2178 binop(Iop_Sar32, argL, mkU8(31)), 2179 binop( Iop_And32, 2180 argL, 2181 binop( Iop_Sub32, 2182 binop(Iop_Shl32, mkU32(1), 2183 unop(Iop_32to8,argR)), 2184 mkU32(1) ) 2185 ) 2186 ); 2187 xer_ca 2188 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); 2189 break; 2190 2191 default: 2192 vex_printf("set_XER_CA: op = %u\n", op); 2193 vpanic("set_XER_CA(ppc)"); 2194 } 2195 2196 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2197 putXER_CA( unop(Iop_32to8, xer_ca) ); 2198} 2199 2200static void set_XER_CA_64 ( UInt op, IRExpr* res, 2201 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2202{ 2203 IRExpr* xer_ca; 2204 vassert(op < PPCG_FLAG_OP_NUMBER); 2205 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2206 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2207 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2208 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64); 2209 2210 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2211 seems reasonable given that it's always generated by 2212 getXER_CA32(), which masks it accordingly. In any case it being 2213 0 or 1 is an invariant of the ppc guest state representation; 2214 if it has any other value, that invariant has been violated. */ 2215 2216 switch (op) { 2217 case /* 0 */ PPCG_FLAG_OP_ADD: 2218 /* res <u argL */ 2219 xer_ca 2220 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL)); 2221 break; 2222 2223 case /* 1 */ PPCG_FLAG_OP_ADDE: 2224 /* res <u argL || (old_ca==1 && res==argL) */ 2225 xer_ca 2226 = mkOR1( 2227 binop(Iop_CmpLT64U, res, argL), 2228 mkAND1( 2229 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2230 binop(Iop_CmpEQ64, res, argL) 2231 ) 2232 ); 2233 xer_ca 2234 = unop(Iop_1Uto32, xer_ca); 2235 break; 2236 2237 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2238 /* res <u argR || (old_ca==1 && res==argR) */ 2239 xer_ca 2240 = mkOR1( 2241 binop(Iop_CmpLT64U, res, argR), 2242 mkAND1( 2243 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2244 binop(Iop_CmpEQ64, res, argR) 2245 ) 2246 ); 2247 xer_ca 2248 = unop(Iop_1Uto32, xer_ca); 2249 break; 2250 2251 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2252 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2253 /* res <=u argR */ 2254 xer_ca 2255 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR)); 2256 break; 2257 2258 2259 case /* 10 */ PPCG_FLAG_OP_SRAW: 2260 /* The shift amount is guaranteed to be in 0 .. 31 inclusive. 2261 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2262 bit of argL. */ 2263 /* This term valid for shift amount < 31 only */ 2264 2265 xer_ca 2266 = binop( 2267 Iop_And64, 2268 binop(Iop_Sar64, argL, mkU8(31)), 2269 binop( Iop_And64, 2270 argL, 2271 binop( Iop_Sub64, 2272 binop(Iop_Shl64, mkU64(1), 2273 unop(Iop_64to8,argR)), 2274 mkU64(1) ) 2275 ) 2276 ); 2277 xer_ca 2278 = IRExpr_Mux0X( 2279 /* shift amt > 31 ? */ 2280 unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(31), argR)), 2281 /* no -- be like srawi */ 2282 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))), 2283 /* yes -- get sign bit of argL */ 2284 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))) 2285 ); 2286 break; 2287 2288 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2289 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2290 Since the shift amount is known to be in the range 0 .. 31 2291 inclusive the following seems viable: 2292 xer.ca == 1 iff the following is nonzero: 2293 (argL >>s 31) -- either all 0s or all 1s 2294 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2295 2296 xer_ca 2297 = binop( 2298 Iop_And64, 2299 binop(Iop_Sar64, argL, mkU8(31)), 2300 binop( Iop_And64, 2301 argL, 2302 binop( Iop_Sub64, 2303 binop(Iop_Shl64, mkU64(1), 2304 unop(Iop_64to8,argR)), 2305 mkU64(1) ) 2306 ) 2307 ); 2308 xer_ca 2309 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2310 break; 2311 2312 2313 case /* 12 */ PPCG_FLAG_OP_SRAD: 2314 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2315 If it is <= 63, behave like SRADI; else XER.CA is the sign 2316 bit of argL. */ 2317 /* This term valid for shift amount < 63 only */ 2318 2319 xer_ca 2320 = binop( 2321 Iop_And64, 2322 binop(Iop_Sar64, argL, mkU8(63)), 2323 binop( Iop_And64, 2324 argL, 2325 binop( Iop_Sub64, 2326 binop(Iop_Shl64, mkU64(1), 2327 unop(Iop_64to8,argR)), 2328 mkU64(1) ) 2329 ) 2330 ); 2331 xer_ca 2332 = IRExpr_Mux0X( 2333 /* shift amt > 63 ? */ 2334 unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)), 2335 /* no -- be like sradi */ 2336 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))), 2337 /* yes -- get sign bit of argL */ 2338 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))) 2339 ); 2340 break; 2341 2342 2343 case /* 13 */ PPCG_FLAG_OP_SRADI: 2344 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2345 Since the shift amount is known to be in the range 0 .. 63 2346 inclusive, the following seems viable: 2347 xer.ca == 1 iff the following is nonzero: 2348 (argL >>s 63) -- either all 0s or all 1s 2349 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2350 2351 xer_ca 2352 = binop( 2353 Iop_And64, 2354 binop(Iop_Sar64, argL, mkU8(63)), 2355 binop( Iop_And64, 2356 argL, 2357 binop( Iop_Sub64, 2358 binop(Iop_Shl64, mkU64(1), 2359 unop(Iop_64to8,argR)), 2360 mkU64(1) ) 2361 ) 2362 ); 2363 xer_ca 2364 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2365 break; 2366 2367 default: 2368 vex_printf("set_XER_CA: op = %u\n", op); 2369 vpanic("set_XER_CA(ppc64)"); 2370 } 2371 2372 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2373 putXER_CA( unop(Iop_32to8, xer_ca) ); 2374} 2375 2376static void set_XER_CA ( IRType ty, UInt op, IRExpr* res, 2377 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2378{ 2379 if (ty == Ity_I32) 2380 set_XER_CA_32( op, res, argL, argR, oldca ); 2381 else 2382 set_XER_CA_64( op, res, argL, argR, oldca ); 2383} 2384 2385 2386 2387/*------------------------------------------------------------*/ 2388/*--- Read/write to guest-state --- */ 2389/*------------------------------------------------------------*/ 2390 2391static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg ) 2392{ 2393 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2394 switch (reg) { 2395 case PPC_GST_SPRG3_RO: 2396 return IRExpr_Get( OFFB_SPRG3_RO, ty ); 2397 2398 case PPC_GST_CIA: 2399 return IRExpr_Get( OFFB_CIA, ty ); 2400 2401 case PPC_GST_LR: 2402 return IRExpr_Get( OFFB_LR, ty ); 2403 2404 case PPC_GST_CTR: 2405 return IRExpr_Get( OFFB_CTR, ty ); 2406 2407 case PPC_GST_VRSAVE: 2408 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); 2409 2410 case PPC_GST_VSCR: 2411 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ), 2412 mkU32(MASK_VSCR_VALID)); 2413 2414 case PPC_GST_CR: { 2415 /* Synthesise the entire CR into a single word. Expensive. */ 2416# define FIELD(_n) \ 2417 binop(Iop_Shl32, \ 2418 unop(Iop_8Uto32, \ 2419 binop(Iop_Or8, \ 2420 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ 2421 binop(Iop_And8, getCR0(_n), mkU8(1)) \ 2422 ) \ 2423 ), \ 2424 mkU8(4 * (7-(_n))) \ 2425 ) 2426 return binop(Iop_Or32, 2427 binop(Iop_Or32, 2428 binop(Iop_Or32, FIELD(0), FIELD(1)), 2429 binop(Iop_Or32, FIELD(2), FIELD(3)) 2430 ), 2431 binop(Iop_Or32, 2432 binop(Iop_Or32, FIELD(4), FIELD(5)), 2433 binop(Iop_Or32, FIELD(6), FIELD(7)) 2434 ) 2435 ); 2436# undef FIELD 2437 } 2438 2439 case PPC_GST_XER: 2440 return binop(Iop_Or32, 2441 binop(Iop_Or32, 2442 binop( Iop_Shl32, getXER_SO32(), mkU8(31)), 2443 binop( Iop_Shl32, getXER_OV32(), mkU8(30))), 2444 binop(Iop_Or32, 2445 binop( Iop_Shl32, getXER_CA32(), mkU8(29)), 2446 getXER_BC32())); 2447 2448 default: 2449 vex_printf("getGST(ppc): reg = %u", reg); 2450 vpanic("getGST(ppc)"); 2451 } 2452} 2453 2454/* Get a masked word from the given reg */ 2455static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask ) 2456{ 2457 IRTemp val = newTemp(Ity_I32); 2458 vassert( reg < PPC_GST_MAX ); 2459 2460 switch (reg) { 2461 2462 case PPC_GST_FPSCR: { 2463 /* Vex-generated code expects the FPSCR to be set as follows: 2464 all exceptions masked, round-to-nearest. 2465 This corresponds to a FPSCR value of 0x0. */ 2466 2467 /* We're only keeping track of the rounding mode, 2468 so if the mask isn't asking for this, just return 0x0 */ 2469 if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) { 2470 assign( val, IRExpr_Get( OFFB_FPROUND, Ity_I32 ) ); 2471 } else { 2472 assign( val, mkU32(0x0) ); 2473 } 2474 break; 2475 } 2476 2477 default: 2478 vex_printf("getGST_masked(ppc): reg = %u", reg); 2479 vpanic("getGST_masked(ppc)"); 2480 } 2481 2482 if (mask != 0xFFFFFFFF) { 2483 return binop(Iop_And32, mkexpr(val), mkU32(mask)); 2484 } else { 2485 return mkexpr(val); 2486 } 2487} 2488 2489/* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation) 2490 and return it at the bottom of an I32; the top 27 bits are 2491 guaranteed to be zero. */ 2492static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld ) 2493{ 2494 UInt shft, mask; 2495 2496 vassert( fld < 8 ); 2497 vassert( reg < PPC_GST_MAX ); 2498 2499 shft = 4*(7-fld); 2500 mask = 0xF<<shft; 2501 2502 switch (reg) { 2503 case PPC_GST_XER: 2504 vassert(fld ==7); 2505 return binop(Iop_Or32, 2506 binop(Iop_Or32, 2507 binop(Iop_Shl32, getXER_SO32(), mkU8(3)), 2508 binop(Iop_Shl32, getXER_OV32(), mkU8(2))), 2509 binop( Iop_Shl32, getXER_CA32(), mkU8(1))); 2510 break; 2511 2512 default: 2513 if (shft == 0) 2514 return getGST_masked( reg, mask ); 2515 else 2516 return binop(Iop_Shr32, 2517 getGST_masked( reg, mask ), 2518 mkU8(toUChar( shft ))); 2519 } 2520} 2521 2522static void putGST ( PPC_GST reg, IRExpr* src ) 2523{ 2524 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2525 IRType ty_src = typeOfIRExpr(irsb->tyenv,src ); 2526 vassert( reg < PPC_GST_MAX ); 2527 switch (reg) { 2528 case PPC_GST_IP_AT_SYSCALL: 2529 vassert( ty_src == ty ); 2530 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) ); 2531 break; 2532 case PPC_GST_CIA: 2533 vassert( ty_src == ty ); 2534 stmt( IRStmt_Put( OFFB_CIA, src ) ); 2535 break; 2536 case PPC_GST_LR: 2537 vassert( ty_src == ty ); 2538 stmt( IRStmt_Put( OFFB_LR, src ) ); 2539 break; 2540 case PPC_GST_CTR: 2541 vassert( ty_src == ty ); 2542 stmt( IRStmt_Put( OFFB_CTR, src ) ); 2543 break; 2544 case PPC_GST_VRSAVE: 2545 vassert( ty_src == Ity_I32 ); 2546 stmt( IRStmt_Put( OFFB_VRSAVE,src)); 2547 break; 2548 case PPC_GST_VSCR: 2549 vassert( ty_src == Ity_I32 ); 2550 stmt( IRStmt_Put( OFFB_VSCR, 2551 binop(Iop_And32, src, 2552 mkU32(MASK_VSCR_VALID)) ) ); 2553 break; 2554 case PPC_GST_XER: 2555 vassert( ty_src == Ity_I32 ); 2556 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) ); 2557 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) ); 2558 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) ); 2559 putXER_BC( unop(Iop_32to8, src) ); 2560 break; 2561 2562 case PPC_GST_EMWARN: 2563 vassert( ty_src == Ity_I32 ); 2564 stmt( IRStmt_Put( OFFB_EMWARN,src) ); 2565 break; 2566 2567 case PPC_GST_TISTART: 2568 vassert( ty_src == ty ); 2569 stmt( IRStmt_Put( OFFB_TISTART, src) ); 2570 break; 2571 2572 case PPC_GST_TILEN: 2573 vassert( ty_src == ty ); 2574 stmt( IRStmt_Put( OFFB_TILEN, src) ); 2575 break; 2576 2577 default: 2578 vex_printf("putGST(ppc): reg = %u", reg); 2579 vpanic("putGST(ppc)"); 2580 } 2581} 2582 2583/* Write masked src to the given reg */ 2584static void putGST_masked ( PPC_GST reg, IRExpr* src, UInt mask ) 2585{ 2586 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2587 vassert( reg < PPC_GST_MAX ); 2588 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 2589 2590 switch (reg) { 2591 case PPC_GST_FPSCR: { 2592 /* Allow writes to Rounding Mode */ 2593 if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) { 2594 /* construct new fpround from new and old values as per mask: 2595 new fpround = (src & (3 & mask)) | (fpround & (3 & ~mask)) */ 2596 stmt( 2597 IRStmt_Put( 2598 OFFB_FPROUND, 2599 binop( 2600 Iop_Or32, 2601 binop(Iop_And32, src, mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & mask)), 2602 binop( 2603 Iop_And32, 2604 IRExpr_Get(OFFB_FPROUND,Ity_I32), 2605 mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & ~mask) 2606 ) 2607 ) 2608 ) 2609 ); 2610 } 2611 2612 /* Give EmWarn for attempted writes to: 2613 - Exception Controls 2614 - Non-IEEE Mode 2615 */ 2616 if (mask & 0xFC) { // Exception Control, Non-IEE mode 2617 VexEmWarn ew = EmWarn_PPCexns; 2618 2619 /* If any of the src::exception_control bits are actually set, 2620 side-exit to the next insn, reporting the warning, 2621 so that Valgrind's dispatcher sees the warning. */ 2622 putGST( PPC_GST_EMWARN, mkU32(ew) ); 2623 stmt( 2624 IRStmt_Exit( 2625 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)), 2626 Ijk_EmWarn, 2627 mkSzConst( ty, nextInsnAddr()) )); 2628 } 2629 2630 /* Ignore all other writes */ 2631 break; 2632 } 2633 2634 default: 2635 vex_printf("putGST_masked(ppc): reg = %u", reg); 2636 vpanic("putGST_masked(ppc)"); 2637 } 2638} 2639 2640/* Write the least significant nibble of src to the specified 2641 REG[FLD] (as per IBM/hardware notation). */ 2642static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld ) 2643{ 2644 UInt shft, mask; 2645 2646 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 2647 vassert( fld < 8 ); 2648 vassert( reg < PPC_GST_MAX ); 2649 2650 shft = 4*(7-fld); 2651 mask = 0xF<<shft; 2652 2653 switch (reg) { 2654 case PPC_GST_CR: 2655 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src))); 2656 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src))); 2657 break; 2658 2659 default: 2660 if (shft == 0) { 2661 putGST_masked( reg, src, mask ); 2662 } else { 2663 putGST_masked( reg, 2664 binop(Iop_Shl32, src, mkU8(toUChar(shft))), 2665 mask ); 2666 } 2667 } 2668} 2669 2670/*------------------------------------------------------------*/ 2671/* Helpers for VSX instructions that do floating point 2672 * operations and need to determine if a src contains a 2673 * special FP value. 2674 * 2675 *------------------------------------------------------------*/ 2676 2677#define NONZERO_FRAC_MASK 0x000fffffffffffffULL 2678#define FP_FRAC_PART(x) binop( Iop_And64, \ 2679 mkexpr( x ), \ 2680 mkU64( NONZERO_FRAC_MASK ) ) 2681 2682// Returns exponent part of a single precision floating point as I32 2683static IRExpr * fp_exp_part_sp(IRTemp src) 2684{ 2685 return binop( Iop_And32, 2686 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 2687 mkU32( 0xff ) ); 2688} 2689 2690// Returns exponent part of floating point as I32 2691static IRExpr * fp_exp_part(IRTemp src, Bool sp) 2692{ 2693 IRExpr * exp; 2694 if (sp) 2695 return fp_exp_part_sp(src); 2696 2697 if (!mode64) 2698 exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32, 2699 mkexpr( src ) ), 2700 mkU8( 20 ) ), mkU32( 0x7ff ) ); 2701 else 2702 exp = unop( Iop_64to32, 2703 binop( Iop_And64, 2704 binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ), 2705 mkU64( 0x7ff ) ) ); 2706 return exp; 2707} 2708 2709static IRExpr * is_Inf_sp(IRTemp src) 2710{ 2711 IRTemp frac_part = newTemp(Ity_I32); 2712 IRExpr * Inf_exp; 2713 2714 assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) ); 2715 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) ); 2716 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) ); 2717} 2718 2719 2720// Infinity: exp = 7ff and fraction is zero; s = 0/1 2721static IRExpr * is_Inf(IRTemp src, Bool sp) 2722{ 2723 IRExpr * Inf_exp, * hi32, * low32; 2724 IRTemp frac_part; 2725 2726 if (sp) 2727 return is_Inf_sp(src); 2728 2729 frac_part = newTemp(Ity_I64); 2730 assign( frac_part, FP_FRAC_PART(src) ); 2731 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), mkU32( 0x7ff ) ); 2732 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 2733 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 2734 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 2735 mkU32( 0 ) ) ); 2736} 2737 2738static IRExpr * is_Zero_sp(IRTemp src) 2739{ 2740 IRTemp sign_less_part = newTemp(Ity_I32); 2741 assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) ); 2742 return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) ); 2743} 2744 2745// Zero: exp is zero and fraction is zero; s = 0/1 2746static IRExpr * is_Zero(IRTemp src, Bool sp) 2747{ 2748 IRExpr * hi32, * low32; 2749 IRTemp sign_less_part; 2750 if (sp) 2751 return is_Zero_sp(src); 2752 2753 sign_less_part = newTemp(Ity_I64); 2754 2755 assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) ); 2756 hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) ); 2757 low32 = unop( Iop_64to32, mkexpr( sign_less_part ) ); 2758 return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 2759 mkU32( 0 ) ); 2760} 2761 2762/* SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1' 2763 * QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0' 2764 * This function returns an IRExpr value of '1' for any type of NaN. 2765 */ 2766static IRExpr * is_NaN(IRTemp src) 2767{ 2768 IRExpr * NaN_exp, * hi32, * low32; 2769 IRTemp frac_part = newTemp(Ity_I64); 2770 2771 assign( frac_part, FP_FRAC_PART(src) ); 2772 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 2773 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 2774 NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), 2775 mkU32( 0x7ff ) ); 2776 2777 return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 2778 mkU32( 0 ) ) ); 2779} 2780 2781/* This function returns an IRExpr value of '1' for any type of NaN. 2782 * The passed 'src' argument is assumed to be Ity_I32. 2783 */ 2784static IRExpr * is_NaN_32(IRTemp src) 2785{ 2786#define NONZERO_FRAC_MASK32 0x007fffffULL 2787#define FP_FRAC_PART32(x) binop( Iop_And32, \ 2788 mkexpr( x ), \ 2789 mkU32( NONZERO_FRAC_MASK32 ) ) 2790 2791 IRExpr * frac_part = FP_FRAC_PART32(src); 2792 IRExpr * exp_part = binop( Iop_And32, 2793 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 2794 mkU32( 0x0ff ) ); 2795 IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) ); 2796 2797 return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) ); 2798} 2799 2800/* This helper function performs the negation part of operations of the form: 2801 * "Negate Multiply-<op>" 2802 * where "<op>" is either "Add" or "Sub". 2803 * 2804 * This function takes one argument -- the floating point intermediate result (converted to 2805 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of 2806 * the operation described above. 2807 */ 2808static IRTemp getNegatedResult(IRTemp intermediateResult) 2809{ 2810 ULong signbit_mask = 0x8000000000000000ULL; 2811 IRTemp signbit_32 = newTemp(Ity_I32); 2812 IRTemp resultantSignbit = newTemp(Ity_I1); 2813 IRTemp negatedResult = newTemp(Ity_I64); 2814 assign( signbit_32, binop( Iop_Shr32, 2815 unop( Iop_64HIto32, 2816 binop( Iop_And64, mkexpr( intermediateResult ), 2817 mkU64( signbit_mask ) ) ), 2818 mkU8( 31 ) ) ); 2819 /* We negate the signbit if and only if the intermediate result from the 2820 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 2821 */ 2822 assign( resultantSignbit, 2823 unop( Iop_Not1, 2824 binop( Iop_CmpEQ32, 2825 binop( Iop_Xor32, 2826 mkexpr( signbit_32 ), 2827 unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ), 2828 mkU32( 1 ) ) ) ); 2829 2830 assign( negatedResult, 2831 binop( Iop_Or64, 2832 binop( Iop_And64, 2833 mkexpr( intermediateResult ), 2834 mkU64( ~signbit_mask ) ), 2835 binop( Iop_32HLto64, 2836 binop( Iop_Shl32, 2837 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 2838 mkU8( 31 ) ), 2839 mkU32( 0 ) ) ) ); 2840 2841 return negatedResult; 2842} 2843 2844/* This helper function performs the negation part of operations of the form: 2845 * "Negate Multiply-<op>" 2846 * where "<op>" is either "Add" or "Sub". 2847 * 2848 * This function takes one argument -- the floating point intermediate result (converted to 2849 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of 2850 * the operation described above. 2851 */ 2852static IRTemp getNegatedResult_32(IRTemp intermediateResult) 2853{ 2854 UInt signbit_mask = 0x80000000; 2855 IRTemp signbit_32 = newTemp(Ity_I32); 2856 IRTemp resultantSignbit = newTemp(Ity_I1); 2857 IRTemp negatedResult = newTemp(Ity_I32); 2858 assign( signbit_32, binop( Iop_Shr32, 2859 binop( Iop_And32, mkexpr( intermediateResult ), 2860 mkU32( signbit_mask ) ), 2861 mkU8( 31 ) ) ); 2862 /* We negate the signbit if and only if the intermediate result from the 2863 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 2864 */ 2865 assign( resultantSignbit, 2866 unop( Iop_Not1, 2867 binop( Iop_CmpEQ32, 2868 binop( Iop_Xor32, 2869 mkexpr( signbit_32 ), 2870 unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ), 2871 mkU32( 1 ) ) ) ); 2872 2873 assign( negatedResult, 2874 binop( Iop_Or32, 2875 binop( Iop_And32, 2876 mkexpr( intermediateResult ), 2877 mkU32( ~signbit_mask ) ), 2878 binop( Iop_Shl32, 2879 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 2880 mkU8( 31 ) ) ) ); 2881 2882 return negatedResult; 2883} 2884 2885/*------------------------------------------------------------*/ 2886/*--- Integer Instruction Translation --- */ 2887/*------------------------------------------------------------*/ 2888 2889/* 2890 Integer Arithmetic Instructions 2891*/ 2892static Bool dis_int_arith ( UInt theInstr ) 2893{ 2894 /* D-Form, XO-Form */ 2895 UChar opc1 = ifieldOPC(theInstr); 2896 UChar rD_addr = ifieldRegDS(theInstr); 2897 UChar rA_addr = ifieldRegA(theInstr); 2898 UInt uimm16 = ifieldUIMM16(theInstr); 2899 UChar rB_addr = ifieldRegB(theInstr); 2900 UChar flag_OE = ifieldBIT10(theInstr); 2901 UInt opc2 = ifieldOPClo9(theInstr); 2902 UChar flag_rC = ifieldBIT0(theInstr); 2903 2904 Long simm16 = extend_s_16to64(uimm16); 2905 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2906 IRTemp rA = newTemp(ty); 2907 IRTemp rB = newTemp(ty); 2908 IRTemp rD = newTemp(ty); 2909 2910 Bool do_rc = False; 2911 2912 assign( rA, getIReg(rA_addr) ); 2913 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB 2914 2915 switch (opc1) { 2916 /* D-Form */ 2917 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 2918 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 2919 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 2920 mkSzExtendS16(ty, uimm16) ) ); 2921 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 2922 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 2923 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 2924 break; 2925 2926 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) 2927 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 2928 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 2929 mkSzExtendS16(ty, uimm16) ) ); 2930 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 2931 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 2932 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 2933 do_rc = True; // Always record to CR 2934 flag_rC = 1; 2935 break; 2936 2937 case 0x0E: // addi (Add Immediate, PPC32 p350) 2938 // li rD,val == addi rD,0,val 2939 // la disp(rA) == addi rD,rA,disp 2940 if ( rA_addr == 0 ) { 2941 DIP("li r%u,%d\n", rD_addr, (Int)simm16); 2942 assign( rD, mkSzExtendS16(ty, uimm16) ); 2943 } else { 2944 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 2945 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 2946 mkSzExtendS16(ty, uimm16) ) ); 2947 } 2948 break; 2949 2950 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353) 2951 // lis rD,val == addis rD,0,val 2952 if ( rA_addr == 0 ) { 2953 DIP("lis r%u,%d\n", rD_addr, (Int)simm16); 2954 assign( rD, mkSzExtendS32(ty, uimm16 << 16) ); 2955 } else { 2956 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16); 2957 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 2958 mkSzExtendS32(ty, uimm16 << 16) ) ); 2959 } 2960 break; 2961 2962 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490) 2963 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 2964 if (mode64) 2965 assign( rD, unop(Iop_128to64, 2966 binop(Iop_MullS64, mkexpr(rA), 2967 mkSzExtendS16(ty, uimm16))) ); 2968 else 2969 assign( rD, unop(Iop_64to32, 2970 binop(Iop_MullS32, mkexpr(rA), 2971 mkSzExtendS16(ty, uimm16))) ); 2972 break; 2973 2974 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540) 2975 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 2976 // rD = simm16 - rA 2977 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 2978 mkSzExtendS16(ty, uimm16), 2979 mkexpr(rA)) ); 2980 set_XER_CA( ty, PPCG_FLAG_OP_SUBFI, 2981 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 2982 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 2983 break; 2984 2985 /* XO-Form */ 2986 case 0x1F: 2987 do_rc = True; // All below record to CR 2988 2989 switch (opc2) { 2990 case 0x10A: // add (Add, PPC32 p347) 2991 DIP("add%s%s r%u,r%u,r%u\n", 2992 flag_OE ? "o" : "", flag_rC ? ".":"", 2993 rD_addr, rA_addr, rB_addr); 2994 assign( rD, binop( mkSzOp(ty, Iop_Add8), 2995 mkexpr(rA), mkexpr(rB) ) ); 2996 if (flag_OE) { 2997 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 2998 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 2999 } 3000 break; 3001 3002 case 0x00A: // addc (Add Carrying, PPC32 p348) 3003 DIP("addc%s%s r%u,r%u,r%u\n", 3004 flag_OE ? "o" : "", flag_rC ? ".":"", 3005 rD_addr, rA_addr, rB_addr); 3006 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3007 mkexpr(rA), mkexpr(rB)) ); 3008 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3009 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3010 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3011 if (flag_OE) { 3012 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3013 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3014 } 3015 break; 3016 3017 case 0x08A: { // adde (Add Extended, PPC32 p349) 3018 IRTemp old_xer_ca = newTemp(ty); 3019 DIP("adde%s%s r%u,r%u,r%u\n", 3020 flag_OE ? "o" : "", flag_rC ? ".":"", 3021 rD_addr, rA_addr, rB_addr); 3022 // rD = rA + rB + XER[CA] 3023 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3024 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3025 binop( mkSzOp(ty, Iop_Add8), 3026 mkexpr(rB), mkexpr(old_xer_ca))) ); 3027 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3028 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3029 mkexpr(old_xer_ca) ); 3030 if (flag_OE) { 3031 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3032 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3033 } 3034 break; 3035 } 3036 3037 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354) 3038 IRTemp old_xer_ca = newTemp(ty); 3039 IRExpr *min_one; 3040 if (rB_addr != 0) { 3041 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n"); 3042 return False; 3043 } 3044 DIP("addme%s%s r%u,r%u,r%u\n", 3045 flag_OE ? "o" : "", flag_rC ? ".":"", 3046 rD_addr, rA_addr, rB_addr); 3047 // rD = rA + (-1) + XER[CA] 3048 // => Just another form of adde 3049 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3050 min_one = mkSzImm(ty, (Long)-1); 3051 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3052 binop( mkSzOp(ty, Iop_Add8), 3053 min_one, mkexpr(old_xer_ca)) )); 3054 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3055 mkexpr(rD), mkexpr(rA), min_one, 3056 mkexpr(old_xer_ca) ); 3057 if (flag_OE) { 3058 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3059 mkexpr(rD), mkexpr(rA), min_one ); 3060 } 3061 break; 3062 } 3063 3064 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355) 3065 IRTemp old_xer_ca = newTemp(ty); 3066 if (rB_addr != 0) { 3067 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n"); 3068 return False; 3069 } 3070 DIP("addze%s%s r%u,r%u,r%u\n", 3071 flag_OE ? "o" : "", flag_rC ? ".":"", 3072 rD_addr, rA_addr, rB_addr); 3073 // rD = rA + (0) + XER[CA] 3074 // => Just another form of adde 3075 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3076 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3077 mkexpr(rA), mkexpr(old_xer_ca)) ); 3078 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3079 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3080 mkexpr(old_xer_ca) ); 3081 if (flag_OE) { 3082 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3083 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3084 } 3085 break; 3086 } 3087 3088 case 0x1EB: // divw (Divide Word, PPC32 p388) 3089 DIP("divw%s%s r%u,r%u,r%u\n", 3090 flag_OE ? "o" : "", flag_rC ? ".":"", 3091 rD_addr, rA_addr, rB_addr); 3092 if (mode64) { 3093 /* Note: 3094 XER settings are mode independent, and reflect the 3095 overflow of the low-order 32bit result 3096 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3097 */ 3098 /* rD[hi32] are undefined: setting them to sign of lo32 3099 - makes set_CR0 happy */ 3100 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) ); 3101 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) ); 3102 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend, 3103 divisor) ) ); 3104 if (flag_OE) { 3105 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3106 mkexpr(rD), dividend, divisor ); 3107 } 3108 } else { 3109 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) ); 3110 if (flag_OE) { 3111 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3112 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3113 } 3114 } 3115 /* Note: 3116 if (0x8000_0000 / -1) or (x / 0) 3117 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3118 => But _no_ exception raised. */ 3119 break; 3120 3121 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389) 3122 DIP("divwu%s%s r%u,r%u,r%u\n", 3123 flag_OE ? "o" : "", flag_rC ? ".":"", 3124 rD_addr, rA_addr, rB_addr); 3125 if (mode64) { 3126 /* Note: 3127 XER settings are mode independent, and reflect the 3128 overflow of the low-order 32bit result 3129 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3130 */ 3131 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) ); 3132 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) ); 3133 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend, 3134 divisor) ) ); 3135 if (flag_OE) { 3136 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3137 mkexpr(rD), dividend, divisor ); 3138 } 3139 } else { 3140 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) ); 3141 if (flag_OE) { 3142 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3143 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3144 } 3145 } 3146 /* Note: ditto comment divw, for (x / 0) */ 3147 break; 3148 3149 case 0x04B: // mulhw (Multiply High Word, PPC32 p488) 3150 if (flag_OE != 0) { 3151 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n"); 3152 return False; 3153 } 3154 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3155 rD_addr, rA_addr, rB_addr); 3156 if (mode64) { 3157 /* rD[hi32] are undefined: setting them to sign of lo32 3158 - makes set_CR0 happy */ 3159 assign( rD, binop(Iop_Sar64, 3160 binop(Iop_Mul64, 3161 mk64lo32Sto64( mkexpr(rA) ), 3162 mk64lo32Sto64( mkexpr(rB) )), 3163 mkU8(32)) ); 3164 } else { 3165 assign( rD, unop(Iop_64HIto32, 3166 binop(Iop_MullS32, 3167 mkexpr(rA), mkexpr(rB))) ); 3168 } 3169 break; 3170 3171 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489) 3172 if (flag_OE != 0) { 3173 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n"); 3174 return False; 3175 } 3176 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3177 rD_addr, rA_addr, rB_addr); 3178 if (mode64) { 3179 /* rD[hi32] are undefined: setting them to sign of lo32 3180 - makes set_CR0 happy */ 3181 assign( rD, binop(Iop_Sar64, 3182 binop(Iop_Mul64, 3183 mk64lo32Uto64( mkexpr(rA) ), 3184 mk64lo32Uto64( mkexpr(rB) ) ), 3185 mkU8(32)) ); 3186 } else { 3187 assign( rD, unop(Iop_64HIto32, 3188 binop(Iop_MullU32, 3189 mkexpr(rA), mkexpr(rB))) ); 3190 } 3191 break; 3192 3193 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491) 3194 DIP("mullw%s%s r%u,r%u,r%u\n", 3195 flag_OE ? "o" : "", flag_rC ? ".":"", 3196 rD_addr, rA_addr, rB_addr); 3197 if (mode64) { 3198 /* rD[hi32] are undefined: setting them to sign of lo32 3199 - set_XER_OV() and set_CR0() depend on this */ 3200 IRExpr *a = unop(Iop_64to32, mkexpr(rA) ); 3201 IRExpr *b = unop(Iop_64to32, mkexpr(rB) ); 3202 assign( rD, binop(Iop_MullS32, a, b) ); 3203 if (flag_OE) { 3204 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3205 mkexpr(rD), 3206 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) ); 3207 } 3208 } else { 3209 assign( rD, unop(Iop_64to32, 3210 binop(Iop_MullU32, 3211 mkexpr(rA), mkexpr(rB))) ); 3212 if (flag_OE) { 3213 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3214 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3215 } 3216 } 3217 break; 3218 3219 case 0x068: // neg (Negate, PPC32 p493) 3220 if (rB_addr != 0) { 3221 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n"); 3222 return False; 3223 } 3224 DIP("neg%s%s r%u,r%u\n", 3225 flag_OE ? "o" : "", flag_rC ? ".":"", 3226 rD_addr, rA_addr); 3227 // rD = (~rA) + 1 3228 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3229 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ), 3230 mkSzImm(ty, 1)) ); 3231 if (flag_OE) { 3232 set_XER_OV( ty, PPCG_FLAG_OP_NEG, 3233 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3234 } 3235 break; 3236 3237 case 0x028: // subf (Subtract From, PPC32 p537) 3238 DIP("subf%s%s r%u,r%u,r%u\n", 3239 flag_OE ? "o" : "", flag_rC ? ".":"", 3240 rD_addr, rA_addr, rB_addr); 3241 // rD = rB - rA 3242 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3243 mkexpr(rB), mkexpr(rA)) ); 3244 if (flag_OE) { 3245 set_XER_OV( ty, PPCG_FLAG_OP_SUBF, 3246 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3247 } 3248 break; 3249 3250 case 0x008: // subfc (Subtract from Carrying, PPC32 p538) 3251 DIP("subfc%s%s r%u,r%u,r%u\n", 3252 flag_OE ? "o" : "", flag_rC ? ".":"", 3253 rD_addr, rA_addr, rB_addr); 3254 // rD = rB - rA 3255 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3256 mkexpr(rB), mkexpr(rA)) ); 3257 set_XER_CA( ty, PPCG_FLAG_OP_SUBFC, 3258 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3259 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3260 if (flag_OE) { 3261 set_XER_OV( ty, PPCG_FLAG_OP_SUBFC, 3262 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3263 } 3264 break; 3265 3266 case 0x088: {// subfe (Subtract from Extended, PPC32 p539) 3267 IRTemp old_xer_ca = newTemp(ty); 3268 DIP("subfe%s%s r%u,r%u,r%u\n", 3269 flag_OE ? "o" : "", flag_rC ? ".":"", 3270 rD_addr, rA_addr, rB_addr); 3271 // rD = (log not)rA + rB + XER[CA] 3272 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3273 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3274 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3275 binop( mkSzOp(ty, Iop_Add8), 3276 mkexpr(rB), mkexpr(old_xer_ca))) ); 3277 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3278 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3279 mkexpr(old_xer_ca) ); 3280 if (flag_OE) { 3281 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3282 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3283 } 3284 break; 3285 } 3286 3287 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541) 3288 IRTemp old_xer_ca = newTemp(ty); 3289 IRExpr *min_one; 3290 if (rB_addr != 0) { 3291 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n"); 3292 return False; 3293 } 3294 DIP("subfme%s%s r%u,r%u\n", 3295 flag_OE ? "o" : "", flag_rC ? ".":"", 3296 rD_addr, rA_addr); 3297 // rD = (log not)rA + (-1) + XER[CA] 3298 // => Just another form of subfe 3299 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3300 min_one = mkSzImm(ty, (Long)-1); 3301 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3302 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3303 binop( mkSzOp(ty, Iop_Add8), 3304 min_one, mkexpr(old_xer_ca))) ); 3305 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3306 mkexpr(rD), mkexpr(rA), min_one, 3307 mkexpr(old_xer_ca) ); 3308 if (flag_OE) { 3309 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3310 mkexpr(rD), mkexpr(rA), min_one ); 3311 } 3312 break; 3313 } 3314 3315 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542) 3316 IRTemp old_xer_ca = newTemp(ty); 3317 if (rB_addr != 0) { 3318 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n"); 3319 return False; 3320 } 3321 DIP("subfze%s%s r%u,r%u\n", 3322 flag_OE ? "o" : "", flag_rC ? ".":"", 3323 rD_addr, rA_addr); 3324 // rD = (log not)rA + (0) + XER[CA] 3325 // => Just another form of subfe 3326 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3327 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3328 unop( mkSzOp(ty, Iop_Not8), 3329 mkexpr(rA)), mkexpr(old_xer_ca)) ); 3330 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3331 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3332 mkexpr(old_xer_ca) ); 3333 if (flag_OE) { 3334 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3335 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3336 } 3337 break; 3338 } 3339 3340 3341 /* 64bit Arithmetic */ 3342 case 0x49: // mulhd (Multiply High DWord, PPC64 p539) 3343 if (flag_OE != 0) { 3344 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n"); 3345 return False; 3346 } 3347 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3348 rD_addr, rA_addr, rB_addr); 3349 assign( rD, unop(Iop_128HIto64, 3350 binop(Iop_MullS64, 3351 mkexpr(rA), mkexpr(rB))) ); 3352 3353 break; 3354 3355 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540) 3356 if (flag_OE != 0) { 3357 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n"); 3358 return False; 3359 } 3360 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3361 rD_addr, rA_addr, rB_addr); 3362 assign( rD, unop(Iop_128HIto64, 3363 binop(Iop_MullU64, 3364 mkexpr(rA), mkexpr(rB))) ); 3365 break; 3366 3367 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543) 3368 DIP("mulld%s%s r%u,r%u,r%u\n", 3369 flag_OE ? "o" : "", flag_rC ? ".":"", 3370 rD_addr, rA_addr, rB_addr); 3371 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) ); 3372 if (flag_OE) { 3373 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3374 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3375 } 3376 break; 3377 3378 case 0x1E9: // divd (Divide DWord, PPC64 p419) 3379 DIP("divd%s%s r%u,r%u,r%u\n", 3380 flag_OE ? "o" : "", flag_rC ? ".":"", 3381 rD_addr, rA_addr, rB_addr); 3382 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) ); 3383 if (flag_OE) { 3384 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3385 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3386 } 3387 break; 3388 /* Note: 3389 if (0x8000_0000_0000_0000 / -1) or (x / 0) 3390 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3391 => But _no_ exception raised. */ 3392 3393 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420) 3394 DIP("divdu%s%s r%u,r%u,r%u\n", 3395 flag_OE ? "o" : "", flag_rC ? ".":"", 3396 rD_addr, rA_addr, rB_addr); 3397 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) ); 3398 if (flag_OE) { 3399 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3400 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3401 } 3402 break; 3403 /* Note: ditto comment divd, for (x / 0) */ 3404 3405 case 0x18B: // divweu (Divide Word Extended Unsigned) 3406 { 3407 /* 3408 * If (RA) >= (RB), or if an attempt is made to perform the division 3409 * <anything> / 0 3410 * then the contents of register RD are undefined as are (if Rc=1) the contents of 3411 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set 3412 * to 1. 3413 */ 3414 IRTemp res = newTemp(Ity_I32); 3415 IRExpr * dividend, * divisor; 3416 DIP("divweu%s%s r%u,r%u,r%u\n", 3417 flag_OE ? "o" : "", flag_rC ? ".":"", 3418 rD_addr, rA_addr, rB_addr); 3419 if (mode64) { 3420 dividend = unop( Iop_64to32, mkexpr( rA ) ); 3421 divisor = unop( Iop_64to32, mkexpr( rB ) ); 3422 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 3423 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 3424 } else { 3425 dividend = mkexpr( rA ); 3426 divisor = mkexpr( rB ); 3427 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 3428 assign( rD, mkexpr( res) ); 3429 } 3430 3431 if (flag_OE) { 3432 set_XER_OV_32( PPCG_FLAG_OP_DIVWEU, 3433 mkexpr(res), dividend, divisor ); 3434 } 3435 break; 3436 } 3437 3438 case 0x1AB: // divwe (Divide Word Extended) 3439 { 3440 /* 3441 * If the quotient cannot be represented in 32 bits, or if an 3442 * attempt is made to perform the division 3443 * <anything> / 0 3444 * then the contents of register RD are undefined as are (if 3445 * Rc=1) the contents of the LT, GT, and EQ bits of CR 3446 * Field 0. In these cases, if OE=1 then OV is set to 1. 3447 */ 3448 3449 IRTemp res = newTemp(Ity_I32); 3450 IRExpr * dividend, * divisor; 3451 DIP("divwe%s%s r%u,r%u,r%u\n", 3452 flag_OE ? "o" : "", flag_rC ? ".":"", 3453 rD_addr, rA_addr, rB_addr); 3454 if (mode64) { 3455 dividend = unop( Iop_64to32, mkexpr( rA ) ); 3456 divisor = unop( Iop_64to32, mkexpr( rB ) ); 3457 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 3458 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 3459 } else { 3460 dividend = mkexpr( rA ); 3461 divisor = mkexpr( rB ); 3462 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 3463 assign( rD, mkexpr( res) ); 3464 } 3465 3466 if (flag_OE) { 3467 set_XER_OV_32( PPCG_FLAG_OP_DIVWE, 3468 mkexpr(res), dividend, divisor ); 3469 } 3470 break; 3471 } 3472 3473 3474 case 0x1A9: // divde (Divide Doubleword Extended) 3475 /* 3476 * If the quotient cannot be represented in 64 bits, or if an 3477 * attempt is made to perform the division 3478 * <anything> / 0 3479 * then the contents of register RD are undefined as are (if 3480 * Rc=1) the contents of the LT, GT, and EQ bits of CR 3481 * Field 0. In these cases, if OE=1 then OV is set to 1. 3482 */ 3483 DIP("divde%s%s r%u,r%u,r%u\n", 3484 flag_OE ? "o" : "", flag_rC ? ".":"", 3485 rD_addr, rA_addr, rB_addr); 3486 assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) ); 3487 if (flag_OE) { 3488 set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ), 3489 mkexpr( rA ), mkexpr( rB ) ); 3490 } 3491 break; 3492 3493 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned) 3494 // Same CR and OV rules as given for divweu above 3495 DIP("divdeu%s%s r%u,r%u,r%u\n", 3496 flag_OE ? "o" : "", flag_rC ? ".":"", 3497 rD_addr, rA_addr, rB_addr); 3498 assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) ); 3499 if (flag_OE) { 3500 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ), 3501 mkexpr( rA ), mkexpr( rB ) ); 3502 } 3503 break; 3504 3505 default: 3506 vex_printf("dis_int_arith(ppc)(opc2)\n"); 3507 return False; 3508 } 3509 break; 3510 3511 default: 3512 vex_printf("dis_int_arith(ppc)(opc1)\n"); 3513 return False; 3514 } 3515 3516 putIReg( rD_addr, mkexpr(rD) ); 3517 3518 if (do_rc && flag_rC) { 3519 set_CR0( mkexpr(rD) ); 3520 } 3521 return True; 3522} 3523 3524 3525 3526/* 3527 Integer Compare Instructions 3528*/ 3529static Bool dis_int_cmp ( UInt theInstr ) 3530{ 3531 /* D-Form, X-Form */ 3532 UChar opc1 = ifieldOPC(theInstr); 3533 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 3534 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) ); 3535 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) ); 3536 UChar rA_addr = ifieldRegA(theInstr); 3537 UInt uimm16 = ifieldUIMM16(theInstr); 3538 UChar rB_addr = ifieldRegB(theInstr); 3539 UInt opc2 = ifieldOPClo10(theInstr); 3540 UChar b0 = ifieldBIT0(theInstr); 3541 3542 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3543 IRExpr *a = getIReg(rA_addr); 3544 IRExpr *b; 3545 3546 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit. 3547 vex_printf("dis_int_cmp(ppc)(flag_L)\n"); 3548 return False; 3549 } 3550 3551 if (b22 != 0) { 3552 vex_printf("dis_int_cmp(ppc)(b22)\n"); 3553 return False; 3554 } 3555 3556 switch (opc1) { 3557 case 0x0B: // cmpi (Compare Immediate, PPC32 p368) 3558 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr, 3559 (Int)extend_s_16to32(uimm16)); 3560 b = mkSzExtendS16( ty, uimm16 ); 3561 if (flag_L == 1) { 3562 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 3563 } else { 3564 a = mkNarrowTo32( ty, a ); 3565 b = mkNarrowTo32( ty, b ); 3566 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b))); 3567 } 3568 putCR0( crfD, getXER_SO() ); 3569 break; 3570 3571 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370) 3572 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16); 3573 b = mkSzImm( ty, uimm16 ); 3574 if (flag_L == 1) { 3575 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 3576 } else { 3577 a = mkNarrowTo32( ty, a ); 3578 b = mkNarrowTo32( ty, b ); 3579 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 3580 } 3581 putCR0( crfD, getXER_SO() ); 3582 break; 3583 3584 /* X Form */ 3585 case 0x1F: 3586 if (b0 != 0) { 3587 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n"); 3588 return False; 3589 } 3590 b = getIReg(rB_addr); 3591 3592 switch (opc2) { 3593 case 0x000: // cmp (Compare, PPC32 p367) 3594 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 3595 /* Comparing a reg with itself produces a result which 3596 doesn't depend on the contents of the reg. Therefore 3597 remove the false dependency, which has been known to cause 3598 memcheck to produce false errors. */ 3599 if (rA_addr == rB_addr) 3600 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 3601 ? mkU64(0) : mkU32(0); 3602 if (flag_L == 1) { 3603 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 3604 } else { 3605 a = mkNarrowTo32( ty, a ); 3606 b = mkNarrowTo32( ty, b ); 3607 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b))); 3608 } 3609 putCR0( crfD, getXER_SO() ); 3610 break; 3611 3612 case 0x020: // cmpl (Compare Logical, PPC32 p369) 3613 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 3614 /* Comparing a reg with itself produces a result which 3615 doesn't depend on the contents of the reg. Therefore 3616 remove the false dependency, which has been known to cause 3617 memcheck to produce false errors. */ 3618 if (rA_addr == rB_addr) 3619 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 3620 ? mkU64(0) : mkU32(0); 3621 if (flag_L == 1) { 3622 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 3623 } else { 3624 a = mkNarrowTo32( ty, a ); 3625 b = mkNarrowTo32( ty, b ); 3626 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 3627 } 3628 putCR0( crfD, getXER_SO() ); 3629 break; 3630 3631 default: 3632 vex_printf("dis_int_cmp(ppc)(opc2)\n"); 3633 return False; 3634 } 3635 break; 3636 3637 default: 3638 vex_printf("dis_int_cmp(ppc)(opc1)\n"); 3639 return False; 3640 } 3641 3642 return True; 3643} 3644 3645 3646/* 3647 Integer Logical Instructions 3648*/ 3649static Bool dis_int_logic ( UInt theInstr ) 3650{ 3651 /* D-Form, X-Form */ 3652 UChar opc1 = ifieldOPC(theInstr); 3653 UChar rS_addr = ifieldRegDS(theInstr); 3654 UChar rA_addr = ifieldRegA(theInstr); 3655 UInt uimm16 = ifieldUIMM16(theInstr); 3656 UChar rB_addr = ifieldRegB(theInstr); 3657 UInt opc2 = ifieldOPClo10(theInstr); 3658 UChar flag_rC = ifieldBIT0(theInstr); 3659 3660 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3661 IRTemp rS = newTemp(ty); 3662 IRTemp rA = newTemp(ty); 3663 IRTemp rB = newTemp(ty); 3664 IRExpr* irx; 3665 Bool do_rc = False; 3666 3667 assign( rS, getIReg(rS_addr) ); 3668 assign( rB, getIReg(rB_addr) ); 3669 3670 switch (opc1) { 3671 case 0x1C: // andi. (AND Immediate, PPC32 p358) 3672 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3673 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 3674 mkSzImm(ty, uimm16)) ); 3675 do_rc = True; // Always record to CR 3676 flag_rC = 1; 3677 break; 3678 3679 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359) 3680 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3681 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 3682 mkSzImm(ty, uimm16 << 16)) ); 3683 do_rc = True; // Always record to CR 3684 flag_rC = 1; 3685 break; 3686 3687 case 0x18: // ori (OR Immediate, PPC32 p497) 3688 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3689 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 3690 mkSzImm(ty, uimm16)) ); 3691 break; 3692 3693 case 0x19: // oris (OR Immediate Shifted, PPC32 p498) 3694 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3695 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 3696 mkSzImm(ty, uimm16 << 16)) ); 3697 break; 3698 3699 case 0x1A: // xori (XOR Immediate, PPC32 p550) 3700 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3701 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 3702 mkSzImm(ty, uimm16)) ); 3703 break; 3704 3705 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551) 3706 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3707 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 3708 mkSzImm(ty, uimm16 << 16)) ); 3709 break; 3710 3711 /* X Form */ 3712 case 0x1F: 3713 do_rc = True; // All below record to CR, except for where we return at case end. 3714 3715 switch (opc2) { 3716 case 0x01C: // and (AND, PPC32 p356) 3717 DIP("and%s r%u,r%u,r%u\n", 3718 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3719 assign(rA, binop( mkSzOp(ty, Iop_And8), 3720 mkexpr(rS), mkexpr(rB))); 3721 break; 3722 3723 case 0x03C: // andc (AND with Complement, PPC32 p357) 3724 DIP("andc%s r%u,r%u,r%u\n", 3725 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3726 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 3727 unop( mkSzOp(ty, Iop_Not8), 3728 mkexpr(rB)))); 3729 break; 3730 3731 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371) 3732 IRExpr* lo32; 3733 if (rB_addr!=0) { 3734 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n"); 3735 return False; 3736 } 3737 DIP("cntlzw%s r%u,r%u\n", 3738 flag_rC ? ".":"", rA_addr, rS_addr); 3739 3740 // mode64: count in low word only 3741 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS); 3742 3743 // Iop_Clz32 undefined for arg==0, so deal with that case: 3744 irx = binop(Iop_CmpNE32, lo32, mkU32(0)); 3745 assign(rA, mkWidenFrom32(ty, 3746 IRExpr_Mux0X( unop(Iop_1Uto8, irx), 3747 mkU32(32), 3748 unop(Iop_Clz32, lo32)), 3749 False)); 3750 3751 // TODO: alternatively: assign(rA, verbose_Clz32(rS)); 3752 break; 3753 } 3754 3755 case 0x11C: // eqv (Equivalent, PPC32 p396) 3756 DIP("eqv%s r%u,r%u,r%u\n", 3757 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3758 assign( rA, unop( mkSzOp(ty, Iop_Not8), 3759 binop( mkSzOp(ty, Iop_Xor8), 3760 mkexpr(rS), mkexpr(rB))) ); 3761 break; 3762 3763 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397 3764 if (rB_addr!=0) { 3765 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n"); 3766 return False; 3767 } 3768 DIP("extsb%s r%u,r%u\n", 3769 flag_rC ? ".":"", rA_addr, rS_addr); 3770 if (mode64) 3771 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) ); 3772 else 3773 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) ); 3774 break; 3775 3776 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398) 3777 if (rB_addr!=0) { 3778 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n"); 3779 return False; 3780 } 3781 DIP("extsh%s r%u,r%u\n", 3782 flag_rC ? ".":"", rA_addr, rS_addr); 3783 if (mode64) 3784 assign( rA, unop(Iop_16Sto64, 3785 unop(Iop_64to16, mkexpr(rS))) ); 3786 else 3787 assign( rA, unop(Iop_16Sto32, 3788 unop(Iop_32to16, mkexpr(rS))) ); 3789 break; 3790 3791 case 0x1DC: // nand (NAND, PPC32 p492) 3792 DIP("nand%s r%u,r%u,r%u\n", 3793 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3794 assign( rA, unop( mkSzOp(ty, Iop_Not8), 3795 binop( mkSzOp(ty, Iop_And8), 3796 mkexpr(rS), mkexpr(rB))) ); 3797 break; 3798 3799 case 0x07C: // nor (NOR, PPC32 p494) 3800 DIP("nor%s r%u,r%u,r%u\n", 3801 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3802 assign( rA, unop( mkSzOp(ty, Iop_Not8), 3803 binop( mkSzOp(ty, Iop_Or8), 3804 mkexpr(rS), mkexpr(rB))) ); 3805 break; 3806 3807 case 0x1BC: // or (OR, PPC32 p495) 3808 if ((!flag_rC) && rS_addr == rB_addr) { 3809 DIP("mr r%u,r%u\n", rA_addr, rS_addr); 3810 assign( rA, mkexpr(rS) ); 3811 } else { 3812 DIP("or%s r%u,r%u,r%u\n", 3813 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3814 assign( rA, binop( mkSzOp(ty, Iop_Or8), 3815 mkexpr(rS), mkexpr(rB)) ); 3816 } 3817 break; 3818 3819 case 0x19C: // orc (OR with Complement, PPC32 p496) 3820 DIP("orc%s r%u,r%u,r%u\n", 3821 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3822 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 3823 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB)))); 3824 break; 3825 3826 case 0x13C: // xor (XOR, PPC32 p549) 3827 DIP("xor%s r%u,r%u,r%u\n", 3828 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3829 assign( rA, binop( mkSzOp(ty, Iop_Xor8), 3830 mkexpr(rS), mkexpr(rB)) ); 3831 break; 3832 3833 3834 /* 64bit Integer Logical Instructions */ 3835 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430) 3836 if (rB_addr!=0) { 3837 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n"); 3838 return False; 3839 } 3840 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr); 3841 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS)))); 3842 break; 3843 3844 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401) 3845 if (rB_addr!=0) { 3846 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n"); 3847 return False; 3848 } 3849 DIP("cntlzd%s r%u,r%u\n", 3850 flag_rC ? ".":"", rA_addr, rS_addr); 3851 // Iop_Clz64 undefined for arg==0, so deal with that case: 3852 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0)); 3853 assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx), 3854 mkU64(64), 3855 unop(Iop_Clz64, mkexpr(rS)) )); 3856 // TODO: alternatively: assign(rA, verbose_Clz64(rS)); 3857 break; 3858 3859 case 0x1FC: // cmpb (Power6: compare bytes) 3860 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 3861 3862 if (mode64) 3863 assign( rA, unop( Iop_V128to64, 3864 binop( Iop_CmpEQ8x16, 3865 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ), 3866 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) ) 3867 )) ); 3868 else 3869 assign( rA, unop( Iop_V128to32, 3870 binop( Iop_CmpEQ8x16, 3871 unop( Iop_32UtoV128, mkexpr(rS) ), 3872 unop( Iop_32UtoV128, mkexpr(rB) ) 3873 )) ); 3874 break; 3875 3876 case 0x2DF: { // mftgpr (move floating-point to general purpose register) 3877 IRTemp frB = newTemp(Ity_F64); 3878 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr); 3879 3880 assign( frB, getFReg(rB_addr)); // always F64 3881 if (mode64) 3882 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 3883 else 3884 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) ); 3885 3886 putIReg( rS_addr, mkexpr(rA)); 3887 return True; 3888 } 3889 3890 case 0x25F: { // mffgpr (move floating-point from general purpose register) 3891 IRTemp frA = newTemp(Ity_F64); 3892 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr); 3893 3894 if (mode64) 3895 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) ); 3896 else 3897 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) ); 3898 3899 putFReg( rS_addr, mkexpr(frA)); 3900 return True; 3901 } 3902 case 0x1FA: // popcntd (population count doubleword 3903 { 3904 DIP("popcntd r%u,r%u\n", rA_addr, rS_addr); 3905 IRTemp result = gen_POPCOUNT(ty, rS); 3906 putIReg( rA_addr, mkexpr(result) ); 3907 return True; 3908 } 3909 case 0x17A: // popcntw (Population Count Words) 3910 { 3911 DIP("popcntw r%u,r%u\n", rA_addr, rS_addr); 3912 if (mode64) { 3913 IRTemp resultHi, resultLo; 3914 IRTemp argLo = newTemp(Ity_I32); 3915 IRTemp argHi = newTemp(Ity_I32); 3916 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 3917 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 3918 resultLo = gen_POPCOUNT(Ity_I32, argLo); 3919 resultHi = gen_POPCOUNT(Ity_I32, argHi); 3920 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo))); 3921 } else { 3922 IRTemp result = gen_POPCOUNT(ty, rS); 3923 putIReg( rA_addr, mkexpr(result) ); 3924 } 3925 return True; 3926 } 3927 case 0x0FC: // bpermd (Bit Permute Doubleword) 3928 { 3929 /* This is a lot of rigmarole to emulate bpermd like this, as it 3930 * could be done much faster by implementing a call to the native 3931 * instruction. However, where possible I want to avoid using new 3932 * native instructions so that we can use valgrind to emulate those 3933 * instructions on older PPC64 hardware. 3934 */ 3935 #define BPERMD_IDX_MASK 0x00000000000000FFULL 3936 #define BPERMD_BIT_MASK 0x8000000000000000ULL 3937 int i; 3938 IRExpr * rS_expr = mkexpr(rS); 3939 IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0)); 3940 DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 3941 for (i = 0; i < 8; i++) { 3942 IRTemp idx_tmp = newTemp( Ity_I64 ); 3943 IRTemp perm_bit = newTemp( Ity_I64 ); 3944 IRTemp idx = newTemp( Ity_I8 ); 3945 IRTemp idx_LT64 = newTemp( Ity_I1 ); 3946 IRTemp idx_LT64_ity64 = newTemp( Ity_I64 ); 3947 3948 assign( idx_tmp, 3949 binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) ); 3950 assign( idx_LT64, 3951 binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) ); 3952 assign( idx, 3953 binop( Iop_And8, 3954 unop( Iop_1Sto8, 3955 mkexpr(idx_LT64) ), 3956 unop( Iop_64to8, mkexpr( idx_tmp ) ) ) ); 3957 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx 3958 * to determine which bit of rB to use for the perm bit, and then we shift 3959 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64 3960 * to set the final perm bit. 3961 */ 3962 assign( idx_LT64_ity64, 3963 unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) ); 3964 assign( perm_bit, 3965 binop( Iop_And64, 3966 mkexpr( idx_LT64_ity64 ), 3967 binop( Iop_Shr64, 3968 binop( Iop_And64, 3969 mkU64( BPERMD_BIT_MASK ), 3970 binop( Iop_Shl64, 3971 mkexpr( rB ), 3972 mkexpr( idx ) ) ), 3973 mkU8( 63 ) ) ) ); 3974 res = binop( Iop_Or64, 3975 res, 3976 binop( Iop_Shl64, 3977 mkexpr( perm_bit ), 3978 mkU8( i ) ) ); 3979 rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) ); 3980 } 3981 putIReg(rA_addr, res); 3982 return True; 3983 } 3984 3985 default: 3986 vex_printf("dis_int_logic(ppc)(opc2)\n"); 3987 return False; 3988 } 3989 break; 3990 3991 default: 3992 vex_printf("dis_int_logic(ppc)(opc1)\n"); 3993 return False; 3994 } 3995 3996 putIReg( rA_addr, mkexpr(rA) ); 3997 3998 if (do_rc && flag_rC) { 3999 set_CR0( mkexpr(rA) ); 4000 } 4001 return True; 4002} 4003 4004/* 4005 Integer Parity Instructions 4006*/ 4007static Bool dis_int_parity ( UInt theInstr ) 4008{ 4009 /* X-Form */ 4010 UChar opc1 = ifieldOPC(theInstr); 4011 UChar rS_addr = ifieldRegDS(theInstr); 4012 UChar rA_addr = ifieldRegA(theInstr); 4013 UChar rB_addr = ifieldRegB(theInstr); 4014 UInt opc2 = ifieldOPClo10(theInstr); 4015 UChar b0 = ifieldBIT0(theInstr); 4016 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4017 4018 IRTemp rS = newTemp(ty); 4019 IRTemp rA = newTemp(ty); 4020 IRTemp iTot1 = newTemp(Ity_I32); 4021 IRTemp iTot2 = newTemp(Ity_I32); 4022 IRTemp iTot3 = newTemp(Ity_I32); 4023 IRTemp iTot4 = newTemp(Ity_I32); 4024 IRTemp iTot5 = newTemp(Ity_I32); 4025 IRTemp iTot6 = newTemp(Ity_I32); 4026 IRTemp iTot7 = newTemp(Ity_I32); 4027 IRTemp iTot8 = newTemp(Ity_I32); 4028 IRTemp rS1 = newTemp(ty); 4029 IRTemp rS2 = newTemp(ty); 4030 IRTemp rS3 = newTemp(ty); 4031 IRTemp rS4 = newTemp(ty); 4032 IRTemp rS5 = newTemp(ty); 4033 IRTemp rS6 = newTemp(ty); 4034 IRTemp rS7 = newTemp(ty); 4035 IRTemp iHi = newTemp(Ity_I32); 4036 IRTemp iLo = newTemp(Ity_I32); 4037 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1); 4038 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32); 4039 4040 if (opc1 != 0x1f || rB_addr || b0) { 4041 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n"); 4042 return False; 4043 } 4044 4045 assign( rS, getIReg(rS_addr) ); 4046 4047 switch (opc2) { 4048 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320) 4049 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr); 4050 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4051 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4052 assign( iTot2, binop(Iop_Add32, 4053 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4054 mkexpr(iTot1)) ); 4055 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4056 assign( iTot3, binop(Iop_Add32, 4057 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4058 mkexpr(iTot2)) ); 4059 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4060 assign( iTot4, binop(Iop_Add32, 4061 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4062 mkexpr(iTot3)) ); 4063 if (mode64) { 4064 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4065 assign( iTot5, binop(Iop_Add32, 4066 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))), 4067 mkexpr(iTot4)) ); 4068 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4069 assign( iTot6, binop(Iop_Add32, 4070 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4071 mkexpr(iTot5)) ); 4072 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4073 assign( iTot7, binop(Iop_Add32, 4074 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4075 mkexpr(iTot6)) ); 4076 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) ); 4077 assign( iTot8, binop(Iop_Add32, 4078 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4079 mkexpr(iTot7)) ); 4080 assign( rA, unop(Iop_32Uto64, 4081 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) ); 4082 } else 4083 assign( rA, mkexpr(iTot4) ); 4084 4085 break; 4086 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320) 4087 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4088 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4089 assign( iTot2, binop(Iop_Add32, 4090 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4091 mkexpr(iTot1)) ); 4092 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4093 assign( iTot3, binop(Iop_Add32, 4094 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4095 mkexpr(iTot2)) ); 4096 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4097 assign( iTot4, binop(Iop_Add32, 4098 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4099 mkexpr(iTot3)) ); 4100 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) ); 4101 4102 if (mode64) { 4103 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4104 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) ); 4105 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4106 assign( iTot6, binop(Iop_Add32, 4107 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4108 mkexpr(iTot5)) ); 4109 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4110 assign( iTot7, binop(Iop_Add32, 4111 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4112 mkexpr(iTot6)) ); 4113 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8))); 4114 assign( iTot8, binop(Iop_Add32, 4115 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4116 mkexpr(iTot7)) ); 4117 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ), 4118 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) ); 4119 } else 4120 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) ); 4121 break; 4122 default: 4123 vex_printf("dis_int_parity(ppc)(opc2)\n"); 4124 return False; 4125 } 4126 4127 putIReg( rA_addr, mkexpr(rA) ); 4128 4129 return True; 4130} 4131 4132 4133/* 4134 Integer Rotate Instructions 4135*/ 4136static Bool dis_int_rot ( UInt theInstr ) 4137{ 4138 /* M-Form, MDS-Form */ 4139 UChar opc1 = ifieldOPC(theInstr); 4140 UChar rS_addr = ifieldRegDS(theInstr); 4141 UChar rA_addr = ifieldRegA(theInstr); 4142 UChar rB_addr = ifieldRegB(theInstr); 4143 UChar sh_imm = rB_addr; 4144 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) ); 4145 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) ); 4146 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) ); 4147 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) ); 4148 UChar b1 = ifieldBIT1(theInstr); 4149 UChar flag_rC = ifieldBIT0(theInstr); 4150 4151 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4152 IRTemp rS = newTemp(ty); 4153 IRTemp rA = newTemp(ty); 4154 IRTemp rB = newTemp(ty); 4155 IRTemp rot = newTemp(ty); 4156 IRExpr *r; 4157 UInt mask32; 4158 ULong mask64; 4159 4160 assign( rS, getIReg(rS_addr) ); 4161 assign( rB, getIReg(rB_addr) ); 4162 4163 switch (opc1) { 4164 case 0x14: { 4165 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500) 4166 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4167 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4168 if (mode64) { 4169 // tmp32 = (ROTL(rS_Lo32, Imm) 4170 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64) 4171 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4172 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4173 r = unop(Iop_32Uto64, r); 4174 assign( rot, binop(Iop_Or64, r, 4175 binop(Iop_Shl64, r, mkU8(32))) ); 4176 assign( rA, 4177 binop(Iop_Or64, 4178 binop(Iop_And64, mkexpr(rot), mkU64(mask64)), 4179 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) ); 4180 } 4181 else { 4182 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask); 4183 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4184 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4185 assign( rA, 4186 binop(Iop_Or32, 4187 binop(Iop_And32, mkU32(mask32), r), 4188 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) ); 4189 } 4190 break; 4191 } 4192 4193 case 0x15: { 4194 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501) 4195 vassert(MaskBeg < 32); 4196 vassert(MaskEnd < 32); 4197 vassert(sh_imm < 32); 4198 4199 if (mode64) { 4200 IRTemp rTmp = newTemp(Ity_I64); 4201 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4202 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4203 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4204 // tmp32 = (ROTL(rS_Lo32, Imm) 4205 // rA = ((tmp32 || tmp32) & mask64) 4206 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4207 r = unop(Iop_32Uto64, r); 4208 assign( rTmp, r ); 4209 r = NULL; 4210 assign( rot, binop(Iop_Or64, mkexpr(rTmp), 4211 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) ); 4212 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4213 } 4214 else { 4215 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) { 4216 /* Special-case the ,n,0,31-n form as that is just n-bit 4217 shift left, PPC32 p501 */ 4218 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4219 rA_addr, rS_addr, sh_imm); 4220 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) ); 4221 } 4222 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) { 4223 /* Special-case the ,32-n,n,31 form as that is just n-bit 4224 unsigned shift right, PPC32 p501 */ 4225 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4226 rA_addr, rS_addr, MaskBeg); 4227 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) ); 4228 } 4229 else { 4230 /* General case. */ 4231 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4232 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4233 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4234 // rA = ROTL(rS, Imm) & mask 4235 assign( rA, binop(Iop_And32, 4236 ROTL(mkexpr(rS), mkU8(sh_imm)), 4237 mkU32(mask32)) ); 4238 } 4239 } 4240 break; 4241 } 4242 4243 case 0x17: { 4244 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503 4245 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"", 4246 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd); 4247 if (mode64) { 4248 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4249 /* weird insn alert! 4250 tmp32 = (ROTL(rS_Lo32, rB[0-4]) 4251 rA = ((tmp32 || tmp32) & mask64) 4252 */ 4253 // note, ROTL does the masking, so we don't do it here 4254 r = ROTL( unop(Iop_64to32, mkexpr(rS)), 4255 unop(Iop_64to8, mkexpr(rB)) ); 4256 r = unop(Iop_32Uto64, r); 4257 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)))); 4258 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4259 } else { 4260 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4261 // rA = ROTL(rS, rB[0-4]) & mask 4262 // note, ROTL does the masking, so we don't do it here 4263 assign( rA, binop(Iop_And32, 4264 ROTL(mkexpr(rS), 4265 unop(Iop_32to8, mkexpr(rB))), 4266 mkU32(mask32)) ); 4267 } 4268 break; 4269 } 4270 4271 /* 64bit Integer Rotates */ 4272 case 0x1E: { 4273 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1); 4274 sh_imm |= b1 << 5; 4275 4276 vassert( msk_imm < 64 ); 4277 vassert( sh_imm < 64 ); 4278 4279 switch (opc2) { 4280 case 0x4: { 4281 /* r = ROTL64( rS, rB_lo6) */ 4282 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) ); 4283 4284 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555) 4285 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4286 rA_addr, rS_addr, rB_addr, msk_imm); 4287 // note, ROTL does the masking, so we don't do it here 4288 mask64 = MASK64(0, 63-msk_imm); 4289 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4290 break; 4291 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556) 4292 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4293 rA_addr, rS_addr, rB_addr, msk_imm); 4294 mask64 = MASK64(63-msk_imm, 63); 4295 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4296 break; 4297 } 4298 break; 4299 } 4300 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557) 4301 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4302 rA_addr, rS_addr, sh_imm, msk_imm); 4303 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4304 mask64 = MASK64(sh_imm, 63-msk_imm); 4305 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4306 break; 4307 // later: deal with special case: (msk_imm==0) => SHL(sh_imm) 4308 /* 4309 Hmm... looks like this'll do the job more simply: 4310 r = SHL(rS, sh_imm) 4311 m = ~(1 << (63-msk_imm)) 4312 assign(rA, r & m); 4313 */ 4314 4315 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558) 4316 if (mode64 4317 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) { 4318 /* special-case the ,64-n,n form as that is just 4319 unsigned shift-right by n */ 4320 DIP("srdi%s r%u,r%u,%u\n", 4321 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm); 4322 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) ); 4323 } else { 4324 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4325 rA_addr, rS_addr, sh_imm, msk_imm); 4326 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4327 mask64 = MASK64(0, 63-msk_imm); 4328 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4329 } 4330 break; 4331 4332 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559) 4333 if (mode64 4334 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) { 4335 /* special-case the ,n,63-n form as that is just 4336 shift-left by n */ 4337 DIP("sldi%s r%u,r%u,%u\n", 4338 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 4339 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) ); 4340 } else { 4341 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4342 rA_addr, rS_addr, sh_imm, msk_imm); 4343 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4344 mask64 = MASK64(63-msk_imm, 63); 4345 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4346 } 4347 break; 4348 4349 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560) 4350 IRTemp rA_orig = newTemp(ty); 4351 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4352 rA_addr, rS_addr, sh_imm, msk_imm); 4353 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4354 mask64 = MASK64(sh_imm, 63-msk_imm); 4355 assign( rA_orig, getIReg(rA_addr) ); 4356 assign( rA, binop(Iop_Or64, 4357 binop(Iop_And64, mkU64(mask64), r), 4358 binop(Iop_And64, mkU64(~mask64), 4359 mkexpr(rA_orig))) ); 4360 break; 4361 } 4362 default: 4363 vex_printf("dis_int_rot(ppc)(opc2)\n"); 4364 return False; 4365 } 4366 break; 4367 } 4368 4369 default: 4370 vex_printf("dis_int_rot(ppc)(opc1)\n"); 4371 return False; 4372 } 4373 4374 putIReg( rA_addr, mkexpr(rA) ); 4375 4376 if (flag_rC) { 4377 set_CR0( mkexpr(rA) ); 4378 } 4379 return True; 4380} 4381 4382 4383/* 4384 Integer Load Instructions 4385*/ 4386static Bool dis_int_load ( UInt theInstr ) 4387{ 4388 /* D-Form, X-Form, DS-Form */ 4389 UChar opc1 = ifieldOPC(theInstr); 4390 UChar rD_addr = ifieldRegDS(theInstr); 4391 UChar rA_addr = ifieldRegA(theInstr); 4392 UInt uimm16 = ifieldUIMM16(theInstr); 4393 UChar rB_addr = ifieldRegB(theInstr); 4394 UInt opc2 = ifieldOPClo10(theInstr); 4395 UChar b1 = ifieldBIT1(theInstr); 4396 UChar b0 = ifieldBIT0(theInstr); 4397 4398 Int simm16 = extend_s_16to32(uimm16); 4399 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4400 IRTemp EA = newTemp(ty); 4401 IRExpr* val; 4402 4403 switch (opc1) { 4404 case 0x1F: // register offset 4405 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 4406 break; 4407 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off 4408 // lowest 2 bits of immediate before forming EA 4409 simm16 = simm16 & 0xFFFFFFFC; 4410 default: // immediate offset 4411 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4412 break; 4413 } 4414 4415 switch (opc1) { 4416 case 0x22: // lbz (Load B & Zero, PPC32 p433) 4417 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4418 val = loadBE(Ity_I8, mkexpr(EA)); 4419 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4420 break; 4421 4422 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434) 4423 if (rA_addr == 0 || rA_addr == rD_addr) { 4424 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n"); 4425 return False; 4426 } 4427 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4428 val = loadBE(Ity_I8, mkexpr(EA)); 4429 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4430 putIReg( rA_addr, mkexpr(EA) ); 4431 break; 4432 4433 case 0x2A: // lha (Load HW Alg, PPC32 p445) 4434 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4435 val = loadBE(Ity_I16, mkexpr(EA)); 4436 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4437 break; 4438 4439 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446) 4440 if (rA_addr == 0 || rA_addr == rD_addr) { 4441 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n"); 4442 return False; 4443 } 4444 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4445 val = loadBE(Ity_I16, mkexpr(EA)); 4446 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4447 putIReg( rA_addr, mkexpr(EA) ); 4448 break; 4449 4450 case 0x28: // lhz (Load HW & Zero, PPC32 p450) 4451 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4452 val = loadBE(Ity_I16, mkexpr(EA)); 4453 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4454 break; 4455 4456 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451) 4457 if (rA_addr == 0 || rA_addr == rD_addr) { 4458 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n"); 4459 return False; 4460 } 4461 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4462 val = loadBE(Ity_I16, mkexpr(EA)); 4463 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4464 putIReg( rA_addr, mkexpr(EA) ); 4465 break; 4466 4467 case 0x20: // lwz (Load W & Zero, PPC32 p460) 4468 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4469 val = loadBE(Ity_I32, mkexpr(EA)); 4470 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4471 break; 4472 4473 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461)) 4474 if (rA_addr == 0 || rA_addr == rD_addr) { 4475 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n"); 4476 return False; 4477 } 4478 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4479 val = loadBE(Ity_I32, mkexpr(EA)); 4480 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4481 putIReg( rA_addr, mkexpr(EA) ); 4482 break; 4483 4484 /* X Form */ 4485 case 0x1F: 4486 if (b0 != 0) { 4487 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n"); 4488 return False; 4489 } 4490 4491 switch (opc2) { 4492 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435) 4493 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4494 if (rA_addr == 0 || rA_addr == rD_addr) { 4495 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 4496 return False; 4497 } 4498 val = loadBE(Ity_I8, mkexpr(EA)); 4499 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4500 putIReg( rA_addr, mkexpr(EA) ); 4501 break; 4502 4503 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436) 4504 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4505 val = loadBE(Ity_I8, mkexpr(EA)); 4506 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4507 break; 4508 4509 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447) 4510 if (rA_addr == 0 || rA_addr == rD_addr) { 4511 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n"); 4512 return False; 4513 } 4514 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4515 val = loadBE(Ity_I16, mkexpr(EA)); 4516 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4517 putIReg( rA_addr, mkexpr(EA) ); 4518 break; 4519 4520 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448) 4521 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4522 val = loadBE(Ity_I16, mkexpr(EA)); 4523 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4524 break; 4525 4526 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452) 4527 if (rA_addr == 0 || rA_addr == rD_addr) { 4528 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n"); 4529 return False; 4530 } 4531 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4532 val = loadBE(Ity_I16, mkexpr(EA)); 4533 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4534 putIReg( rA_addr, mkexpr(EA) ); 4535 break; 4536 4537 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453) 4538 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4539 val = loadBE(Ity_I16, mkexpr(EA)); 4540 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4541 break; 4542 4543 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462) 4544 if (rA_addr == 0 || rA_addr == rD_addr) { 4545 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 4546 return False; 4547 } 4548 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4549 val = loadBE(Ity_I32, mkexpr(EA)); 4550 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4551 putIReg( rA_addr, mkexpr(EA) ); 4552 break; 4553 4554 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463) 4555 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4556 val = loadBE(Ity_I32, mkexpr(EA)); 4557 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4558 break; 4559 4560 4561 /* 64bit Loads */ 4562 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475) 4563 if (rA_addr == 0 || rA_addr == rD_addr) { 4564 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n"); 4565 return False; 4566 } 4567 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4568 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4569 putIReg( rA_addr, mkexpr(EA) ); 4570 break; 4571 4572 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476) 4573 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4574 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4575 break; 4576 4577 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501) 4578 if (rA_addr == 0 || rA_addr == rD_addr) { 4579 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n"); 4580 return False; 4581 } 4582 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4583 putIReg( rD_addr, 4584 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 4585 putIReg( rA_addr, mkexpr(EA) ); 4586 break; 4587 4588 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502) 4589 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4590 putIReg( rD_addr, 4591 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 4592 break; 4593 4594 default: 4595 vex_printf("dis_int_load(ppc)(opc2)\n"); 4596 return False; 4597 } 4598 break; 4599 4600 /* DS Form - 64bit Loads. In each case EA will have been formed 4601 with the lowest 2 bits masked off the immediate offset. */ 4602 case 0x3A: 4603 switch ((b1<<1) | b0) { 4604 case 0x0: // ld (Load DWord, PPC64 p472) 4605 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4606 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4607 break; 4608 4609 case 0x1: // ldu (Load DWord, Update, PPC64 p474) 4610 if (rA_addr == 0 || rA_addr == rD_addr) { 4611 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n"); 4612 return False; 4613 } 4614 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4615 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4616 putIReg( rA_addr, mkexpr(EA) ); 4617 break; 4618 4619 case 0x2: // lwa (Load Word Alg, PPC64 p499) 4620 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4621 putIReg( rD_addr, 4622 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 4623 break; 4624 4625 default: 4626 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 4627 return False; 4628 } 4629 break; 4630 4631 default: 4632 vex_printf("dis_int_load(ppc)(opc1)\n"); 4633 return False; 4634 } 4635 return True; 4636} 4637 4638 4639 4640/* 4641 Integer Store Instructions 4642*/ 4643static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi ) 4644{ 4645 /* D-Form, X-Form, DS-Form */ 4646 UChar opc1 = ifieldOPC(theInstr); 4647 UInt rS_addr = ifieldRegDS(theInstr); 4648 UInt rA_addr = ifieldRegA(theInstr); 4649 UInt uimm16 = ifieldUIMM16(theInstr); 4650 UInt rB_addr = ifieldRegB(theInstr); 4651 UInt opc2 = ifieldOPClo10(theInstr); 4652 UChar b1 = ifieldBIT1(theInstr); 4653 UChar b0 = ifieldBIT0(theInstr); 4654 4655 Int simm16 = extend_s_16to32(uimm16); 4656 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4657 IRTemp rS = newTemp(ty); 4658 IRTemp rB = newTemp(ty); 4659 IRTemp EA = newTemp(ty); 4660 4661 assign( rB, getIReg(rB_addr) ); 4662 assign( rS, getIReg(rS_addr) ); 4663 4664 switch (opc1) { 4665 case 0x1F: // register offset 4666 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 4667 break; 4668 case 0x3E: // immediate offset: 64bit: std/stdu: mask off 4669 // lowest 2 bits of immediate before forming EA 4670 simm16 = simm16 & 0xFFFFFFFC; 4671 default: // immediate offset 4672 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4673 break; 4674 } 4675 4676 switch (opc1) { 4677 case 0x26: // stb (Store B, PPC32 p509) 4678 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4679 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 4680 break; 4681 4682 case 0x27: // stbu (Store B, Update, PPC32 p510) 4683 if (rA_addr == 0 ) { 4684 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n"); 4685 return False; 4686 } 4687 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4688 putIReg( rA_addr, mkexpr(EA) ); 4689 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 4690 break; 4691 4692 case 0x2C: // sth (Store HW, PPC32 p522) 4693 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4694 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 4695 break; 4696 4697 case 0x2D: // sthu (Store HW, Update, PPC32 p524) 4698 if (rA_addr == 0) { 4699 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n"); 4700 return False; 4701 } 4702 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4703 putIReg( rA_addr, mkexpr(EA) ); 4704 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 4705 break; 4706 4707 case 0x24: // stw (Store W, PPC32 p530) 4708 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4709 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 4710 break; 4711 4712 case 0x25: // stwu (Store W, Update, PPC32 p534) 4713 if (rA_addr == 0) { 4714 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n"); 4715 return False; 4716 } 4717 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4718 putIReg( rA_addr, mkexpr(EA) ); 4719 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 4720 break; 4721 4722 /* X Form : all these use EA_indexed */ 4723 case 0x1F: 4724 if (b0 != 0) { 4725 vex_printf("dis_int_store(ppc)(0x1F,b0)\n"); 4726 return False; 4727 } 4728 4729 switch (opc2) { 4730 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511) 4731 if (rA_addr == 0) { 4732 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n"); 4733 return False; 4734 } 4735 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4736 putIReg( rA_addr, mkexpr(EA) ); 4737 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 4738 break; 4739 4740 case 0x0D7: // stbx (Store B Indexed, PPC32 p512) 4741 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4742 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 4743 break; 4744 4745 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525) 4746 if (rA_addr == 0) { 4747 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n"); 4748 return False; 4749 } 4750 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4751 putIReg( rA_addr, mkexpr(EA) ); 4752 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 4753 break; 4754 4755 case 0x197: // sthx (Store HW Indexed, PPC32 p526) 4756 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4757 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 4758 break; 4759 4760 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535) 4761 if (rA_addr == 0) { 4762 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n"); 4763 return False; 4764 } 4765 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4766 putIReg( rA_addr, mkexpr(EA) ); 4767 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 4768 break; 4769 4770 case 0x097: // stwx (Store W Indexed, PPC32 p536) 4771 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4772 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 4773 break; 4774 4775 4776 /* 64bit Stores */ 4777 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584) 4778 if (rA_addr == 0) { 4779 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n"); 4780 return False; 4781 } 4782 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4783 putIReg( rA_addr, mkexpr(EA) ); 4784 storeBE( mkexpr(EA), mkexpr(rS) ); 4785 break; 4786 4787 case 0x095: // stdx (Store DWord Indexed, PPC64 p585) 4788 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4789 storeBE( mkexpr(EA), mkexpr(rS) ); 4790 break; 4791 4792 default: 4793 vex_printf("dis_int_store(ppc)(opc2)\n"); 4794 return False; 4795 } 4796 break; 4797 4798 /* DS Form - 64bit Stores. In each case EA will have been formed 4799 with the lowest 2 bits masked off the immediate offset. */ 4800 case 0x3E: 4801 switch ((b1<<1) | b0) { 4802 case 0x0: // std (Store DWord, PPC64 p580) 4803 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4804 storeBE( mkexpr(EA), mkexpr(rS) ); 4805 break; 4806 4807 case 0x1: // stdu (Store DWord, Update, PPC64 p583) 4808 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4809 putIReg( rA_addr, mkexpr(EA) ); 4810 storeBE( mkexpr(EA), mkexpr(rS) ); 4811 break; 4812 4813 default: 4814 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 4815 return False; 4816 } 4817 break; 4818 4819 default: 4820 vex_printf("dis_int_store(ppc)(opc1)\n"); 4821 return False; 4822 } 4823 return True; 4824} 4825 4826 4827 4828/* 4829 Integer Load/Store Multiple Instructions 4830*/ 4831static Bool dis_int_ldst_mult ( UInt theInstr ) 4832{ 4833 /* D-Form */ 4834 UChar opc1 = ifieldOPC(theInstr); 4835 UChar rD_addr = ifieldRegDS(theInstr); 4836 UChar rS_addr = rD_addr; 4837 UChar rA_addr = ifieldRegA(theInstr); 4838 UInt uimm16 = ifieldUIMM16(theInstr); 4839 4840 Int simm16 = extend_s_16to32(uimm16); 4841 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4842 IRTemp EA = newTemp(ty); 4843 UInt r = 0; 4844 UInt ea_off = 0; 4845 IRExpr* irx_addr; 4846 4847 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4848 4849 switch (opc1) { 4850 case 0x2E: // lmw (Load Multiple Word, PPC32 p454) 4851 if (rA_addr >= rD_addr) { 4852 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n"); 4853 return False; 4854 } 4855 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4856 for (r = rD_addr; r <= 31; r++) { 4857 irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off)); 4858 putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ), 4859 False) ); 4860 ea_off += 4; 4861 } 4862 break; 4863 4864 case 0x2F: // stmw (Store Multiple Word, PPC32 p527) 4865 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4866 for (r = rS_addr; r <= 31; r++) { 4867 irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off)); 4868 storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) ); 4869 ea_off += 4; 4870 } 4871 break; 4872 4873 default: 4874 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n"); 4875 return False; 4876 } 4877 return True; 4878} 4879 4880 4881 4882/* 4883 Integer Load/Store String Instructions 4884*/ 4885static 4886void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 4887 IRTemp EA, // EA 4888 Int rD, // first dst register 4889 Int maxBytes ) // 32 or 128 4890{ 4891 Int i, shift = 24; 4892 IRExpr* e_nbytes = mkexpr(tNBytes); 4893 IRExpr* e_EA = mkexpr(EA); 4894 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4895 4896 vassert(rD >= 0 && rD < 32); 4897 rD--; if (rD < 0) rD = 31; 4898 4899 for (i = 0; i < maxBytes; i++) { 4900 /* if (nBytes < (i+1)) goto NIA; */ 4901 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 4902 Ijk_Boring, 4903 mkSzConst( ty, nextInsnAddr()) )); 4904 /* when crossing into a new dest register, set it to zero. */ 4905 if ((i % 4) == 0) { 4906 rD++; if (rD == 32) rD = 0; 4907 putIReg(rD, mkSzImm(ty, 0)); 4908 shift = 24; 4909 } 4910 /* rD |= (8Uto32(*(EA+i))) << shift */ 4911 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 4912 putIReg( 4913 rD, 4914 mkWidenFrom32( 4915 ty, 4916 binop( 4917 Iop_Or32, 4918 mkNarrowTo32(ty, getIReg(rD)), 4919 binop( 4920 Iop_Shl32, 4921 unop( 4922 Iop_8Uto32, 4923 loadBE(Ity_I8, 4924 binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i))) 4925 ), 4926 mkU8(toUChar(shift)) 4927 ) 4928 ), 4929 /*Signed*/False 4930 ) 4931 ); 4932 shift -= 8; 4933 } 4934} 4935 4936static 4937void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 4938 IRTemp EA, // EA 4939 Int rS, // first src register 4940 Int maxBytes ) // 32 or 128 4941{ 4942 Int i, shift = 24; 4943 IRExpr* e_nbytes = mkexpr(tNBytes); 4944 IRExpr* e_EA = mkexpr(EA); 4945 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4946 4947 vassert(rS >= 0 && rS < 32); 4948 rS--; if (rS < 0) rS = 31; 4949 4950 for (i = 0; i < maxBytes; i++) { 4951 /* if (nBytes < (i+1)) goto NIA; */ 4952 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 4953 Ijk_Boring, 4954 mkSzConst( ty, nextInsnAddr() ) )); 4955 /* check for crossing into a new src register. */ 4956 if ((i % 4) == 0) { 4957 rS++; if (rS == 32) rS = 0; 4958 shift = 24; 4959 } 4960 /* *(EA+i) = 32to8(rS >> shift) */ 4961 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 4962 storeBE( 4963 binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)), 4964 unop(Iop_32to8, 4965 binop(Iop_Shr32, 4966 mkNarrowTo32(ty, getIReg(rS)), 4967 mkU8(toUChar(shift)))) 4968 ); 4969 shift -= 8; 4970 } 4971} 4972 4973static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) 4974{ 4975 /* X-Form */ 4976 UChar opc1 = ifieldOPC(theInstr); 4977 UChar rD_addr = ifieldRegDS(theInstr); 4978 UChar rS_addr = rD_addr; 4979 UChar rA_addr = ifieldRegA(theInstr); 4980 UChar rB_addr = ifieldRegB(theInstr); 4981 UChar NumBytes = rB_addr; 4982 UInt opc2 = ifieldOPClo10(theInstr); 4983 UChar b0 = ifieldBIT0(theInstr); 4984 4985 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4986 IRTemp t_EA = newTemp(ty); 4987 IRTemp t_nbytes = IRTemp_INVALID; 4988 4989 *stopHere = False; 4990 4991 if (opc1 != 0x1F || b0 != 0) { 4992 vex_printf("dis_int_ldst_str(ppc)(opc1)\n"); 4993 return False; 4994 } 4995 4996 switch (opc2) { 4997 case 0x255: // lswi (Load String Word Immediate, PPC32 p455) 4998 /* NB: does not reject the case where RA is in the range of 4999 registers to be loaded. It should. */ 5000 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes); 5001 assign( t_EA, ea_rAor0(rA_addr) ); 5002 if (NumBytes == 8 && !mode64) { 5003 /* Special case hack */ 5004 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */ 5005 putIReg( rD_addr, 5006 loadBE(Ity_I32, mkexpr(t_EA)) ); 5007 putIReg( (rD_addr+1) % 32, 5008 loadBE(Ity_I32, 5009 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) ); 5010 } else { 5011 t_nbytes = newTemp(Ity_I32); 5012 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5013 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5014 *stopHere = True; 5015 } 5016 return True; 5017 5018 case 0x215: // lswx (Load String Word Indexed, PPC32 p456) 5019 /* NB: does not reject the case where RA is in the range of 5020 registers to be loaded. It should. Although considering 5021 that that can only be detected at run time, it's not easy to 5022 do so. */ 5023 if (rD_addr == rA_addr || rD_addr == rB_addr) 5024 return False; 5025 if (rD_addr == 0 && rA_addr == 0) 5026 return False; 5027 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5028 t_nbytes = newTemp(Ity_I32); 5029 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5030 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5031 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 ); 5032 *stopHere = True; 5033 return True; 5034 5035 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528) 5036 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes); 5037 assign( t_EA, ea_rAor0(rA_addr) ); 5038 if (NumBytes == 8 && !mode64) { 5039 /* Special case hack */ 5040 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */ 5041 storeBE( mkexpr(t_EA), 5042 getIReg(rD_addr) ); 5043 storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)), 5044 getIReg((rD_addr+1) % 32) ); 5045 } else { 5046 t_nbytes = newTemp(Ity_I32); 5047 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5048 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5049 *stopHere = True; 5050 } 5051 return True; 5052 5053 case 0x295: // stswx (Store String Word Indexed, PPC32 p529) 5054 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5055 t_nbytes = newTemp(Ity_I32); 5056 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5057 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5058 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 ); 5059 *stopHere = True; 5060 return True; 5061 5062 default: 5063 vex_printf("dis_int_ldst_str(ppc)(opc2)\n"); 5064 return False; 5065 } 5066 return True; 5067} 5068 5069 5070/* ------------------------------------------------------------------ 5071 Integer Branch Instructions 5072 ------------------------------------------------------------------ */ 5073 5074/* 5075 Branch helper function 5076 ok = BO[2] | ((CTR[0] != 0) ^ BO[1]) 5077 Returns an I32 which is 0x00000000 if the ctr condition failed 5078 and 0xFFFFFFFF otherwise. 5079*/ 5080static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO ) 5081{ 5082 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5083 IRTemp ok = newTemp(Ity_I32); 5084 5085 if ((BO >> 2) & 1) { // independent of ctr 5086 assign( ok, mkU32(0xFFFFFFFF) ); 5087 } else { 5088 if ((BO >> 1) & 1) { // ctr == 0 ? 5089 assign( ok, unop( Iop_1Sto32, 5090 binop( mkSzOp(ty, Iop_CmpEQ8), 5091 getGST( PPC_GST_CTR ), 5092 mkSzImm(ty,0))) ); 5093 } else { // ctr != 0 ? 5094 assign( ok, unop( Iop_1Sto32, 5095 binop( mkSzOp(ty, Iop_CmpNE8), 5096 getGST( PPC_GST_CTR ), 5097 mkSzImm(ty,0))) ); 5098 } 5099 } 5100 return mkexpr(ok); 5101} 5102 5103 5104/* 5105 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3]) 5106 Returns an I32 which is either 0 if the condition failed or 5107 some arbitrary nonzero value otherwise. */ 5108 5109static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) 5110{ 5111 Int where; 5112 IRTemp res = newTemp(Ity_I32); 5113 IRTemp cr_bi = newTemp(Ity_I32); 5114 5115 if ((BO >> 4) & 1) { 5116 assign( res, mkU32(1) ); 5117 } else { 5118 // ok = (CR[BI] == BO[3]) Note, the following relies on 5119 // getCRbit_anywhere returning a value which 5120 // is either zero or has exactly 1 bit set. 5121 assign( cr_bi, getCRbit_anywhere( BI, &where ) ); 5122 5123 if ((BO >> 3) & 1) { 5124 /* We can use cr_bi as-is. */ 5125 assign( res, mkexpr(cr_bi) ); 5126 } else { 5127 /* We have to invert the sense of the information held in 5128 cr_bi. For that we need to know which bit 5129 getCRbit_anywhere regards as significant. */ 5130 assign( res, binop(Iop_Xor32, mkexpr(cr_bi), 5131 mkU32(1<<where)) ); 5132 } 5133 } 5134 return mkexpr(res); 5135} 5136 5137 5138/* 5139 Integer Branch Instructions 5140*/ 5141static Bool dis_branch ( UInt theInstr, 5142 VexAbiInfo* vbi, 5143 /*OUT*/DisResult* dres, 5144 Bool (*resteerOkFn)(void*,Addr64), 5145 void* callback_opaque ) 5146{ 5147 UChar opc1 = ifieldOPC(theInstr); 5148 UChar BO = ifieldRegDS(theInstr); 5149 UChar BI = ifieldRegA(theInstr); 5150 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */ 5151 UChar b11to15 = ifieldRegB(theInstr); 5152 UInt opc2 = ifieldOPClo10(theInstr); 5153 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */ 5154 UChar flag_AA = ifieldBIT1(theInstr); 5155 UChar flag_LK = ifieldBIT0(theInstr); 5156 5157 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5158 Addr64 tgt = 0; 5159 Int BD = extend_s_16to32(BD_u16); 5160 IRTemp do_branch = newTemp(Ity_I32); 5161 IRTemp ctr_ok = newTemp(Ity_I32); 5162 IRTemp cond_ok = newTemp(Ity_I32); 5163 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr()); 5164 IRConst* c_nia = mkSzConst(ty, nextInsnAddr()); 5165 IRTemp lr_old = newTemp(ty); 5166 5167 /* Hack to pass through code that just wants to read the PC */ 5168 if (theInstr == 0x429F0005) { 5169 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI); 5170 putGST( PPC_GST_LR, e_nia ); 5171 return True; 5172 } 5173 5174 /* The default what-next. Individual cases can override it. */ 5175 dres->whatNext = Dis_StopHere; 5176 5177 switch (opc1) { 5178 case 0x12: // b (Branch, PPC32 p360) 5179 if (flag_AA) { 5180 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) ); 5181 } else { 5182 tgt = mkSzAddr( ty, guest_CIA_curr_instr + 5183 (Long)extend_s_26to64(LI_u26) ); 5184 } 5185 if (mode64) { 5186 DIP("b%s%s 0x%llx\n", 5187 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt); 5188 } else { 5189 DIP("b%s%s 0x%x\n", 5190 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt); 5191 } 5192 5193 if (flag_LK) { 5194 putGST( PPC_GST_LR, e_nia ); 5195 if (vbi->guest_ppc_zap_RZ_at_bl 5196 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) { 5197 IRTemp t_tgt = newTemp(ty); 5198 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) ); 5199 make_redzone_AbiHint( vbi, t_tgt, 5200 "branch-and-link (unconditional call)" ); 5201 } 5202 } 5203 5204 if (resteerOkFn( callback_opaque, tgt )) { 5205 dres->whatNext = Dis_ResteerU; 5206 dres->continueAt = tgt; 5207 } else { 5208 irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring; 5209 irsb->next = mkSzImm(ty, tgt); 5210 } 5211 break; 5212 5213 case 0x10: // bc (Branch Conditional, PPC32 p361) 5214 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", 5215 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); 5216 5217 if (!(BO & 0x4)) { 5218 putGST( PPC_GST_CTR, 5219 binop(mkSzOp(ty, Iop_Sub8), 5220 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5221 } 5222 5223 /* This is a bit subtle. ctr_ok is either all 0s or all 1s. 5224 cond_ok is either zero or nonzero, since that's the cheapest 5225 way to compute it. Anding them together gives a value which 5226 is either zero or non zero and so that's what we must test 5227 for in the IRStmt_Exit. */ 5228 assign( ctr_ok, branch_ctr_ok( BO ) ); 5229 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5230 assign( do_branch, 5231 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5232 5233 if (flag_AA) { 5234 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16)); 5235 } else { 5236 tgt = mkSzAddr(ty, guest_CIA_curr_instr + 5237 (Long)extend_s_16to64(BD_u16)); 5238 } 5239 if (flag_LK) 5240 putGST( PPC_GST_LR, e_nia ); 5241 5242 stmt( IRStmt_Exit( 5243 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)), 5244 flag_LK ? Ijk_Call : Ijk_Boring, 5245 mkSzConst(ty, tgt) ) ); 5246 5247 irsb->jumpkind = Ijk_Boring; 5248 irsb->next = e_nia; 5249 break; 5250 5251 case 0x13: 5252 /* For bclr and bcctr, it appears that the lowest two bits of 5253 b11to15 are a branch hint, and so we only need to ensure it's 5254 of the form 000XX. */ 5255 if ((b11to15 & ~3) != 0) { 5256 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15); 5257 return False; 5258 } 5259 5260 switch (opc2) { 5261 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363) 5262 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid 5263 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n"); 5264 return False; 5265 } 5266 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5267 5268 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5269 5270 /* FIXME: this is confusing. lr_old holds the old value 5271 of ctr, not lr :-) */ 5272 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 )); 5273 5274 if (flag_LK) 5275 putGST( PPC_GST_LR, e_nia ); 5276 5277 stmt( IRStmt_Exit( 5278 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)), 5279 Ijk_Boring, 5280 c_nia )); 5281 5282 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) { 5283 make_redzone_AbiHint( vbi, lr_old, 5284 "b-ctr-l (indirect call)" ); 5285 } 5286 5287 irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring; 5288 irsb->next = mkexpr(lr_old); 5289 break; 5290 5291 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365) 5292 Bool vanilla_return = False; 5293 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) { 5294 DIP("blr\n"); 5295 vanilla_return = True; 5296 } else { 5297 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5298 } 5299 5300 if (!(BO & 0x4)) { 5301 putGST( PPC_GST_CTR, 5302 binop(mkSzOp(ty, Iop_Sub8), 5303 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5304 } 5305 5306 /* See comments above for 'bc' about this */ 5307 assign( ctr_ok, branch_ctr_ok( BO ) ); 5308 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5309 assign( do_branch, 5310 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5311 5312 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 )); 5313 5314 if (flag_LK) 5315 putGST( PPC_GST_LR, e_nia ); 5316 5317 stmt( IRStmt_Exit( 5318 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)), 5319 Ijk_Boring, 5320 c_nia )); 5321 5322 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) { 5323 make_redzone_AbiHint( vbi, lr_old, 5324 "branch-to-lr (unconditional return)" ); 5325 } 5326 5327 /* blrl is pretty strange; it's like a return that sets the 5328 return address of its caller to the insn following this 5329 one. Mark it as a return. */ 5330 irsb->jumpkind = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */ 5331 irsb->next = mkexpr(lr_old); 5332 break; 5333 } 5334 default: 5335 vex_printf("dis_int_branch(ppc)(opc2)\n"); 5336 return False; 5337 } 5338 break; 5339 5340 default: 5341 vex_printf("dis_int_branch(ppc)(opc1)\n"); 5342 return False; 5343 } 5344 5345 return True; 5346} 5347 5348 5349 5350/* 5351 Condition Register Logical Instructions 5352*/ 5353static Bool dis_cond_logic ( UInt theInstr ) 5354{ 5355 /* XL-Form */ 5356 UChar opc1 = ifieldOPC(theInstr); 5357 UChar crbD_addr = ifieldRegDS(theInstr); 5358 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) ); 5359 UChar crbA_addr = ifieldRegA(theInstr); 5360 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) ); 5361 UChar crbB_addr = ifieldRegB(theInstr); 5362 UInt opc2 = ifieldOPClo10(theInstr); 5363 UChar b0 = ifieldBIT0(theInstr); 5364 5365 IRTemp crbD = newTemp(Ity_I32); 5366 IRTemp crbA = newTemp(Ity_I32); 5367 IRTemp crbB = newTemp(Ity_I32); 5368 5369 if (opc1 != 19 || b0 != 0) { 5370 vex_printf("dis_cond_logic(ppc)(opc1)\n"); 5371 return False; 5372 } 5373 5374 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464) 5375 if (((crbD_addr & 0x3) != 0) || 5376 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) { 5377 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n"); 5378 return False; 5379 } 5380 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr); 5381 putCR0( crfD_addr, getCR0( crfS_addr) ); 5382 putCR321( crfD_addr, getCR321(crfS_addr) ); 5383 } else { 5384 assign( crbA, getCRbit(crbA_addr) ); 5385 if (crbA_addr == crbB_addr) 5386 crbB = crbA; 5387 else 5388 assign( crbB, getCRbit(crbB_addr) ); 5389 5390 switch (opc2) { 5391 case 0x101: // crand (Cond Reg AND, PPC32 p372) 5392 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5393 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) ); 5394 break; 5395 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373) 5396 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5397 assign( crbD, binop(Iop_And32, 5398 mkexpr(crbA), 5399 unop(Iop_Not32, mkexpr(crbB))) ); 5400 break; 5401 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374) 5402 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5403 assign( crbD, unop(Iop_Not32, 5404 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) ); 5405 break; 5406 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375) 5407 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5408 assign( crbD, unop(Iop_Not32, 5409 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) ); 5410 break; 5411 case 0x021: // crnor (Cond Reg NOR, PPC32 p376) 5412 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5413 assign( crbD, unop(Iop_Not32, 5414 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) ); 5415 break; 5416 case 0x1C1: // cror (Cond Reg OR, PPC32 p377) 5417 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5418 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) ); 5419 break; 5420 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378) 5421 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5422 assign( crbD, binop(Iop_Or32, 5423 mkexpr(crbA), 5424 unop(Iop_Not32, mkexpr(crbB))) ); 5425 break; 5426 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379) 5427 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5428 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) ); 5429 break; 5430 default: 5431 vex_printf("dis_cond_logic(ppc)(opc2)\n"); 5432 return False; 5433 } 5434 5435 putCRbit( crbD_addr, mkexpr(crbD) ); 5436 } 5437 return True; 5438} 5439 5440 5441/* 5442 Trap instructions 5443*/ 5444 5445/* Do the code generation for a trap. Returned Bool is true iff 5446 this is an unconditional trap. If the two arg IRExpr*s are 5447 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s 5448 then they are 64-bit, and we must be disassembling 64-bit 5449 instructions. */ 5450static Bool do_trap ( UChar TO, 5451 IRExpr* argL0, IRExpr* argR0, Addr64 cia ) 5452{ 5453 IRTemp argL, argR; 5454 IRExpr *argLe, *argRe, *cond, *tmp; 5455 5456 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32; 5457 5458 IROp opAND = is32bit ? Iop_And32 : Iop_And64; 5459 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64; 5460 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S; 5461 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U; 5462 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64; 5463 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64; 5464 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0); 5465 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2); 5466 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4); 5467 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8); 5468 5469 const UChar b11100 = 0x1C; 5470 const UChar b00111 = 0x07; 5471 5472 if (is32bit) { 5473 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 ); 5474 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 ); 5475 } else { 5476 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 ); 5477 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 ); 5478 vassert( mode64 ); 5479 } 5480 5481 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) { 5482 /* Unconditional trap. Just do the exit without 5483 testing the arguments. */ 5484 stmt( IRStmt_Exit( 5485 binop(opCMPEQ, const0, const0), 5486 Ijk_SigTRAP, 5487 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia) 5488 )); 5489 return True; /* unconditional trap */ 5490 } 5491 5492 if (is32bit) { 5493 argL = newTemp(Ity_I32); 5494 argR = newTemp(Ity_I32); 5495 } else { 5496 argL = newTemp(Ity_I64); 5497 argR = newTemp(Ity_I64); 5498 } 5499 5500 assign( argL, argL0 ); 5501 assign( argR, argR0 ); 5502 5503 argLe = mkexpr(argL); 5504 argRe = mkexpr(argR); 5505 5506 cond = const0; 5507 if (TO & 16) { // L <s R 5508 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8); 5509 cond = binop(opOR, tmp, cond); 5510 } 5511 if (TO & 8) { // L >s R 5512 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4); 5513 cond = binop(opOR, tmp, cond); 5514 } 5515 if (TO & 4) { // L == R 5516 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2); 5517 cond = binop(opOR, tmp, cond); 5518 } 5519 if (TO & 2) { // L <u R 5520 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8); 5521 cond = binop(opOR, tmp, cond); 5522 } 5523 if (TO & 1) { // L >u R 5524 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4); 5525 cond = binop(opOR, tmp, cond); 5526 } 5527 stmt( IRStmt_Exit( 5528 binop(opCMPNE, cond, const0), 5529 Ijk_SigTRAP, 5530 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia) 5531 )); 5532 return False; /* not an unconditional trap */ 5533} 5534 5535static Bool dis_trapi ( UInt theInstr, 5536 /*OUT*/DisResult* dres ) 5537{ 5538 /* D-Form */ 5539 UChar opc1 = ifieldOPC(theInstr); 5540 UChar TO = ifieldRegDS(theInstr); 5541 UChar rA_addr = ifieldRegA(theInstr); 5542 UInt uimm16 = ifieldUIMM16(theInstr); 5543 ULong simm16 = extend_s_16to64(uimm16); 5544 Addr64 cia = guest_CIA_curr_instr; 5545 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5546 Bool uncond = False; 5547 5548 switch (opc1) { 5549 case 0x03: // twi (Trap Word Immediate, PPC32 p548) 5550 uncond = do_trap( TO, 5551 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 5552 : getIReg(rA_addr), 5553 mkU32( (UInt)simm16 ), 5554 cia ); 5555 if (TO == 4) { 5556 DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 5557 } else { 5558 DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 5559 } 5560 break; 5561 case 0x02: // tdi 5562 if (!mode64) 5563 return False; 5564 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia ); 5565 if (TO == 4) { 5566 DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 5567 } else { 5568 DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 5569 } 5570 break; 5571 default: 5572 return False; 5573 } 5574 5575 if (uncond) { 5576 /* If the trap shows signs of being unconditional, don't 5577 continue decoding past it. */ 5578 irsb->next = mkSzImm( ty, nextInsnAddr() ); 5579 irsb->jumpkind = Ijk_Boring; 5580 dres->whatNext = Dis_StopHere; 5581 } 5582 5583 return True; 5584} 5585 5586static Bool dis_trap ( UInt theInstr, 5587 /*OUT*/DisResult* dres ) 5588{ 5589 /* X-Form */ 5590 UInt opc2 = ifieldOPClo10(theInstr); 5591 UChar TO = ifieldRegDS(theInstr); 5592 UChar rA_addr = ifieldRegA(theInstr); 5593 UChar rB_addr = ifieldRegB(theInstr); 5594 Addr64 cia = guest_CIA_curr_instr; 5595 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5596 Bool uncond = False; 5597 5598 if (ifieldBIT0(theInstr) != 0) 5599 return False; 5600 5601 switch (opc2) { 5602 case 0x004: // tw (Trap Word, PPC64 p540) 5603 uncond = do_trap( TO, 5604 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 5605 : getIReg(rA_addr), 5606 mode64 ? unop(Iop_64to32, getIReg(rB_addr)) 5607 : getIReg(rB_addr), 5608 cia ); 5609 if (TO == 4) { 5610 DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 5611 } else { 5612 DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 5613 } 5614 break; 5615 case 0x044: // td (Trap Doubleword, PPC64 p534) 5616 if (!mode64) 5617 return False; 5618 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia ); 5619 if (TO == 4) { 5620 DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 5621 } else { 5622 DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 5623 } 5624 break; 5625 default: 5626 return False; 5627 } 5628 5629 if (uncond) { 5630 /* If the trap shows signs of being unconditional, don't 5631 continue decoding past it. */ 5632 irsb->next = mkSzImm( ty, nextInsnAddr() ); 5633 irsb->jumpkind = Ijk_Boring; 5634 dres->whatNext = Dis_StopHere; 5635 } 5636 5637 return True; 5638} 5639 5640 5641/* 5642 System Linkage Instructions 5643*/ 5644static Bool dis_syslink ( UInt theInstr, 5645 VexAbiInfo* abiinfo, DisResult* dres ) 5646{ 5647 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5648 5649 if (theInstr != 0x44000002) { 5650 vex_printf("dis_syslink(ppc)(theInstr)\n"); 5651 return False; 5652 } 5653 5654 // sc (System Call, PPC32 p504) 5655 DIP("sc\n"); 5656 5657 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX 5658 Valgrind can back the guest up to this instruction if it needs 5659 to restart the syscall. */ 5660 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) ); 5661 5662 /* It's important that all ArchRegs carry their up-to-date value 5663 at this point. So we declare an end-of-block here, which 5664 forces any TempRegs caching ArchRegs to be flushed. */ 5665 irsb->next = abiinfo->guest_ppc_sc_continues_at_LR 5666 ? getGST( PPC_GST_LR ) 5667 : mkSzImm( ty, nextInsnAddr() ); 5668 irsb->jumpkind = Ijk_Sys_syscall; 5669 5670 dres->whatNext = Dis_StopHere; 5671 return True; 5672} 5673 5674 5675/* 5676 Memory Synchronization Instructions 5677 5678 Note on Reservations: 5679 We rely on the assumption that V will in fact only allow one thread at 5680 once to run. In effect, a thread can make a reservation, but we don't 5681 check any stores it does. Instead, the reservation is cancelled when 5682 the scheduler switches to another thread (run_thread_for_a_while()). 5683*/ 5684static Bool dis_memsync ( UInt theInstr ) 5685{ 5686 /* X-Form, XL-Form */ 5687 UChar opc1 = ifieldOPC(theInstr); 5688 UInt b11to25 = IFIELD(theInstr, 11, 15); 5689 UChar flag_L = ifieldRegDS(theInstr); 5690 UInt b11to20 = IFIELD(theInstr, 11, 10); 5691 UChar rD_addr = ifieldRegDS(theInstr); 5692 UChar rS_addr = rD_addr; 5693 UChar rA_addr = ifieldRegA(theInstr); 5694 UChar rB_addr = ifieldRegB(theInstr); 5695 UInt opc2 = ifieldOPClo10(theInstr); 5696 UChar b0 = ifieldBIT0(theInstr); 5697 5698 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5699 IRTemp EA = newTemp(ty); 5700 5701 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 5702 5703 switch (opc1) { 5704 /* XL-Form */ 5705 case 0x13: // isync (Instruction Synchronize, PPC32 p432) 5706 if (opc2 != 0x096) { 5707 vex_printf("dis_memsync(ppc)(0x13,opc2)\n"); 5708 return False; 5709 } 5710 if (b11to25 != 0 || b0 != 0) { 5711 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n"); 5712 return False; 5713 } 5714 DIP("isync\n"); 5715 stmt( IRStmt_MBE(Imbe_Fence) ); 5716 break; 5717 5718 /* X-Form */ 5719 case 0x1F: 5720 switch (opc2) { 5721 case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394) 5722 if (b11to25 != 0 || b0 != 0) { 5723 vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n"); 5724 return False; 5725 } 5726 DIP("eieio\n"); 5727 /* Insert a memory fence, just to be on the safe side. */ 5728 stmt( IRStmt_MBE(Imbe_Fence) ); 5729 break; 5730 5731 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458) 5732 IRTemp res; 5733 /* According to the PowerPC ISA version 2.05, b0 (called EH 5734 in the documentation) is merely a hint bit to the 5735 hardware, I think as to whether or not contention is 5736 likely. So we can just ignore it. */ 5737 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 5738 5739 // trap if misaligned 5740 gen_SIGBUS_if_misaligned( EA, 4 ); 5741 5742 // and actually do the load 5743 res = newTemp(Ity_I32); 5744 stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) ); 5745 5746 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) ); 5747 break; 5748 } 5749 5750 case 0x096: { 5751 // stwcx. (Store Word Conditional Indexed, PPC32 p532) 5752 // Note this has to handle stwcx. in both 32- and 64-bit modes, 5753 // so isn't quite as straightforward as it might otherwise be. 5754 IRTemp rS = newTemp(Ity_I32); 5755 IRTemp resSC; 5756 if (b0 != 1) { 5757 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 5758 return False; 5759 } 5760 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5761 5762 // trap if misaligned 5763 gen_SIGBUS_if_misaligned( EA, 4 ); 5764 5765 // Get the data to be stored, and narrow to 32 bits if necessary 5766 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) ); 5767 5768 // Do the store, and get success/failure bit into resSC 5769 resSC = newTemp(Ity_I1); 5770 stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) ); 5771 5772 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 5773 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 5774 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 5775 putCR0(0, getXER_SO()); 5776 5777 /* Note: 5778 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 5779 whether rS is stored is dependent on that value. */ 5780 /* So I guess we can just ignore this case? */ 5781 break; 5782 } 5783 5784 case 0x256: // sync (Synchronize, PPC32 p543), 5785 // also lwsync (L==1), ptesync (L==2) 5786 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html 5787 5788 The PowerPC architecture used in IBM chips has expanded 5789 the sync instruction into two variants: lightweight sync 5790 and heavyweight sync. The original sync instruction is 5791 the new heavyweight sync and lightweight sync is a strict 5792 subset of the heavyweight sync functionality. This allows 5793 the programmer to specify a less expensive operation on 5794 high-end systems when the full sync functionality is not 5795 necessary. 5796 5797 The basic "sync" mnemonic now utilizes an operand. "sync" 5798 without an operand now becomes a extended mnemonic for 5799 heavyweight sync. Processors without the lwsync 5800 instruction will not decode the L field and will perform a 5801 heavyweight sync. Everything is backward compatible. 5802 5803 sync = sync 0 5804 lwsync = sync 1 5805 ptesync = sync 2 *** TODO - not implemented *** 5806 */ 5807 if (b11to20 != 0 || b0 != 0) { 5808 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n"); 5809 return False; 5810 } 5811 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) { 5812 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n"); 5813 return False; 5814 } 5815 DIP("%ssync\n", flag_L == 1 ? "lw" : ""); 5816 /* Insert a memory fence. It's sometimes important that these 5817 are carried through to the generated code. */ 5818 stmt( IRStmt_MBE(Imbe_Fence) ); 5819 break; 5820 5821 /* 64bit Memsync */ 5822 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473) 5823 IRTemp res; 5824 /* According to the PowerPC ISA version 2.05, b0 (called EH 5825 in the documentation) is merely a hint bit to the 5826 hardware, I think as to whether or not contention is 5827 likely. So we can just ignore it. */ 5828 if (!mode64) 5829 return False; 5830 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 5831 5832 // trap if misaligned 5833 gen_SIGBUS_if_misaligned( EA, 8 ); 5834 5835 // and actually do the load 5836 res = newTemp(Ity_I64); 5837 stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) ); 5838 5839 putIReg( rD_addr, mkexpr(res) ); 5840 break; 5841 } 5842 5843 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581) 5844 // A marginally simplified version of the stwcx. case 5845 IRTemp rS = newTemp(Ity_I64); 5846 IRTemp resSC; 5847 if (b0 != 1) { 5848 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n"); 5849 return False; 5850 } 5851 if (!mode64) 5852 return False; 5853 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5854 5855 // trap if misaligned 5856 gen_SIGBUS_if_misaligned( EA, 8 ); 5857 5858 // Get the data to be stored 5859 assign( rS, getIReg(rS_addr) ); 5860 5861 // Do the store, and get success/failure bit into resSC 5862 resSC = newTemp(Ity_I1); 5863 stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) ); 5864 5865 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 5866 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 5867 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 5868 putCR0(0, getXER_SO()); 5869 5870 /* Note: 5871 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 5872 whether rS is stored is dependent on that value. */ 5873 /* So I guess we can just ignore this case? */ 5874 break; 5875 } 5876 5877 default: 5878 vex_printf("dis_memsync(ppc)(opc2)\n"); 5879 return False; 5880 } 5881 break; 5882 5883 default: 5884 vex_printf("dis_memsync(ppc)(opc1)\n"); 5885 return False; 5886 } 5887 return True; 5888} 5889 5890 5891 5892/* 5893 Integer Shift Instructions 5894*/ 5895static Bool dis_int_shift ( UInt theInstr ) 5896{ 5897 /* X-Form, XS-Form */ 5898 UChar opc1 = ifieldOPC(theInstr); 5899 UChar rS_addr = ifieldRegDS(theInstr); 5900 UChar rA_addr = ifieldRegA(theInstr); 5901 UChar rB_addr = ifieldRegB(theInstr); 5902 UChar sh_imm = rB_addr; 5903 UInt opc2 = ifieldOPClo10(theInstr); 5904 UChar b1 = ifieldBIT1(theInstr); 5905 UChar flag_rC = ifieldBIT0(theInstr); 5906 5907 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5908 IRTemp rA = newTemp(ty); 5909 IRTemp rS = newTemp(ty); 5910 IRTemp rB = newTemp(ty); 5911 IRTemp outofrange = newTemp(Ity_I8); 5912 IRTemp rS_lo32 = newTemp(Ity_I32); 5913 IRTemp rB_lo32 = newTemp(Ity_I32); 5914 IRExpr* e_tmp; 5915 5916 assign( rS, getIReg(rS_addr) ); 5917 assign( rB, getIReg(rB_addr) ); 5918 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) ); 5919 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) ); 5920 5921 if (opc1 == 0x1F) { 5922 switch (opc2) { 5923 case 0x018: { // slw (Shift Left Word, PPC32 p505) 5924 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5925 rA_addr, rS_addr, rB_addr); 5926 /* rA = rS << rB */ 5927 /* ppc32 semantics are: 5928 slw(x,y) = (x << (y & 31)) -- primary result 5929 & ~((y << 26) >>s 31) -- make result 0 5930 for y in 32 .. 63 5931 */ 5932 e_tmp = 5933 binop( Iop_And32, 5934 binop( Iop_Shl32, 5935 mkexpr(rS_lo32), 5936 unop( Iop_32to8, 5937 binop(Iop_And32, 5938 mkexpr(rB_lo32), mkU32(31)))), 5939 unop( Iop_Not32, 5940 binop( Iop_Sar32, 5941 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)), 5942 mkU8(31))) ); 5943 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 5944 break; 5945 } 5946 5947 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506) 5948 IRTemp sh_amt = newTemp(Ity_I32); 5949 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 5950 rA_addr, rS_addr, rB_addr); 5951 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is: 5952 amt = rB & 63 5953 rA = Sar32( rS, amt > 31 ? 31 : amt ) 5954 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi) 5955 */ 5956 assign( sh_amt, binop(Iop_And32, mkU32(0x3F), 5957 mkexpr(rB_lo32)) ); 5958 assign( outofrange, 5959 unop( Iop_1Uto8, 5960 binop(Iop_CmpLT32U, mkU32(31), 5961 mkexpr(sh_amt)) )); 5962 e_tmp = binop( Iop_Sar32, 5963 mkexpr(rS_lo32), 5964 unop( Iop_32to8, 5965 IRExpr_Mux0X( mkexpr(outofrange), 5966 mkexpr(sh_amt), 5967 mkU32(31)) ) ); 5968 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) ); 5969 5970 set_XER_CA( ty, PPCG_FLAG_OP_SRAW, 5971 mkexpr(rA), 5972 mkWidenFrom32(ty, mkexpr(rS_lo32), True), 5973 mkWidenFrom32(ty, mkexpr(sh_amt), True ), 5974 mkWidenFrom32(ty, getXER_CA32(), True) ); 5975 break; 5976 } 5977 5978 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507) 5979 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"", 5980 rA_addr, rS_addr, sh_imm); 5981 vassert(sh_imm < 32); 5982 if (mode64) { 5983 assign( rA, binop(Iop_Sar64, 5984 binop(Iop_Shl64, getIReg(rS_addr), 5985 mkU8(32)), 5986 mkU8(32 + sh_imm)) ); 5987 } else { 5988 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32), 5989 mkU8(sh_imm)) ); 5990 } 5991 5992 set_XER_CA( ty, PPCG_FLAG_OP_SRAWI, 5993 mkexpr(rA), 5994 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True), 5995 mkSzImm(ty, sh_imm), 5996 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 5997 break; 5998 5999 case 0x218: // srw (Shift Right Word, PPC32 p508) 6000 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6001 rA_addr, rS_addr, rB_addr); 6002 /* rA = rS >>u rB */ 6003 /* ppc32 semantics are: 6004 srw(x,y) = (x >>u (y & 31)) -- primary result 6005 & ~((y << 26) >>s 31) -- make result 0 6006 for y in 32 .. 63 6007 */ 6008 e_tmp = 6009 binop( 6010 Iop_And32, 6011 binop( Iop_Shr32, 6012 mkexpr(rS_lo32), 6013 unop( Iop_32to8, 6014 binop(Iop_And32, mkexpr(rB_lo32), 6015 mkU32(31)))), 6016 unop( Iop_Not32, 6017 binop( Iop_Sar32, 6018 binop(Iop_Shl32, mkexpr(rB_lo32), 6019 mkU8(26)), 6020 mkU8(31)))); 6021 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6022 break; 6023 6024 6025 /* 64bit Shifts */ 6026 case 0x01B: // sld (Shift Left DWord, PPC64 p568) 6027 DIP("sld%s r%u,r%u,r%u\n", 6028 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6029 /* rA = rS << rB */ 6030 /* ppc64 semantics are: 6031 slw(x,y) = (x << (y & 63)) -- primary result 6032 & ~((y << 57) >>s 63) -- make result 0 6033 for y in 64 .. 6034 */ 6035 assign( rA, 6036 binop( 6037 Iop_And64, 6038 binop( Iop_Shl64, 6039 mkexpr(rS), 6040 unop( Iop_64to8, 6041 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6042 unop( Iop_Not64, 6043 binop( Iop_Sar64, 6044 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6045 mkU8(63)))) ); 6046 break; 6047 6048 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570) 6049 IRTemp sh_amt = newTemp(Ity_I64); 6050 DIP("srad%s r%u,r%u,r%u\n", 6051 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6052 /* amt = rB & 127 6053 rA = Sar64( rS, amt > 63 ? 63 : amt ) 6054 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi) 6055 */ 6056 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) ); 6057 assign( outofrange, 6058 unop( Iop_1Uto8, 6059 binop(Iop_CmpLT64U, mkU64(63), 6060 mkexpr(sh_amt)) )); 6061 assign( rA, 6062 binop( Iop_Sar64, 6063 mkexpr(rS), 6064 unop( Iop_64to8, 6065 IRExpr_Mux0X( mkexpr(outofrange), 6066 mkexpr(sh_amt), 6067 mkU64(63)) )) 6068 ); 6069 set_XER_CA( ty, PPCG_FLAG_OP_SRAD, 6070 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt), 6071 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6072 break; 6073 } 6074 6075 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571) 6076 sh_imm |= b1<<5; 6077 vassert(sh_imm < 64); 6078 DIP("sradi%s r%u,r%u,%u\n", 6079 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 6080 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) ); 6081 6082 set_XER_CA( ty, PPCG_FLAG_OP_SRADI, 6083 mkexpr(rA), 6084 getIReg(rS_addr), 6085 mkU64(sh_imm), 6086 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6087 break; 6088 6089 case 0x21B: // srd (Shift Right DWord, PPC64 p574) 6090 DIP("srd%s r%u,r%u,r%u\n", 6091 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6092 /* rA = rS >>u rB */ 6093 /* ppc semantics are: 6094 srw(x,y) = (x >>u (y & 63)) -- primary result 6095 & ~((y << 57) >>s 63) -- make result 0 6096 for y in 64 .. 127 6097 */ 6098 assign( rA, 6099 binop( 6100 Iop_And64, 6101 binop( Iop_Shr64, 6102 mkexpr(rS), 6103 unop( Iop_64to8, 6104 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6105 unop( Iop_Not64, 6106 binop( Iop_Sar64, 6107 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6108 mkU8(63)))) ); 6109 break; 6110 6111 default: 6112 vex_printf("dis_int_shift(ppc)(opc2)\n"); 6113 return False; 6114 } 6115 } else { 6116 vex_printf("dis_int_shift(ppc)(opc1)\n"); 6117 return False; 6118 } 6119 6120 putIReg( rA_addr, mkexpr(rA) ); 6121 6122 if (flag_rC) { 6123 set_CR0( mkexpr(rA) ); 6124 } 6125 return True; 6126} 6127 6128 6129 6130/* 6131 Integer Load/Store Reverse Instructions 6132*/ 6133/* Generates code to swap the byte order in an Ity_I32. */ 6134static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t ) 6135{ 6136 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 6137 return 6138 binop(Iop_Or32, 6139 binop(Iop_Shl32, mkexpr(t), mkU8(24)), 6140 binop(Iop_Or32, 6141 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 6142 mkU32(0x00FF0000)), 6143 binop(Iop_Or32, 6144 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 6145 mkU32(0x0000FF00)), 6146 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)), 6147 mkU32(0x000000FF) ) 6148 ))); 6149} 6150 6151/* Generates code to swap the byte order in the lower half of an Ity_I32, 6152 and zeroes the upper half. */ 6153static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t ) 6154{ 6155 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 6156 return 6157 binop(Iop_Or32, 6158 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 6159 mkU32(0x0000FF00)), 6160 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 6161 mkU32(0x000000FF)) 6162 ); 6163} 6164 6165static Bool dis_int_ldst_rev ( UInt theInstr ) 6166{ 6167 /* X-Form */ 6168 UChar opc1 = ifieldOPC(theInstr); 6169 UChar rD_addr = ifieldRegDS(theInstr); 6170 UChar rS_addr = rD_addr; 6171 UChar rA_addr = ifieldRegA(theInstr); 6172 UChar rB_addr = ifieldRegB(theInstr); 6173 UInt opc2 = ifieldOPClo10(theInstr); 6174 UChar b0 = ifieldBIT0(theInstr); 6175 6176 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6177 IRTemp EA = newTemp(ty); 6178 IRTemp w1 = newTemp(Ity_I32); 6179 IRTemp w2 = newTemp(Ity_I32); 6180 6181 if (opc1 != 0x1F || b0 != 0) { 6182 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n"); 6183 return False; 6184 } 6185 6186 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6187 6188 switch (opc2) { 6189 6190 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449) 6191 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6192 assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) ); 6193 assign( w2, gen_byterev16(w1) ); 6194 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 6195 /* Signed */False) ); 6196 break; 6197 6198 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459) 6199 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6200 assign( w1, loadBE(Ity_I32, mkexpr(EA)) ); 6201 assign( w2, gen_byterev32(w1) ); 6202 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 6203 /* Signed */False) ); 6204 break; 6205 6206 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed) 6207 { 6208 IRExpr * nextAddr; 6209 IRTemp w3 = newTemp( Ity_I32 ); 6210 IRTemp w4 = newTemp( Ity_I32 ); 6211 DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6212 assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) ); 6213 assign( w2, gen_byterev32( w1 ) ); 6214 nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 6215 ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) ); 6216 assign( w3, loadBE( Ity_I32, nextAddr ) ); 6217 assign( w4, gen_byterev32( w3 ) ); 6218 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) ); 6219 break; 6220 } 6221 6222 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523) 6223 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6224 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6225 storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) ); 6226 break; 6227 6228 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531) 6229 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6230 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6231 storeBE( mkexpr(EA), gen_byterev32(w1) ); 6232 break; 6233 6234 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed) 6235 { 6236 IRTemp lo = newTemp(Ity_I32); 6237 IRTemp hi = newTemp(Ity_I32); 6238 IRTemp rS = newTemp(Ity_I64); 6239 assign( rS, getIReg( rS_addr ) ); 6240 DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6241 assign(lo, unop(Iop_64HIto32, mkexpr(rS))); 6242 assign(hi, unop(Iop_64to32, mkexpr(rS))); 6243 storeBE( mkexpr( EA ), 6244 binop( Iop_32HLto64, gen_byterev32( hi ), gen_byterev32( lo ) ) ); 6245 break; 6246 } 6247 6248 default: 6249 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n"); 6250 return False; 6251 } 6252 return True; 6253} 6254 6255 6256 6257/* 6258 Processor Control Instructions 6259*/ 6260static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr ) 6261{ 6262 UChar opc1 = ifieldOPC(theInstr); 6263 6264 /* X-Form */ 6265 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 6266 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 6267 UChar rD_addr = ifieldRegDS(theInstr); 6268 UInt b11to20 = IFIELD( theInstr, 11, 10 ); 6269 6270 /* XFX-Form */ 6271 UChar rS_addr = rD_addr; 6272 UInt SPR = b11to20; 6273 UInt TBR = b11to20; 6274 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) ); 6275 UInt CRM = IFIELD( theInstr, 12, 8 ); 6276 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 6277 6278 UInt opc2 = ifieldOPClo10(theInstr); 6279 UChar b0 = ifieldBIT0(theInstr); 6280 6281 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6282 IRTemp rS = newTemp(ty); 6283 assign( rS, getIReg(rS_addr) ); 6284 6285 /* Reorder SPR field as per PPC32 p470 */ 6286 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); 6287 /* Reorder TBR field as per PPC32 p475 */ 6288 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31); 6289 6290 if (opc1 != 0x1F || b0 != 0) { 6291 vex_printf("dis_proc_ctl(ppc)(opc1|b0)\n"); 6292 return False; 6293 } 6294 6295 switch (opc2) { 6296 /* X-Form */ 6297 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466) 6298 if (b21to22 != 0 || b11to20 != 0) { 6299 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n"); 6300 return False; 6301 } 6302 DIP("mcrxr crf%d\n", crfD); 6303 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */ 6304 putGST_field( PPC_GST_CR, 6305 getGST_field( PPC_GST_XER, 7 ), 6306 crfD ); 6307 6308 // Clear XER[0-3] 6309 putXER_SO( mkU8(0) ); 6310 putXER_OV( mkU8(0) ); 6311 putXER_CA( mkU8(0) ); 6312 break; 6313 } 6314 6315 case 0x013: 6316 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467) 6317 // b20==1 & b11==0: mfocrf (Move from One CR Field) 6318 // However it seems that the 'mfcr' behaviour is an acceptable 6319 // implementation of mfocr (from the 2.02 arch spec) 6320 if (b11to20 == 0) { 6321 DIP("mfcr r%u\n", rD_addr); 6322 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 6323 /* Signed */False) ); 6324 break; 6325 } 6326 if (b20 == 1 && b11 == 0) { 6327 DIP("mfocrf r%u,%u\n", rD_addr, CRM); 6328 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 6329 /* Signed */False) ); 6330 break; 6331 } 6332 /* not decodable */ 6333 return False; 6334 6335 /* XFX-Form */ 6336 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470) 6337 6338 switch (SPR) { // Choose a register... 6339 case 0x1: 6340 DIP("mfxer r%u\n", rD_addr); 6341 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ), 6342 /* Signed */False) ); 6343 break; 6344 case 0x8: 6345 DIP("mflr r%u\n", rD_addr); 6346 putIReg( rD_addr, getGST( PPC_GST_LR ) ); 6347 break; 6348 case 0x9: 6349 DIP("mfctr r%u\n", rD_addr); 6350 putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 6351 break; 6352 case 0x100: 6353 DIP("mfvrsave r%u\n", rD_addr); 6354 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ), 6355 /* Signed */False) ); 6356 break; 6357 6358 case 0x103: 6359 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr); 6360 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) ); 6361 break; 6362 6363 /* Even a lowly PPC7400 can run the associated helper, so no 6364 obvious need for feature testing at this point. */ 6365 case 268 /* 0x10C */: 6366 case 269 /* 0x10D */: { 6367 UInt arg = SPR==268 ? 0 : 1; 6368 IRTemp val = newTemp(Ity_I32); 6369 IRExpr** args = mkIRExprVec_1( mkU32(arg) ); 6370 IRDirty* d = unsafeIRDirty_1_N( 6371 val, 6372 0/*regparms*/, 6373 "ppc32g_dirtyhelper_MFSPR_268_269", 6374 fnptr_to_fnentry 6375 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269), 6376 args 6377 ); 6378 /* execute the dirty call, dumping the result in val. */ 6379 stmt( IRStmt_Dirty(d) ); 6380 putIReg( rD_addr, 6381 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 6382 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 6383 break; 6384 } 6385 6386 /* Again, runs natively on PPC7400 (7447, really). Not 6387 bothering with a feature test. */ 6388 case 287: /* 0x11F */ { 6389 IRTemp val = newTemp(Ity_I32); 6390 IRExpr** args = mkIRExprVec_0(); 6391 IRDirty* d = unsafeIRDirty_1_N( 6392 val, 6393 0/*regparms*/, 6394 "ppc32g_dirtyhelper_MFSPR_287", 6395 fnptr_to_fnentry 6396 (vbi, &ppc32g_dirtyhelper_MFSPR_287), 6397 args 6398 ); 6399 /* execute the dirty call, dumping the result in val. */ 6400 stmt( IRStmt_Dirty(d) ); 6401 putIReg( rD_addr, 6402 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 6403 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 6404 break; 6405 } 6406 6407 default: 6408 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR); 6409 return False; 6410 } 6411 break; 6412 6413 case 0x173: { // mftb (Move from Time Base, PPC32 p475) 6414 IRTemp val = newTemp(Ity_I64); 6415 IRExpr** args = mkIRExprVec_0(); 6416 IRDirty* d = unsafeIRDirty_1_N( 6417 val, 6418 0/*regparms*/, 6419 "ppcg_dirtyhelper_MFTB", 6420 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB), 6421 args ); 6422 /* execute the dirty call, dumping the result in val. */ 6423 stmt( IRStmt_Dirty(d) ); 6424 6425 switch (TBR) { 6426 case 269: 6427 DIP("mftbu r%u", rD_addr); 6428 putIReg( rD_addr, 6429 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)), 6430 /* Signed */False) ); 6431 break; 6432 case 268: 6433 DIP("mftb r%u", rD_addr); 6434 putIReg( rD_addr, (mode64) ? mkexpr(val) : 6435 unop(Iop_64to32, mkexpr(val)) ); 6436 break; 6437 default: 6438 return False; /* illegal instruction */ 6439 } 6440 break; 6441 } 6442 6443 case 0x090: { 6444 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477) 6445 // b20==1: mtocrf (Move to One Cond Reg Field) 6446 Int cr; 6447 UChar shft; 6448 if (b11 != 0) 6449 return False; 6450 if (b20 == 1) { 6451 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if > 6452 1 field is written. It seems more robust to decline to 6453 decode the insn if so. */ 6454 switch (CRM) { 6455 case 0x01: case 0x02: case 0x04: case 0x08: 6456 case 0x10: case 0x20: case 0x40: case 0x80: 6457 break; 6458 default: 6459 return False; 6460 } 6461 } 6462 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf", 6463 CRM, rS_addr); 6464 /* Write to each field specified by CRM */ 6465 for (cr = 0; cr < 8; cr++) { 6466 if ((CRM & (1 << (7-cr))) == 0) 6467 continue; 6468 shft = 4*(7-cr); 6469 putGST_field( PPC_GST_CR, 6470 binop(Iop_Shr32, 6471 mkNarrowTo32(ty, mkexpr(rS)), 6472 mkU8(shft)), cr ); 6473 } 6474 break; 6475 } 6476 6477 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483) 6478 6479 switch (SPR) { // Choose a register... 6480 case 0x1: 6481 DIP("mtxer r%u\n", rS_addr); 6482 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) ); 6483 break; 6484 case 0x8: 6485 DIP("mtlr r%u\n", rS_addr); 6486 putGST( PPC_GST_LR, mkexpr(rS) ); 6487 break; 6488 case 0x9: 6489 DIP("mtctr r%u\n", rS_addr); 6490 putGST( PPC_GST_CTR, mkexpr(rS) ); 6491 break; 6492 case 0x100: 6493 DIP("mtvrsave r%u\n", rS_addr); 6494 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) ); 6495 break; 6496 6497 default: 6498 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR); 6499 return False; 6500 } 6501 break; 6502 6503 default: 6504 vex_printf("dis_proc_ctl(ppc)(opc2)\n"); 6505 return False; 6506 } 6507 return True; 6508} 6509 6510 6511/* 6512 Cache Management Instructions 6513*/ 6514static Bool dis_cache_manage ( UInt theInstr, 6515 DisResult* dres, 6516 VexArchInfo* guest_archinfo ) 6517{ 6518 /* X-Form */ 6519 UChar opc1 = ifieldOPC(theInstr); 6520 UChar b21to25 = ifieldRegDS(theInstr); 6521 UChar rA_addr = ifieldRegA(theInstr); 6522 UChar rB_addr = ifieldRegB(theInstr); 6523 UInt opc2 = ifieldOPClo10(theInstr); 6524 UChar b0 = ifieldBIT0(theInstr); 6525 UInt lineszB = guest_archinfo->ppc_cache_line_szB; 6526 Bool is_dcbzl = False; 6527 6528 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6529 6530 /* For dcbt, the lowest two bits of b21to25 encode an 6531 access-direction hint (TH field) which we ignore. Well, that's 6532 what the PowerPC documentation says. In fact xlc -O4 on POWER5 6533 seems to generate values of 8 and 10 for b21to25. */ 6534 if (opc1 == 0x1F && opc2 == 0x116) { 6535 /* b21to25 &= ~3; */ /* if the docs were true */ 6536 b21to25 = 0; /* blunt instrument */ 6537 } 6538 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz 6539 if (b21to25 == 1) { 6540 is_dcbzl = True; 6541 b21to25 = 0; 6542 if (!(guest_archinfo->ppc_dcbzl_szB)) { 6543 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n"); 6544 return False; 6545 } 6546 } 6547 } 6548 6549 if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) { 6550 if (0) vex_printf("dis_cache_manage %d %d %d\n", 6551 (Int)opc1, (Int)b21to25, (Int)b0); 6552 vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n"); 6553 return False; 6554 } 6555 6556 /* stay sane .. */ 6557 vassert(lineszB == 32 || lineszB == 64 || lineszB == 128); 6558 6559 switch (opc2) { 6560//zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380) 6561//zz vassert(0); /* AWAITING TEST CASE */ 6562//zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr); 6563//zz if (0) vex_printf("vex ppc->IR: kludged dcba\n"); 6564//zz break; 6565 6566 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382) 6567 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr); 6568 /* nop as far as vex is concerned */ 6569 break; 6570 6571 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384) 6572 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr); 6573 /* nop as far as vex is concerned */ 6574 break; 6575 6576 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385) 6577 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr); 6578 /* nop as far as vex is concerned */ 6579 break; 6580 6581 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386) 6582 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr); 6583 /* nop as far as vex is concerned */ 6584 break; 6585 6586 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387) 6587 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264) 6588 /* Clear all bytes in cache block at (rA|0) + rB. */ 6589 IRTemp EA = newTemp(ty); 6590 IRTemp addr = newTemp(ty); 6591 IRExpr* irx_addr; 6592 UInt i; 6593 UInt clearszB; 6594 if (is_dcbzl) { 6595 clearszB = guest_archinfo->ppc_dcbzl_szB; 6596 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr); 6597 } 6598 else { 6599 clearszB = guest_archinfo->ppc_dcbz_szB; 6600 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr); 6601 } 6602 6603 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6604 6605 if (mode64) { 6606 /* Round EA down to the start of the containing block. */ 6607 assign( addr, binop( Iop_And64, 6608 mkexpr(EA), 6609 mkU64( ~((ULong)clearszB-1) )) ); 6610 6611 for (i = 0; i < clearszB / 8; i++) { 6612 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) ); 6613 storeBE( irx_addr, mkU64(0) ); 6614 } 6615 } else { 6616 /* Round EA down to the start of the containing block. */ 6617 assign( addr, binop( Iop_And32, 6618 mkexpr(EA), 6619 mkU32( ~(clearszB-1) )) ); 6620 6621 for (i = 0; i < clearszB / 4; i++) { 6622 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) ); 6623 storeBE( irx_addr, mkU32(0) ); 6624 } 6625 } 6626 break; 6627 } 6628 6629 case 0x3D6: { 6630 // icbi (Instruction Cache Block Invalidate, PPC32 p431) 6631 /* Invalidate all translations containing code from the cache 6632 block at (rA|0) + rB. */ 6633 IRTemp EA = newTemp(ty); 6634 IRTemp addr = newTemp(ty); 6635 DIP("icbi r%u,r%u\n", rA_addr, rB_addr); 6636 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6637 6638 /* Round EA down to the start of the containing block. */ 6639 assign( addr, binop( mkSzOp(ty, Iop_And8), 6640 mkexpr(EA), 6641 mkSzImm(ty, ~(((ULong)lineszB)-1) )) ); 6642 putGST( PPC_GST_TISTART, mkexpr(addr) ); 6643 putGST( PPC_GST_TILEN, mkSzImm(ty, lineszB) ); 6644 6645 /* be paranoid ... */ 6646 stmt( IRStmt_MBE(Imbe_Fence) ); 6647 6648 irsb->jumpkind = Ijk_TInval; 6649 irsb->next = mkSzImm(ty, nextInsnAddr()); 6650 dres->whatNext = Dis_StopHere; 6651 break; 6652 } 6653 6654 default: 6655 vex_printf("dis_cache_manage(ppc)(opc2)\n"); 6656 return False; 6657 } 6658 return True; 6659} 6660 6661 6662/*------------------------------------------------------------*/ 6663/*--- Floating Point Helpers ---*/ 6664/*------------------------------------------------------------*/ 6665 6666/* --------- Synthesise a 2-bit FPU rounding mode. --------- */ 6667/* Produces a value in 0 .. 3, which is encoded as per the type 6668 IRRoundingMode. PPCRoundingMode encoding is different to 6669 IRRoundingMode, so need to map it. 6670*/ 6671static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void ) 6672{ 6673/* 6674 rounding mode | PPC | IR 6675 ------------------------ 6676 to nearest | 00 | 00 6677 to zero | 01 | 11 6678 to +infinity | 10 | 10 6679 to -infinity | 11 | 01 6680*/ 6681 IRTemp rm_PPC32 = newTemp(Ity_I32); 6682 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) ); 6683 6684 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 6685 return binop( Iop_Xor32, 6686 mkexpr(rm_PPC32), 6687 binop( Iop_And32, 6688 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)), 6689 mkU32(2) )); 6690} 6691 6692 6693/*------------------------------------------------------------*/ 6694/*--- Floating Point Instruction Translation ---*/ 6695/*------------------------------------------------------------*/ 6696 6697/* 6698 Floating Point Load Instructions 6699*/ 6700static Bool dis_fp_load ( UInt theInstr ) 6701{ 6702 /* X-Form, D-Form */ 6703 UChar opc1 = ifieldOPC(theInstr); 6704 UChar frD_addr = ifieldRegDS(theInstr); 6705 UChar rA_addr = ifieldRegA(theInstr); 6706 UChar rB_addr = ifieldRegB(theInstr); 6707 UInt opc2 = ifieldOPClo10(theInstr); 6708 UChar b0 = ifieldBIT0(theInstr); 6709 UInt uimm16 = ifieldUIMM16(theInstr); 6710 6711 Int simm16 = extend_s_16to32(uimm16); 6712 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6713 IRTemp EA = newTemp(ty); 6714 IRTemp rA = newTemp(ty); 6715 IRTemp rB = newTemp(ty); 6716 IRTemp iHi = newTemp(Ity_I32); 6717 IRTemp iLo = newTemp(Ity_I32); 6718 6719 assign( rA, getIReg(rA_addr) ); 6720 assign( rB, getIReg(rB_addr) ); 6721 6722 /* These are completely straightforward from a rounding and status 6723 bits perspective: no rounding involved and no funny status or CR 6724 bits affected. */ 6725 6726 switch (opc1) { 6727 case 0x30: // lfs (Load Float Single, PPC32 p441) 6728 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 6729 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 6730 putFReg( frD_addr, 6731 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 6732 break; 6733 6734 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442) 6735 if (rA_addr == 0) 6736 return False; 6737 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 6738 assign( EA, ea_rA_simm(rA_addr, simm16) ); 6739 putFReg( frD_addr, 6740 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 6741 putIReg( rA_addr, mkexpr(EA) ); 6742 break; 6743 6744 case 0x32: // lfd (Load Float Double, PPC32 p437) 6745 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 6746 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 6747 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 6748 break; 6749 6750 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438) 6751 if (rA_addr == 0) 6752 return False; 6753 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 6754 assign( EA, ea_rA_simm(rA_addr, simm16) ); 6755 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 6756 putIReg( rA_addr, mkexpr(EA) ); 6757 break; 6758 6759 case 0x1F: 6760 if (b0 != 0) { 6761 vex_printf("dis_fp_load(ppc)(instr,b0)\n"); 6762 return False; 6763 } 6764 6765 switch(opc2) { 6766 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444) 6767 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 6768 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6769 putFReg( frD_addr, unop( Iop_F32toF64, 6770 loadBE(Ity_F32, mkexpr(EA))) ); 6771 break; 6772 6773 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443) 6774 if (rA_addr == 0) 6775 return False; 6776 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 6777 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 6778 putFReg( frD_addr, 6779 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 6780 putIReg( rA_addr, mkexpr(EA) ); 6781 break; 6782 6783 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440) 6784 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 6785 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6786 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 6787 break; 6788 6789 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439) 6790 if (rA_addr == 0) 6791 return False; 6792 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 6793 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 6794 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 6795 putIReg( rA_addr, mkexpr(EA) ); 6796 break; 6797 6798 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120) 6799 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 6800 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6801 assign( iLo, loadBE(Ity_I32, mkexpr(EA)) ); 6802 assign( iHi, binop(Iop_Sub32, 6803 mkU32(0), 6804 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) ); 6805 putFReg( frD_addr, unop(Iop_ReinterpI64asF64, 6806 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) ); 6807 break; 6808 6809 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed 6810 { 6811 IRTemp dw = newTemp( Ity_I64 ); 6812 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 6813 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6814 assign( iLo, loadBE(Ity_I32, mkexpr(EA)) ); 6815 assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) ); 6816 putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) ); 6817 break; 6818 } 6819 6820 default: 6821 vex_printf("dis_fp_load(ppc)(opc2)\n"); 6822 return False; 6823 } 6824 break; 6825 6826 default: 6827 vex_printf("dis_fp_load(ppc)(opc1)\n"); 6828 return False; 6829 } 6830 return True; 6831} 6832 6833 6834 6835/* 6836 Floating Point Store Instructions 6837*/ 6838static Bool dis_fp_store ( UInt theInstr ) 6839{ 6840 /* X-Form, D-Form */ 6841 UChar opc1 = ifieldOPC(theInstr); 6842 UChar frS_addr = ifieldRegDS(theInstr); 6843 UChar rA_addr = ifieldRegA(theInstr); 6844 UChar rB_addr = ifieldRegB(theInstr); 6845 UInt opc2 = ifieldOPClo10(theInstr); 6846 UChar b0 = ifieldBIT0(theInstr); 6847 Int uimm16 = ifieldUIMM16(theInstr); 6848 6849 Int simm16 = extend_s_16to32(uimm16); 6850 IRTemp frS = newTemp(Ity_F64); 6851 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6852 IRTemp EA = newTemp(ty); 6853 IRTemp rA = newTemp(ty); 6854 IRTemp rB = newTemp(ty); 6855 6856 assign( frS, getFReg(frS_addr) ); 6857 assign( rA, getIReg(rA_addr) ); 6858 assign( rB, getIReg(rB_addr) ); 6859 6860 /* These are straightforward from a status bits perspective: no 6861 funny status or CR bits affected. For single precision stores, 6862 the values are truncated and denormalised (not rounded) to turn 6863 them into single precision values. */ 6864 6865 switch (opc1) { 6866 6867 case 0x34: // stfs (Store Float Single, PPC32 p518) 6868 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 6869 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 6870 /* Use Iop_TruncF64asF32 to truncate and possible denormalise 6871 the value to be stored in the correct way, without any 6872 rounding. */ 6873 storeBE( mkexpr(EA), 6874 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 6875 break; 6876 6877 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519) 6878 if (rA_addr == 0) 6879 return False; 6880 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 6881 assign( EA, ea_rA_simm(rA_addr, simm16) ); 6882 /* See comment for stfs */ 6883 storeBE( mkexpr(EA), 6884 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 6885 putIReg( rA_addr, mkexpr(EA) ); 6886 break; 6887 6888 case 0x36: // stfd (Store Float Double, PPC32 p513) 6889 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 6890 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 6891 storeBE( mkexpr(EA), mkexpr(frS) ); 6892 break; 6893 6894 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514) 6895 if (rA_addr == 0) 6896 return False; 6897 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 6898 assign( EA, ea_rA_simm(rA_addr, simm16) ); 6899 storeBE( mkexpr(EA), mkexpr(frS) ); 6900 putIReg( rA_addr, mkexpr(EA) ); 6901 break; 6902 6903 case 0x1F: 6904 if (b0 != 0) { 6905 vex_printf("dis_fp_store(ppc)(instr,b0)\n"); 6906 return False; 6907 } 6908 switch(opc2) { 6909 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521) 6910 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 6911 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6912 /* See note for stfs */ 6913 storeBE( mkexpr(EA), 6914 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 6915 break; 6916 6917 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520) 6918 if (rA_addr == 0) 6919 return False; 6920 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 6921 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 6922 /* See note for stfs */ 6923 storeBE( mkexpr(EA), 6924 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 6925 putIReg( rA_addr, mkexpr(EA) ); 6926 break; 6927 6928 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516) 6929 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 6930 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6931 storeBE( mkexpr(EA), mkexpr(frS) ); 6932 break; 6933 6934 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515) 6935 if (rA_addr == 0) 6936 return False; 6937 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 6938 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 6939 storeBE( mkexpr(EA), mkexpr(frS) ); 6940 putIReg( rA_addr, mkexpr(EA) ); 6941 break; 6942 6943 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517) 6944 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 6945 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 6946 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6947 storeBE( mkexpr(EA), 6948 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) ); 6949 break; 6950 6951 default: 6952 vex_printf("dis_fp_store(ppc)(opc2)\n"); 6953 return False; 6954 } 6955 break; 6956 6957 default: 6958 vex_printf("dis_fp_store(ppc)(opc1)\n"); 6959 return False; 6960 } 6961 return True; 6962} 6963 6964 6965 6966/* 6967 Floating Point Arith Instructions 6968*/ 6969static Bool dis_fp_arith ( UInt theInstr ) 6970{ 6971 /* A-Form */ 6972 UChar opc1 = ifieldOPC(theInstr); 6973 UChar frD_addr = ifieldRegDS(theInstr); 6974 UChar frA_addr = ifieldRegA(theInstr); 6975 UChar frB_addr = ifieldRegB(theInstr); 6976 UChar frC_addr = ifieldRegC(theInstr); 6977 UChar opc2 = ifieldOPClo5(theInstr); 6978 UChar flag_rC = ifieldBIT0(theInstr); 6979 6980 IRTemp frD = newTemp(Ity_F64); 6981 IRTemp frA = newTemp(Ity_F64); 6982 IRTemp frB = newTemp(Ity_F64); 6983 IRTemp frC = newTemp(Ity_F64); 6984 IRExpr* rm = get_IR_roundingmode(); 6985 6986 /* By default, we will examine the results of the operation and set 6987 fpscr[FPRF] accordingly. */ 6988 Bool set_FPRF = True; 6989 6990 /* By default, if flag_RC is set, we will clear cr1 after the 6991 operation. In reality we should set cr1 to indicate the 6992 exception status of the operation, but since we're not 6993 simulating exceptions, the exception status will appear to be 6994 zero. Hence cr1 should be cleared if this is a . form insn. */ 6995 Bool clear_CR1 = True; 6996 6997 assign( frA, getFReg(frA_addr)); 6998 assign( frB, getFReg(frB_addr)); 6999 assign( frC, getFReg(frC_addr)); 7000 7001 switch (opc1) { 7002 case 0x3B: 7003 switch (opc2) { 7004 case 0x12: // fdivs (Floating Divide Single, PPC32 p407) 7005 if (frC_addr != 0) 7006 return False; 7007 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7008 frD_addr, frA_addr, frB_addr); 7009 assign( frD, triop( Iop_DivF64r32, 7010 rm, mkexpr(frA), mkexpr(frB) )); 7011 break; 7012 7013 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430) 7014 if (frC_addr != 0) 7015 return False; 7016 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7017 frD_addr, frA_addr, frB_addr); 7018 assign( frD, triop( Iop_SubF64r32, 7019 rm, mkexpr(frA), mkexpr(frB) )); 7020 break; 7021 7022 case 0x15: // fadds (Floating Add Single, PPC32 p401) 7023 if (frC_addr != 0) 7024 return False; 7025 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7026 frD_addr, frA_addr, frB_addr); 7027 assign( frD, triop( Iop_AddF64r32, 7028 rm, mkexpr(frA), mkexpr(frB) )); 7029 break; 7030 7031 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428) 7032 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 7033 if (frA_addr != 0 || frC_addr != 0) 7034 return False; 7035 DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"", 7036 frD_addr, frB_addr); 7037 // however illogically, on ppc970 this insn behaves identically 7038 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32. 7039 assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) )); 7040 break; 7041 7042 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421) 7043 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7044 if (frA_addr != 0 || frC_addr != 0) 7045 return False; 7046 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"", 7047 frD_addr, frB_addr); 7048 { IRExpr* ieee_one 7049 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 7050 assign( frD, triop( Iop_DivF64r32, 7051 rm, 7052 ieee_one, mkexpr(frB) )); 7053 } 7054 break; 7055 7056 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414) 7057 if (frB_addr != 0) 7058 return False; 7059 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7060 frD_addr, frA_addr, frC_addr); 7061 assign( frD, triop( Iop_MulF64r32, 7062 rm, mkexpr(frA), mkexpr(frC) )); 7063 break; 7064 7065 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single) 7066 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7067 // Undocumented instruction? 7068 if (frA_addr != 0 || frC_addr != 0) 7069 return False; 7070 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"", 7071 frD_addr, frB_addr); 7072 assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) ); 7073 break; 7074 7075 default: 7076 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n"); 7077 return False; 7078 } 7079 break; 7080 7081 case 0x3F: 7082 switch (opc2) { 7083 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406) 7084 if (frC_addr != 0) 7085 return False; 7086 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7087 frD_addr, frA_addr, frB_addr); 7088 assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) ); 7089 break; 7090 7091 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429) 7092 if (frC_addr != 0) 7093 return False; 7094 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7095 frD_addr, frA_addr, frB_addr); 7096 assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) ); 7097 break; 7098 7099 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400) 7100 if (frC_addr != 0) 7101 return False; 7102 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7103 frD_addr, frA_addr, frB_addr); 7104 assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) ); 7105 break; 7106 7107 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427) 7108 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 7109 if (frA_addr != 0 || frC_addr != 0) 7110 return False; 7111 DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"", 7112 frD_addr, frB_addr); 7113 assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) ); 7114 break; 7115 7116 case 0x17: { // fsel (Floating Select, PPC32 p426) 7117 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7118 IRTemp cc = newTemp(Ity_I32); 7119 IRTemp cc_b0 = newTemp(Ity_I32); 7120 7121 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7122 frD_addr, frA_addr, frC_addr, frB_addr); 7123 7124 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40 7125 // => GT|EQ == (cc & 0x1 == 0) 7126 assign( cc, binop(Iop_CmpF64, mkexpr(frA), 7127 IRExpr_Const(IRConst_F64(0))) ); 7128 assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) ); 7129 7130 // frD = (frA >= 0.0) ? frC : frB 7131 // = (cc_b0 == 0) ? frC : frB 7132 assign( frD, 7133 IRExpr_Mux0X( 7134 unop(Iop_1Uto8, 7135 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0))), 7136 mkexpr(frB), 7137 mkexpr(frC) )); 7138 7139 /* One of the rare ones which don't mess with FPRF */ 7140 set_FPRF = False; 7141 break; 7142 } 7143 7144 case 0x18: // fre (Floating Reciprocal Estimate) 7145 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7146 // Note: unclear whether this insn really exists or not 7147 // ppc970 doesn't have it, but POWER5 does 7148 if (frA_addr != 0 || frC_addr != 0) 7149 return False; 7150 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"", 7151 frD_addr, frB_addr); 7152 { IRExpr* ieee_one 7153 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 7154 assign( frD, triop( Iop_DivF64, 7155 rm, 7156 ieee_one, mkexpr(frB) )); 7157 } 7158 break; 7159 7160 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413) 7161 if (frB_addr != 0) 7162 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n"); 7163 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7164 frD_addr, frA_addr, frC_addr); 7165 assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) ); 7166 break; 7167 7168 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424) 7169 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7170 if (frA_addr != 0 || frC_addr != 0) 7171 return False; 7172 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"", 7173 frD_addr, frB_addr); 7174 assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) ); 7175 break; 7176 7177 default: 7178 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n"); 7179 return False; 7180 } 7181 break; 7182 7183 default: 7184 vex_printf("dis_fp_arith(ppc)(opc1)\n"); 7185 return False; 7186 } 7187 7188 putFReg( frD_addr, mkexpr(frD) ); 7189 7190 if (set_FPRF) { 7191 // XXX XXX XXX FIXME 7192 // set FPRF from frD 7193 } 7194 7195 if (flag_rC && clear_CR1) { 7196 putCR321( 1, mkU8(0) ); 7197 putCR0( 1, mkU8(0) ); 7198 } 7199 7200 return True; 7201} 7202 7203 7204 7205/* 7206 Floating Point Mult-Add Instructions 7207*/ 7208static Bool dis_fp_multadd ( UInt theInstr ) 7209{ 7210 /* A-Form */ 7211 UChar opc1 = ifieldOPC(theInstr); 7212 UChar frD_addr = ifieldRegDS(theInstr); 7213 UChar frA_addr = ifieldRegA(theInstr); 7214 UChar frB_addr = ifieldRegB(theInstr); 7215 UChar frC_addr = ifieldRegC(theInstr); 7216 UChar opc2 = ifieldOPClo5(theInstr); 7217 UChar flag_rC = ifieldBIT0(theInstr); 7218 7219 IRTemp frD = newTemp(Ity_F64); 7220 IRTemp frA = newTemp(Ity_F64); 7221 IRTemp frB = newTemp(Ity_F64); 7222 IRTemp frC = newTemp(Ity_F64); 7223 IRTemp rmt = newTemp(Ity_I32); 7224 IRExpr* rm; 7225 7226 /* By default, we will examine the results of the operation and set 7227 fpscr[FPRF] accordingly. */ 7228 Bool set_FPRF = True; 7229 7230 /* By default, if flag_RC is set, we will clear cr1 after the 7231 operation. In reality we should set cr1 to indicate the 7232 exception status of the operation, but since we're not 7233 simulating exceptions, the exception status will appear to be 7234 zero. Hence cr1 should be cleared if this is a . form insn. */ 7235 Bool clear_CR1 = True; 7236 7237 /* Bind the rounding mode expression to a temp; there's no 7238 point in creating gratuitous CSEs, as we know we'll need 7239 to use it twice. */ 7240 assign( rmt, get_IR_roundingmode() ); 7241 rm = mkexpr(rmt); 7242 7243 assign( frA, getFReg(frA_addr)); 7244 assign( frB, getFReg(frB_addr)); 7245 assign( frC, getFReg(frC_addr)); 7246 7247 /* The rounding in this is all a bit dodgy. The idea is to only do 7248 one rounding. That clearly isn't achieveable without dedicated 7249 four-input IR primops, although in the single precision case we 7250 can sort-of simulate it by doing the inner multiply in double 7251 precision. 7252 7253 In the negated cases, the negation happens after rounding. */ 7254 7255 switch (opc1) { 7256 case 0x3B: 7257 switch (opc2) { 7258 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412) 7259 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7260 frD_addr, frA_addr, frC_addr, frB_addr); 7261 assign( frD, qop( Iop_MSubF64r32, rm, 7262 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 7263 break; 7264 7265 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409) 7266 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7267 frD_addr, frA_addr, frC_addr, frB_addr); 7268 assign( frD, qop( Iop_MAddF64r32, rm, 7269 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 7270 break; 7271 7272 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420) 7273 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7274 frD_addr, frA_addr, frC_addr, frB_addr); 7275 assign( frD, unop( Iop_NegF64, 7276 qop( Iop_MSubF64r32, rm, 7277 mkexpr(frA), mkexpr(frC), mkexpr(frB) ))); 7278 break; 7279 7280 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418) 7281 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7282 frD_addr, frA_addr, frC_addr, frB_addr); 7283 assign( frD, unop( Iop_NegF64, 7284 qop( Iop_MAddF64r32, rm, 7285 mkexpr(frA), mkexpr(frC), mkexpr(frB) ))); 7286 break; 7287 7288 default: 7289 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n"); 7290 return False; 7291 } 7292 break; 7293 7294 case 0x3F: 7295 switch (opc2) { 7296 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411) 7297 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7298 frD_addr, frA_addr, frC_addr, frB_addr); 7299 assign( frD, qop( Iop_MSubF64, rm, 7300 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 7301 break; 7302 7303 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408) 7304 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7305 frD_addr, frA_addr, frC_addr, frB_addr); 7306 assign( frD, qop( Iop_MAddF64, rm, 7307 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 7308 break; 7309 7310 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419) 7311 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7312 frD_addr, frA_addr, frC_addr, frB_addr); 7313 assign( frD, unop( Iop_NegF64, 7314 qop( Iop_MSubF64, rm, 7315 mkexpr(frA), mkexpr(frC), mkexpr(frB) ))); 7316 break; 7317 7318 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417) 7319 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7320 frD_addr, frA_addr, frC_addr, frB_addr); 7321 assign( frD, unop( Iop_NegF64, 7322 qop( Iop_MAddF64, rm, 7323 mkexpr(frA), mkexpr(frC), mkexpr(frB) ))); 7324 break; 7325 7326 default: 7327 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n"); 7328 return False; 7329 } 7330 break; 7331 7332 default: 7333 vex_printf("dis_fp_multadd(ppc)(opc1)\n"); 7334 return False; 7335 } 7336 7337 putFReg( frD_addr, mkexpr(frD) ); 7338 7339 if (set_FPRF) { 7340 // XXX XXX XXX FIXME 7341 // set FPRF from frD 7342 } 7343 7344 if (flag_rC && clear_CR1) { 7345 putCR321( 1, mkU8(0) ); 7346 putCR0( 1, mkU8(0) ); 7347 } 7348 7349 return True; 7350} 7351 7352/* 7353 * fe_flag is set to 1 if any of the following conditions occurs: 7354 * - The floating-point operand in register FRB is a Zero, a 7355 * NaN, an Infinity, or a negative value. 7356 * - e_b is less than or equal to: -970 for double precision; -103 for single precision 7357 * Otherwise fe_flag is set to 0. 7358 * 7359 * fg_flag is set to 1 if either of the following conditions occurs. 7360 * - The floating-point operand in register FRB is a Zero, an 7361 * Infinity, or a denormalized value. 7362 * Otherwise fg_flag is set to 0. 7363 * 7364 */ 7365static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 7366{ 7367 // The following temps are for holding intermediate results 7368 IRTemp e_b = newTemp(Ity_I32); 7369 IRExpr * fe_flag, * fg_flag; 7370 IRTemp frB_exp_shR = newTemp(Ity_I32); 7371 UInt bias = sp? 127 : 1023; 7372 IRExpr * frbNaN, * frbDenorm, * frBNeg; 7373 IRExpr * eb_LTE; 7374 IRTemp frbZero_tmp = newTemp(Ity_I1); 7375 IRTemp frbInf_tmp = newTemp(Ity_I1); 7376 *fe_flag_tmp = newTemp(Ity_I32); 7377 *fg_flag_tmp = newTemp(Ity_I32); 7378 assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) ); 7379 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 7380 7381 ////////////////// fe_flag tests BEGIN ////////////////////// 7382 /* We first do all tests that may result in setting fe_flag to '1'. 7383 * (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv() 7384 * for details.) 7385 */ 7386 frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int); 7387 assign( frbInf_tmp, is_Inf(frB_Int, sp) ); 7388 assign( frbZero_tmp, is_Zero(frB_Int, sp ) ); 7389 { 7390 // Test_value = -970 for double precision 7391 UInt test_value = sp ? 0xffffff99 : 0xfffffc36; 7392 eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) ); 7393 } 7394 frBNeg = binop( Iop_CmpEQ32, 7395 binop( Iop_Shr32, 7396 sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ), 7397 mkU8( 31 ) ), 7398 mkU32( 1 ) ); 7399 ////////////////// fe_flag tests END ////////////////////// 7400 7401 ////////////////// fg_flag tests BEGIN ////////////////////// 7402 /* 7403 * The following tests were already performed above in the fe_flag 7404 * tests. So these conditions will result in both fe_ and fg_ flags 7405 * being set. 7406 * - Test if FRB is Zero 7407 * - Test if FRB is an Infinity 7408 */ 7409 7410 /* 7411 * Test if FRB holds a denormalized value. A denormalized value is one where 7412 * the exp is 0 and the fraction is non-zero. 7413 */ 7414 if (sp) { 7415 IRTemp frac_part = newTemp(Ity_I32); 7416 assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) ); 7417 frbDenorm 7418 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 7419 binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) ); 7420 } else { 7421 IRExpr * hi32, * low32, * fraction_is_nonzero; 7422 IRTemp frac_part = newTemp(Ity_I64); 7423 7424 assign( frac_part, FP_FRAC_PART(frB_Int) ); 7425 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 7426 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 7427 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 7428 mkU32( 0 ) ); 7429 frbDenorm 7430 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 7431 fraction_is_nonzero ); 7432 } 7433 ////////////////// fg_flag tests END ////////////////////// 7434 7435 ///////////////////////// 7436 fe_flag = mkOR1( mkexpr( frbZero_tmp ), 7437 mkOR1( frbNaN, 7438 mkOR1( mkexpr( frbInf_tmp ), 7439 mkOR1( frBNeg, eb_LTE ) ) ) ); 7440 7441 fe_flag = unop(Iop_1Uto32, fe_flag); 7442 7443 fg_flag = mkOR1( mkexpr( frbZero_tmp ), 7444 mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) ); 7445 fg_flag = unop(Iop_1Uto32, fg_flag); 7446 assign (*fg_flag_tmp, fg_flag); 7447 assign (*fe_flag_tmp, fe_flag); 7448} 7449/* 7450 * fe_flag is set to 1 if any of the following conditions occurs: 7451 * - The double-precision floating-point operand in register FRA is a NaN or an 7452 * Infinity. 7453 * - The double-precision floating-point operand in register FRB is a Zero, a 7454 * NaN, or an Infinity. 7455 * - e_b is less than or equal to -1022. 7456 * - e_b is greater than or equal to 1021. 7457 * - The double-precision floating-point operand in register FRA is not a zero 7458 * and the difference, e_a - e_b, is greater than or equal to 1023. 7459 * - The double-precision floating-point operand in register FRA is not a zero 7460 * and the difference, e_a - e_b, is less than or equal to -1021. 7461 * - The double-precision floating-point operand in register FRA is not a zero 7462 * and e_a is less than or equal to -970 7463 * Otherwise fe_flag is set to 0. 7464 * 7465 * fg_flag is set to 1 if either of the following conditions occurs. 7466 * - The double-precision floating-point operand in register FRA is an Infinity. 7467 * - The double-precision floating-point operand in register FRB is a Zero, an 7468 * Infinity, or a denormalized value. 7469 * Otherwise fg_flag is set to 0. 7470 * 7471 */ 7472static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 7473{ 7474 // The following temps are for holding intermediate results 7475 IRTemp e_a = newTemp(Ity_I32); 7476 IRTemp e_b = newTemp(Ity_I32); 7477 IRTemp frA_exp_shR = newTemp(Ity_I32); 7478 IRTemp frB_exp_shR = newTemp(Ity_I32); 7479 7480 UInt bias = sp? 127 : 1023; 7481 *fe_flag_tmp = newTemp(Ity_I32); 7482 *fg_flag_tmp = newTemp(Ity_I32); 7483 7484 /* The following variables hold boolean results from tests 7485 * that are OR'ed together for setting the fe_ and fg_ flags. 7486 * For some cases, the booleans are used more than once, so 7487 * I make those IRTemp's instead of IRExpr's. 7488 */ 7489 IRExpr * fraNaN, * frbNaN, * frbDenorm; 7490 IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE; 7491 IRTemp fraInf_tmp = newTemp(Ity_I1); 7492 IRTemp frbZero_tmp = newTemp(Ity_I1); 7493 IRTemp frbInf_tmp = newTemp(Ity_I1); 7494 IRTemp fraNotZero_tmp = newTemp(Ity_I1); 7495 7496/* The following are the flags that are set by OR'ing the results of 7497 * all the tests done for tdiv. These flags are the input to the specified CR. 7498 */ 7499 IRExpr * fe_flag, * fg_flag; 7500 7501 // Create temps that will be used throughout the following tests. 7502 assign( frA_exp_shR, fp_exp_part( frA_int, sp ) ); 7503 assign( frB_exp_shR, fp_exp_part( frB_int, sp ) ); 7504 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */ 7505 assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) )); 7506 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 7507 7508 7509 ////////////////// fe_flag tests BEGIN ////////////////////// 7510 /* We first do all tests that may result in setting fe_flag to '1'. */ 7511 7512 /* 7513 * Test if the double-precision floating-point operand in register FRA is 7514 * a NaN: 7515 */ 7516 fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int); 7517 /* 7518 * Test if the double-precision floating-point operand in register FRA is 7519 * an Infinity. 7520 */ 7521 assign(fraInf_tmp, is_Inf(frA_int, sp)); 7522 7523 /* 7524 * Test if the double-precision floating-point operand in register FRB is 7525 * a NaN: 7526 */ 7527 frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int); 7528 /* 7529 * Test if the double-precision floating-point operand in register FRB is 7530 * an Infinity. 7531 */ 7532 assign( frbInf_tmp, is_Inf(frB_int, sp) ); 7533 /* 7534 * Test if the double-precision floating-point operand in register FRB is 7535 * a Zero. 7536 */ 7537 assign( frbZero_tmp, is_Zero(frB_int, sp) ); 7538 7539 /* 7540 * Test if e_b <= -1022 for double precision; 7541 * or e_b <= -126 for single precision 7542 */ 7543 { 7544 UInt test_value = sp ? 0xffffff82 : 0xfffffc02; 7545 eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value)); 7546 } 7547 7548 /* 7549 * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision; 7550 * or e_b >= -125 (125 < e_b) for single precision 7551 */ 7552 { 7553 Int test_value = sp ? 125 : 1021; 7554 eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b)); 7555 } 7556 7557 /* 7558 * Test if FRA != Zero and (e_a - e_b) >= bias 7559 */ 7560 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) ); 7561 ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ), 7562 binop( Iop_CmpLT32S, mkU32( bias ), 7563 binop( Iop_Sub32, mkexpr( e_a ), 7564 mkexpr( e_b ) ) ) ); 7565 7566 /* 7567 * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)] 7568 */ 7569 { 7570 UInt test_value = sp ? 0xffffff83 : 0xfffffc03; 7571 7572 ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ), 7573 binop( Iop_CmpLE32S, 7574 binop( Iop_Sub32, 7575 mkexpr( e_a ), 7576 mkexpr( e_b ) ), 7577 mkU32( test_value ) ) ); 7578 } 7579 7580 /* 7581 * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)] 7582 */ 7583 { 7584 UInt test_value = 0xfffffc36; //Int test_value = -970; 7585 7586 ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S, 7587 mkexpr( e_a ), 7588 mkU32( test_value ) ) ); 7589 } 7590 ////////////////// fe_flag tests END ////////////////////// 7591 7592 ////////////////// fg_flag tests BEGIN ////////////////////// 7593 /* 7594 * The following tests were already performed above in the fe_flag 7595 * tests. So these conditions will result in both fe_ and fg_ flags 7596 * being set. 7597 * - Test if FRA is an Infinity 7598 * - Test if FRB ix Zero 7599 * - Test if FRB is an Infinity 7600 */ 7601 7602 /* 7603 * Test if FRB holds a denormalized value. A denormalized value is one where 7604 * the exp is 0 and the fraction is non-zero. 7605 */ 7606 { 7607 IRExpr * fraction_is_nonzero; 7608 7609 if (sp) { 7610 fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int), 7611 mkU32( 0 ) ); 7612 } else { 7613 IRExpr * hi32, * low32; 7614 IRTemp frac_part = newTemp(Ity_I64); 7615 assign( frac_part, FP_FRAC_PART(frB_int) ); 7616 7617 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 7618 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 7619 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 7620 mkU32( 0 ) ); 7621 } 7622 frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), 7623 mkU32( 0x0 ) ), fraction_is_nonzero ); 7624 7625 } 7626 ////////////////// fg_flag tests END ////////////////////// 7627 7628 fe_flag 7629 = mkOR1( 7630 fraNaN, 7631 mkOR1( 7632 mkexpr( fraInf_tmp ), 7633 mkOR1( 7634 mkexpr( frbZero_tmp ), 7635 mkOR1( 7636 frbNaN, 7637 mkOR1( 7638 mkexpr( frbInf_tmp ), 7639 mkOR1( eb_LTE, 7640 mkOR1( eb_GTE, 7641 mkOR1( ea_eb_GTE, 7642 mkOR1( ea_eb_LTE, 7643 ea_LTE ) ) ) ) ) ) ) ) ); 7644 7645 fe_flag = unop(Iop_1Uto32, fe_flag); 7646 7647 fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ), 7648 mkOR1( mkexpr( frbInf_tmp ), 7649 frbDenorm ) ) ); 7650 fg_flag = unop(Iop_1Uto32, fg_flag); 7651 assign(*fe_flag_tmp, fe_flag); 7652 assign(*fg_flag_tmp, fg_flag); 7653} 7654 7655/* See description for _do_fp_tdiv() above. */ 7656static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int) 7657{ 7658 IRTemp fe_flag, fg_flag; 7659 ///////////////////////// 7660 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 7661 * where fl_flag == 1 on ppc64. 7662 */ 7663 IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE)); 7664 fe_flag = fg_flag = IRTemp_INVALID; 7665 _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag); 7666 return binop( Iop_Or32, 7667 binop( Iop_Or32, 7668 binop( Iop_Shl32, fl_flag, mkU8( 3 ) ), 7669 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 7670 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ); 7671} 7672 7673static Bool dis_fp_tests ( UInt theInstr ) 7674{ 7675 UChar opc1 = ifieldOPC(theInstr); 7676 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 7677 UChar frB_addr = ifieldRegB(theInstr); 7678 UChar b0 = ifieldBIT0(theInstr); 7679 UInt opc2 = ifieldOPClo10(theInstr); 7680 IRTemp frB_I64 = newTemp(Ity_I64); 7681 7682 if (opc1 != 0x3F || b0 != 0 ){ 7683 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 7684 return False; 7685 } 7686 assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) ); 7687 7688 switch (opc2) { 7689 case 0x080: // ftdiv 7690 { 7691 UChar frA_addr = ifieldRegA(theInstr); 7692 IRTemp frA_I64 = newTemp(Ity_I64); 7693 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 7694 if (b21to22 != 0 ) { 7695 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 7696 return False; 7697 } 7698 7699 assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) ); 7700 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 7701 7702 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 7703 break; 7704 } 7705 case 0x0A0: // ftsqrt 7706 { 7707 IRTemp flags = newTemp(Ity_I32); 7708 IRTemp fe_flag, fg_flag; 7709 fe_flag = fg_flag = IRTemp_INVALID; 7710 UChar b18to22 = toUChar( IFIELD( theInstr, 18, 5 ) ); 7711 if ( b18to22 != 0) { 7712 vex_printf("dis_fp_tests(ppc)(ftsqrt)\n"); 7713 return False; 7714 } 7715 DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr); 7716 do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag); 7717 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 7718 * where fl_flag == 1 on ppc64. 7719 */ 7720 assign( flags, 7721 binop( Iop_Or32, 7722 binop( Iop_Or32, mkU32( 8 ), // fl_flag 7723 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 7724 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 7725 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 7726 break; 7727 } 7728 7729 default: 7730 vex_printf("dis_fp_tests(ppc)(opc2)\n"); 7731 return False; 7732 7733 } 7734 return True; 7735} 7736 7737/* 7738 Floating Point Compare Instructions 7739*/ 7740static Bool dis_fp_cmp ( UInt theInstr ) 7741{ 7742 /* X-Form */ 7743 UChar opc1 = ifieldOPC(theInstr); 7744 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 7745 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 7746 UChar frA_addr = ifieldRegA(theInstr); 7747 UChar frB_addr = ifieldRegB(theInstr); 7748 UInt opc2 = ifieldOPClo10(theInstr); 7749 UChar b0 = ifieldBIT0(theInstr); 7750 7751 IRTemp ccIR = newTemp(Ity_I32); 7752 IRTemp ccPPC32 = newTemp(Ity_I32); 7753 7754 IRTemp frA = newTemp(Ity_F64); 7755 IRTemp frB = newTemp(Ity_F64); 7756 7757 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) { 7758 vex_printf("dis_fp_cmp(ppc)(instr)\n"); 7759 return False; 7760 } 7761 7762 assign( frA, getFReg(frA_addr)); 7763 assign( frB, getFReg(frB_addr)); 7764 7765 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) ); 7766 7767 /* Map compare result from IR to PPC32 */ 7768 /* 7769 FP cmp result | PPC | IR 7770 -------------------------- 7771 UN | 0x1 | 0x45 7772 EQ | 0x2 | 0x40 7773 GT | 0x4 | 0x00 7774 LT | 0x8 | 0x01 7775 */ 7776 7777 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2) 7778 // | ((ccIR ^ (ccIR>>6)) & 1) 7779 assign( 7780 ccPPC32, 7781 binop( 7782 Iop_Shl32, 7783 mkU32(1), 7784 unop( 7785 Iop_32to8, 7786 binop( 7787 Iop_Or32, 7788 binop( 7789 Iop_And32, 7790 unop( 7791 Iop_Not32, 7792 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5)) 7793 ), 7794 mkU32(2) 7795 ), 7796 binop( 7797 Iop_And32, 7798 binop( 7799 Iop_Xor32, 7800 mkexpr(ccIR), 7801 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6)) 7802 ), 7803 mkU32(1) 7804 ) 7805 ) 7806 ) 7807 ) 7808 ); 7809 7810 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 7811 7812 /* CAB: TODO?: Support writing cc to FPSCR->FPCC ? 7813 putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 ); 7814 */ 7815 // XXX XXX XXX FIXME 7816 // Also write the result into FPRF (it's not entirely clear how) 7817 7818 /* Note: Differences between fcmpu and fcmpo are only in exception 7819 flag settings, which aren't supported anyway. */ 7820 switch (opc2) { 7821 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403) 7822 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 7823 break; 7824 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402) 7825 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 7826 break; 7827 default: 7828 vex_printf("dis_fp_cmp(ppc)(opc2)\n"); 7829 return False; 7830 } 7831 return True; 7832} 7833 7834 7835 7836/* 7837 Floating Point Rounding/Conversion Instructions 7838*/ 7839static Bool dis_fp_round ( UInt theInstr ) 7840{ 7841 /* X-Form */ 7842 UChar opc1 = ifieldOPC(theInstr); 7843 UChar b16to20 = ifieldRegA(theInstr); 7844 UChar frD_addr = ifieldRegDS(theInstr); 7845 UChar frB_addr = ifieldRegB(theInstr); 7846 UInt opc2 = ifieldOPClo10(theInstr); 7847 UChar flag_rC = ifieldBIT0(theInstr); 7848 7849 IRTemp frD = newTemp(Ity_F64); 7850 IRTemp frB = newTemp(Ity_F64); 7851 IRTemp r_tmp32 = newTemp(Ity_I32); 7852 IRTemp r_tmp64 = newTemp(Ity_I64); 7853 IRExpr* rm = get_IR_roundingmode(); 7854 7855 /* By default, we will examine the results of the operation and set 7856 fpscr[FPRF] accordingly. */ 7857 Bool set_FPRF = True; 7858 7859 /* By default, if flag_RC is set, we will clear cr1 after the 7860 operation. In reality we should set cr1 to indicate the 7861 exception status of the operation, but since we're not 7862 simulating exceptions, the exception status will appear to be 7863 zero. Hence cr1 should be cleared if this is a . form insn. */ 7864 Bool clear_CR1 = True; 7865 if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) { 7866 vex_printf("dis_fp_round(ppc)(instr)\n"); 7867 return False; 7868 } 7869 7870 assign( frB, getFReg(frB_addr)); 7871 if (opc1 == 0x3B) { 7872 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because 7873 * they're very similar to the other instructions handled here, but have 7874 * a different primary opcode. 7875 */ 7876 switch (opc2) { 7877 case 0x34E: // fcfids (Float convert from signed DWord to single precision) 7878 DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7879 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 7880 assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm, 7881 mkexpr( r_tmp64 ) ) ) ); 7882 goto putFR; 7883 7884 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision) 7885 DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7886 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 7887 assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) ); 7888 goto putFR; 7889 } 7890 } 7891 7892 7893 switch (opc2) { 7894 case 0x00C: // frsp (Float Round to Single, PPC32 p423) 7895 DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7896 assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) )); 7897 break; 7898 7899 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404) 7900 DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7901 assign( r_tmp32, 7902 binop(Iop_F64toI32S, rm, mkexpr(frB)) ); 7903 assign( frD, unop( Iop_ReinterpI64asF64, 7904 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 7905 /* FPRF is undefined after fctiw. Leave unchanged. */ 7906 set_FPRF = False; 7907 break; 7908 7909 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405) 7910 DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7911 assign( r_tmp32, 7912 binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) )); 7913 assign( frD, unop( Iop_ReinterpI64asF64, 7914 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 7915 /* FPRF is undefined after fctiwz. Leave unchanged. */ 7916 set_FPRF = False; 7917 break; 7918 7919 case 0x08F: case 0x08E: // fctiwu[z] 7920 DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "", 7921 flag_rC ? ".":"", frD_addr, frB_addr); 7922 assign( r_tmp32, 7923 binop( Iop_F64toI32U, 7924 opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm, 7925 mkexpr( frB ) ) ); 7926 assign( frD, unop( Iop_ReinterpI64asF64, 7927 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 7928 /* FPRF is undefined after fctiwz. Leave unchanged. */ 7929 set_FPRF = False; 7930 break; 7931 7932 7933 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437) 7934 DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7935 assign( r_tmp64, 7936 binop(Iop_F64toI64S, rm, mkexpr(frB)) ); 7937 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 7938 /* FPRF is undefined after fctid. Leave unchanged. */ 7939 set_FPRF = False; 7940 break; 7941 7942 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437) 7943 DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7944 assign( r_tmp64, 7945 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 7946 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 7947 /* FPRF is undefined after fctidz. Leave unchanged. */ 7948 set_FPRF = False; 7949 break; 7950 7951 case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero]) 7952 { 7953 DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z", 7954 flag_rC ? ".":"", frD_addr, frB_addr); 7955 assign( r_tmp64, 7956 binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) ); 7957 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 7958 /* FPRF is undefined after fctidz. Leave unchanged. */ 7959 set_FPRF = False; 7960 break; 7961 } 7962 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434) 7963 DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7964 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 7965 assign( frD, 7966 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) ); 7967 break; 7968 7969 case 0x3CE: // fcfidu (Float convert from unsigned DWord) 7970 DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7971 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 7972 assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) ); 7973 break; 7974 7975 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim 7976 switch(opc2) { 7977 case 0x188: // frin (Floating Round to Integer Nearest) 7978 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7979 assign( r_tmp64, 7980 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) ); 7981 break; 7982 case 0x1A8: // friz (Floating Round to Integer Toward Zero) 7983 DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7984 assign( r_tmp64, 7985 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 7986 break; 7987 case 0x1C8: // frip (Floating Round to Integer Plus) 7988 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7989 assign( r_tmp64, 7990 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) ); 7991 break; 7992 case 0x1E8: // frim (Floating Round to Integer Minus) 7993 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 7994 assign( r_tmp64, 7995 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) ); 7996 break; 7997 } 7998 7999 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 8000 /* F64 has only log10(2**52) significant digits anyway */ 8001 /* need to preserve sign of zero */ 8002 /* frD = (fabs(frB) > 9e18) ? frB : 8003 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */ 8004 assign(frD, IRExpr_Mux0X( unop(Iop_32to8, 8005 binop(Iop_CmpF64, 8006 IRExpr_Const(IRConst_F64(9e18)), 8007 unop(Iop_AbsF64, mkexpr(frB)))), 8008 IRExpr_Mux0X(unop(Iop_32to8, 8009 binop(Iop_Shr32, 8010 unop(Iop_64HIto32, 8011 unop(Iop_ReinterpF64asI64, 8012 mkexpr(frB))), mkU8(31))), 8013 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ), 8014 unop(Iop_NegF64, 8015 unop( Iop_AbsF64, 8016 binop(Iop_I64StoF64, mkU32(0), 8017 mkexpr(r_tmp64)) )) ), 8018 mkexpr(frB))); 8019 break; 8020 8021 default: 8022 vex_printf("dis_fp_round(ppc)(opc2)\n"); 8023 return False; 8024 } 8025putFR: 8026 putFReg( frD_addr, mkexpr(frD) ); 8027 8028 if (set_FPRF) { 8029 // XXX XXX XXX FIXME 8030 // set FPRF from frD 8031 } 8032 8033 if (flag_rC && clear_CR1) { 8034 putCR321( 1, mkU8(0) ); 8035 putCR0( 1, mkU8(0) ); 8036 } 8037 8038 return True; 8039} 8040 8041/* 8042 Floating Point Pair Instructions 8043*/ 8044static Bool dis_fp_pair ( UInt theInstr ) 8045{ 8046 /* X-Form/DS-Form */ 8047 UChar opc1 = ifieldOPC(theInstr); 8048 UChar frT_hi_addr = ifieldRegDS(theInstr); 8049 UChar frT_lo_addr = frT_hi_addr + 1; 8050 UChar rA_addr = ifieldRegA(theInstr); 8051 UChar rB_addr = ifieldRegB(theInstr); 8052 UInt uimm16 = ifieldUIMM16(theInstr); 8053 Int simm16 = extend_s_16to32(uimm16); 8054 UInt opc2 = ifieldOPClo10(theInstr); 8055 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8056 IRTemp EA_hi = newTemp(ty); 8057 IRTemp EA_lo = newTemp(ty); 8058 IRTemp frT_hi = newTemp(Ity_F64); 8059 IRTemp frT_lo = newTemp(Ity_F64); 8060 UChar b0 = ifieldBIT0(theInstr); 8061 Bool is_load = 0; 8062 8063 if ((frT_hi_addr %2) != 0) { 8064 vex_printf("dis_fp_pair(ppc) : odd frT register\n"); 8065 return False; 8066 } 8067 8068 switch (opc1) { 8069 case 0x1F: // register offset 8070 switch(opc2) { 8071 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125) 8072 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 8073 is_load = 1; 8074 break; 8075 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125) 8076 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 8077 break; 8078 default: 8079 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n"); 8080 return False; 8081 } 8082 8083 if (b0 != 0) { 8084 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n"); 8085 return False; 8086 } 8087 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) ); 8088 break; 8089 case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125) 8090 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 8091 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 8092 is_load = 1; 8093 break; 8094 case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125) 8095 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 8096 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 8097 break; 8098 default: // immediate offset 8099 vex_printf("dis_fp_pair(ppc)(instr)\n"); 8100 return False; 8101 } 8102 8103 if (mode64) 8104 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) ); 8105 else 8106 assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) ); 8107 8108 assign( frT_hi, getFReg(frT_hi_addr) ); 8109 assign( frT_lo, getFReg(frT_lo_addr) ); 8110 8111 if (is_load) { 8112 putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) ); 8113 putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) ); 8114 } else { 8115 storeBE( mkexpr(EA_hi), mkexpr(frT_hi) ); 8116 storeBE( mkexpr(EA_lo), mkexpr(frT_lo) ); 8117 } 8118 8119 return True; 8120} 8121 8122 8123/* 8124 Floating Point Move Instructions 8125*/ 8126static Bool dis_fp_move ( UInt theInstr ) 8127{ 8128 /* X-Form */ 8129 UChar opc1 = ifieldOPC(theInstr); 8130 UChar frD_addr = ifieldRegDS(theInstr); 8131 UChar frA_addr = ifieldRegA(theInstr); 8132 UChar frB_addr = ifieldRegB(theInstr); 8133 UInt opc2 = ifieldOPClo10(theInstr); 8134 UChar flag_rC = ifieldBIT0(theInstr); 8135 8136 IRTemp frD = newTemp(Ity_F64); 8137 IRTemp frB = newTemp(Ity_F64); 8138 IRTemp itmpB = newTemp(Ity_F64); 8139 IRTemp frA; 8140 IRTemp signA; 8141 IRTemp hiD; 8142 8143 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) { 8144 vex_printf("dis_fp_move(ppc)(instr)\n"); 8145 return False; 8146 } 8147 8148 assign( frB, getFReg(frB_addr)); 8149 8150 switch (opc2) { 8151 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126) 8152 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr, 8153 frB_addr); 8154 signA = newTemp(Ity_I32); 8155 hiD = newTemp(Ity_I32); 8156 itmpB = newTemp(Ity_I64); 8157 frA = newTemp(Ity_F64); 8158 assign( frA, getFReg(frA_addr) ); 8159 8160 /* get A's sign bit */ 8161 assign(signA, binop(Iop_And32, 8162 unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64, 8163 mkexpr(frA))), 8164 mkU32(0x80000000)) ); 8165 8166 assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) ); 8167 8168 /* mask off B's sign bit and or in A's sign bit */ 8169 assign(hiD, binop(Iop_Or32, 8170 binop(Iop_And32, 8171 unop(Iop_64HIto32, 8172 mkexpr(itmpB)), /* frB's high 32 bits */ 8173 mkU32(0x7fffffff)), 8174 mkexpr(signA)) ); 8175 8176 /* combine hiD/loB into frD */ 8177 assign( frD, unop(Iop_ReinterpI64asF64, 8178 binop(Iop_32HLto64, 8179 mkexpr(hiD), 8180 unop(Iop_64to32, 8181 mkexpr(itmpB)))) ); /* frB's low 32 bits */ 8182 break; 8183 8184 case 0x028: // fneg (Floating Negate, PPC32 p416) 8185 DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8186 assign( frD, unop( Iop_NegF64, mkexpr(frB) )); 8187 break; 8188 8189 case 0x048: // fmr (Floating Move Register, PPC32 p410) 8190 DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8191 assign( frD, mkexpr(frB) ); 8192 break; 8193 8194 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415) 8195 DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8196 assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) ))); 8197 break; 8198 8199 case 0x108: // fabs (Floating Absolute Value, PPC32 p399) 8200 DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8201 assign( frD, unop( Iop_AbsF64, mkexpr(frB) )); 8202 break; 8203 8204 default: 8205 vex_printf("dis_fp_move(ppc)(opc2)\n"); 8206 return False; 8207 } 8208 8209 putFReg( frD_addr, mkexpr(frD) ); 8210 8211 /* None of these change FPRF. cr1 is set in the usual way though, 8212 if flag_rC is set. */ 8213 8214 if (flag_rC) { 8215 putCR321( 1, mkU8(0) ); 8216 putCR0( 1, mkU8(0) ); 8217 } 8218 8219 return True; 8220} 8221 8222 8223 8224/* 8225 Floating Point Status/Control Register Instructions 8226*/ 8227static Bool dis_fp_scr ( UInt theInstr ) 8228{ 8229 /* Many forms - see each switch case */ 8230 UChar opc1 = ifieldOPC(theInstr); 8231 UInt opc2 = ifieldOPClo10(theInstr); 8232 UChar flag_rC = ifieldBIT0(theInstr); 8233 8234 if (opc1 != 0x3F) { 8235 vex_printf("dis_fp_scr(ppc)(instr)\n"); 8236 return False; 8237 } 8238 8239 switch (opc2) { 8240 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479) 8241 // Bit crbD of the FPSCR is set. 8242 UChar crbD = ifieldRegDS(theInstr); 8243 UInt b11to20 = IFIELD(theInstr, 11, 10); 8244 8245 if (b11to20 != 0) { 8246 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n"); 8247 return False; 8248 } 8249 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD); 8250 putGST_masked( PPC_GST_FPSCR, mkU32(1<<(31-crbD)), 1<<(31-crbD) ); 8251 break; 8252 } 8253 8254 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465) 8255 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 8256 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 8257 UChar crfS = toUChar( IFIELD( theInstr, 18, 3 ) ); 8258 UChar b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) ); 8259 IRTemp tmp = newTemp(Ity_I32); 8260 IRExpr* fpscr_all; 8261 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) { 8262 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n"); 8263 return False; 8264 } 8265 DIP("mcrfs crf%d,crf%d\n", crfD, crfS); 8266 vassert(crfD < 8); 8267 vassert(crfS < 8); 8268 fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 8269 assign( tmp, binop(Iop_And32, 8270 binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))), 8271 mkU32(0xF)) ); 8272 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD ); 8273 break; 8274 } 8275 8276 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478) 8277 // Bit crbD of the FPSCR is cleared. 8278 UChar crbD = ifieldRegDS(theInstr); 8279 UInt b11to20 = IFIELD(theInstr, 11, 10); 8280 8281 if (b11to20 != 0) { 8282 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n"); 8283 return False; 8284 } 8285 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD); 8286 putGST_masked( PPC_GST_FPSCR, mkU32(0), 1<<(31-crbD) ); 8287 break; 8288 } 8289 8290 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481) 8291 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 8292 UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) ); 8293 UChar IMM = toUChar( IFIELD( theInstr, 12, 4 ) ); 8294 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 8295 8296 if (b16to22 != 0 || b11 != 0) { 8297 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n"); 8298 return False; 8299 } 8300 DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM); 8301 putGST_field( PPC_GST_FPSCR, mkU32(IMM), crfD ); 8302 break; 8303 } 8304 8305 case 0x247: { // mffs (Move from FPSCR, PPC32 p468) 8306 UChar frD_addr = ifieldRegDS(theInstr); 8307 UInt b11to20 = IFIELD(theInstr, 11, 10); 8308 IRExpr* fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 8309 8310 if (b11to20 != 0) { 8311 vex_printf("dis_fp_scr(ppc)(instr,mffs)\n"); 8312 return False; 8313 } 8314 DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr); 8315 putFReg( frD_addr, 8316 unop( Iop_ReinterpI64asF64, 8317 unop( Iop_32Uto64, fpscr_all ))); 8318 break; 8319 } 8320 8321 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480) 8322 UChar b25 = toUChar( IFIELD(theInstr, 25, 1) ); 8323 UChar FM = toUChar( IFIELD(theInstr, 17, 8) ); 8324 UChar frB_addr = ifieldRegB(theInstr); 8325 IRTemp frB = newTemp(Ity_F64); 8326 IRTemp rB_32 = newTemp(Ity_I32); 8327 Int i, mask; 8328 8329 if (b25 == 1) { 8330 /* new 64 bit move variant for power 6. If L field (bit 25) is 8331 * a one do a full 64 bit move. Note, the FPSCR is not really 8332 * properly modeled. This instruciton only changes the value of 8333 * the rounding mode. The HW exception bits do not get set in 8334 * the simulator. 1/12/09 8335 */ 8336 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr); 8337 mask = 0xFF; 8338 8339 } else { 8340 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr); 8341 // Build 32bit mask from FM: 8342 mask = 0; 8343 for (i=0; i<8; i++) { 8344 if ((FM & (1<<(7-i))) == 1) { 8345 mask |= 0xF << (7-i); 8346 } 8347 } 8348 } 8349 assign( frB, getFReg(frB_addr)); 8350 assign( rB_32, unop( Iop_64to32, 8351 unop( Iop_ReinterpF64asI64, mkexpr(frB) ))); 8352 putGST_masked( PPC_GST_FPSCR, mkexpr(rB_32), mask ); 8353 break; 8354 } 8355 8356 default: 8357 vex_printf("dis_fp_scr(ppc)(opc2)\n"); 8358 return False; 8359 } 8360 return True; 8361} 8362 8363 8364 8365/*------------------------------------------------------------*/ 8366/*--- AltiVec Instruction Translation ---*/ 8367/*------------------------------------------------------------*/ 8368 8369/* 8370 Altivec Cache Control Instructions (Data Streams) 8371*/ 8372static Bool dis_av_datastream ( UInt theInstr ) 8373{ 8374 /* X-Form */ 8375 UChar opc1 = ifieldOPC(theInstr); 8376 UChar flag_T = toUChar( IFIELD( theInstr, 25, 1 ) ); 8377 UChar flag_A = flag_T; 8378 UChar b23to24 = toUChar( IFIELD( theInstr, 23, 2 ) ); 8379 UChar STRM = toUChar( IFIELD( theInstr, 21, 2 ) ); 8380 UChar rA_addr = ifieldRegA(theInstr); 8381 UChar rB_addr = ifieldRegB(theInstr); 8382 UInt opc2 = ifieldOPClo10(theInstr); 8383 UChar b0 = ifieldBIT0(theInstr); 8384 8385 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) { 8386 vex_printf("dis_av_datastream(ppc)(instr)\n"); 8387 return False; 8388 } 8389 8390 switch (opc2) { 8391 case 0x156: // dst (Data Stream Touch, AV p115) 8392 DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "", 8393 rA_addr, rB_addr, STRM); 8394 break; 8395 8396 case 0x176: // dstst (Data Stream Touch for Store, AV p117) 8397 DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "", 8398 rA_addr, rB_addr, STRM); 8399 break; 8400 8401 case 0x336: // dss (Data Stream Stop, AV p114) 8402 if (rA_addr != 0 || rB_addr != 0) { 8403 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n"); 8404 return False; 8405 } 8406 if (flag_A == 0) { 8407 DIP("dss %d\n", STRM); 8408 } else { 8409 DIP("dssall\n"); 8410 } 8411 break; 8412 8413 default: 8414 vex_printf("dis_av_datastream(ppc)(opc2)\n"); 8415 return False; 8416 } 8417 return True; 8418} 8419 8420/* 8421 AltiVec Processor Control Instructions 8422*/ 8423static Bool dis_av_procctl ( UInt theInstr ) 8424{ 8425 /* VX-Form */ 8426 UChar opc1 = ifieldOPC(theInstr); 8427 UChar vD_addr = ifieldRegDS(theInstr); 8428 UChar vA_addr = ifieldRegA(theInstr); 8429 UChar vB_addr = ifieldRegB(theInstr); 8430 UInt opc2 = IFIELD( theInstr, 0, 11 ); 8431 8432 if (opc1 != 0x4) { 8433 vex_printf("dis_av_procctl(ppc)(instr)\n"); 8434 return False; 8435 } 8436 8437 switch (opc2) { 8438 case 0x604: // mfvscr (Move from VSCR, AV p129) 8439 if (vA_addr != 0 || vB_addr != 0) { 8440 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 8441 return False; 8442 } 8443 DIP("mfvscr v%d\n", vD_addr); 8444 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) ); 8445 break; 8446 8447 case 0x644: { // mtvscr (Move to VSCR, AV p130) 8448 IRTemp vB = newTemp(Ity_V128); 8449 if (vD_addr != 0 || vA_addr != 0) { 8450 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 8451 return False; 8452 } 8453 DIP("mtvscr v%d\n", vB_addr); 8454 assign( vB, getVReg(vB_addr)); 8455 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) ); 8456 break; 8457 } 8458 default: 8459 vex_printf("dis_av_procctl(ppc)(opc2)\n"); 8460 return False; 8461 } 8462 return True; 8463} 8464 8465/* 8466 * VSX scalar and vector convert instructions 8467 */ 8468static Bool 8469dis_vx_conv ( UInt theInstr, UInt opc2 ) 8470{ 8471 /* XX2-Form */ 8472 UChar opc1 = ifieldOPC( theInstr ); 8473 UChar XT = ifieldRegXT( theInstr ); 8474 UChar XB = ifieldRegXB( theInstr ); 8475 IRTemp xB, xB2; 8476 IRTemp b3, b2, b1, b0; 8477 xB = xB2 = IRTemp_INVALID; 8478 8479 if (opc1 != 0x3C) { 8480 vex_printf( "dis_vx_conv(ppc)(instr)\n" ); 8481 return False; 8482 } 8483 8484 /* Create and assign temps only as needed for the given instruction. */ 8485 switch (opc2) { 8486 // scalar double-precision floating point argument 8487 case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x090: 8488 xB = newTemp(Ity_F64); 8489 assign( xB, 8490 unop( Iop_ReinterpI64asF64, 8491 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 8492 break; 8493 // vector double-precision floating point arguments 8494 case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0: 8495 8496 xB = newTemp(Ity_F64); 8497 xB2 = newTemp(Ity_F64); 8498 assign( xB, 8499 unop( Iop_ReinterpI64asF64, 8500 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 8501 assign( xB2, 8502 unop( Iop_ReinterpI64asF64, 8503 unop( Iop_V128to64, getVSReg( XB ) ) ) ); 8504 break; 8505 // vector single precision or [un]signed integer word arguments 8506 case 0x130: case 0x392: case 0x330: case 0x310: case 0x110: 8507 case 0x1f0: case 0x1d0: 8508 b3 = b2 = b1 = b0 = IRTemp_INVALID; 8509 breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0); 8510 break; 8511 // vector [un]signed integer doubleword argument 8512 case 0x3f0: case 0x370: case 0x3d0: case 0x350: 8513 xB = newTemp(Ity_I64); 8514 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 8515 xB2 = newTemp(Ity_I64); 8516 assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) ); 8517 break; 8518 // scalar [un]signed integer doubleword argument 8519 case 0x2F0: case 0x2D0: 8520 xB = newTemp(Ity_I64); 8521 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 8522 break; 8523 // scalar single precision argument 8524 case 0x292: // xscvspdp 8525 xB = newTemp(Ity_I32); 8526 assign( xB, 8527 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 8528 break; 8529 8530 /* Certain instructions have their complete implementation in the main switch statement 8531 * that follows this one; thus we have a "do nothing" case for those instructions here. 8532 */ 8533 case 0x170: case 0x150: 8534 break; // do nothing 8535 8536 default: 8537 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 8538 return False; 8539 } 8540 8541 8542 switch (opc2) { 8543 case 0x2B0: 8544 // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert 8545 // to Signed Integer Doubleword format with Saturate) 8546 DIP("xscvdpsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 8547 putVSReg( XT, 8548 binop( Iop_64HLtoV128, binop( Iop_F64toI64S, 8549 mkU32( Irrm_ZERO ), 8550 mkexpr( xB ) ), mkU64( 0 ) ) ); 8551 break; 8552 case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and 8553 // Convert to Signed Integer Word format with Saturate) 8554 DIP("xscvdpsxws v%u,v%u\n", (UInt)XT, (UInt)XB); 8555 putVSReg( XT, 8556 binop( Iop_64HLtoV128, 8557 unop( Iop_32Sto64, 8558 binop( Iop_F64toI32S, 8559 mkU32( Irrm_ZERO ), 8560 mkexpr( xB ) ) ), 8561 mkU64( 0ULL ) ) ); 8562 break; 8563 case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert 8564 // to Unsigned Integer Doubleword format with Saturate) 8565 DIP("xscvdpuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 8566 putVSReg( XT, 8567 binop( Iop_64HLtoV128, 8568 binop( Iop_F64toI64U, 8569 mkU32( Irrm_ZERO ), 8570 mkexpr( xB ) ), 8571 mkU64( 0ULL ) ) ); 8572 break; 8573 case 0x2F0: 8574 // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to 8575 // Double-Precision format) 8576 DIP("xscvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 8577 putVSReg( XT, 8578 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 8579 binop( Iop_I64StoF64, get_IR_roundingmode(), 8580 mkexpr( xB ) ) ), 8581 mkU64( 0 ) ) ); 8582 break; 8583 case 0x2D0: 8584 // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to 8585 // Double-Precision format) 8586 DIP("xscvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 8587 putVSReg( XT, 8588 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 8589 binop( Iop_I64UtoF64, get_IR_roundingmode(), 8590 mkexpr( xB ) ) ), 8591 mkU64( 0 ) ) ); 8592 break; 8593 case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert 8594 // to Signed Integer Word format with Saturate) 8595 { 8596 IRTemp hiResult_32 = newTemp(Ity_I32); 8597 IRTemp loResult_32 = newTemp(Ity_I32); 8598 IRExpr* rmZero = mkU32(Irrm_ZERO); 8599 8600 DIP("xvcvdpsxws v%u,v%u\n", (UInt)XT, (UInt)XB); 8601 assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB))); 8602 assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2))); 8603 putVSReg( XT, 8604 binop( Iop_64HLtoV128, 8605 unop( Iop_32Sto64, mkexpr( hiResult_32 ) ), 8606 unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) ); 8607 break; 8608 } 8609 case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws 8610 // (VSX Vector truncate Single-Precision to integer and 8611 // Convert to [Un]signed Integer Word format with Saturate) 8612 { 8613 IRExpr * b0_result, * b1_result, * b2_result, * b3_result; 8614 IRTemp tempResult = newTemp(Ity_V128); 8615 IRTemp res0 = newTemp(Ity_I32); 8616 IRTemp res1 = newTemp(Ity_I32); 8617 IRTemp res2 = newTemp(Ity_I32); 8618 IRTemp res3 = newTemp(Ity_I32); 8619 IRTemp hi64 = newTemp(Ity_I64); 8620 IRTemp lo64 = newTemp(Ity_I64); 8621 Bool un_signed = (opc2 == 0x110); 8622 IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ; 8623 8624 DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB); 8625 /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN, 8626 * then result is set to 0x80000000. */ 8627 assign(tempResult, unop(op, getVSReg(XB))); 8628 assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) ); 8629 assign( lo64, unop(Iop_V128to64, mkexpr(tempResult)) ); 8630 assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) ); 8631 assign( res2, unop(Iop_64to32, mkexpr(hi64)) ); 8632 assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) ); 8633 assign( res0, unop(Iop_64to32, mkexpr(lo64)) ); 8634 8635 b3_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b3)), 8636 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 8637 mkexpr(res3), 8638 // then: result is 0x{8|0}80000000 8639 mkU32(un_signed ? 0x00000000 : 0x80000000)); 8640 b2_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b2)), 8641 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 8642 mkexpr(res2), 8643 // then: result is 0x{8|0}80000000 8644 mkU32(un_signed ? 0x00000000 : 0x80000000)); 8645 b1_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b1)), 8646 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 8647 mkexpr(res1), 8648 // then: result is 0x{8|0}80000000 8649 mkU32(un_signed ? 0x00000000 : 0x80000000)); 8650 b0_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b0)), 8651 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 8652 mkexpr(res0), 8653 // then: result is 0x{8|0}80000000 8654 mkU32(un_signed ? 0x00000000 : 0x80000000)); 8655 8656 putVSReg( XT, 8657 binop( Iop_64HLtoV128, 8658 binop( Iop_32HLto64, b3_result, b2_result ), 8659 binop( Iop_32HLto64, b1_result, b0_result ) ) ); 8660 break; 8661 } 8662 case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and 8663 // Convert to Single-Precision format 8664 DIP("xscvdpsp v%u,v%u\n", (UInt)XT, (UInt)XB); 8665 putVSReg( XT, 8666 binop( Iop_64HLtoV128, 8667 binop( Iop_32HLto64, 8668 unop( Iop_ReinterpF32asI32, 8669 unop( Iop_TruncF64asF32, 8670 binop( Iop_RoundF64toF32, 8671 get_IR_roundingmode(), 8672 mkexpr( xB ) ) ) ), 8673 mkU32( 0 ) ), 8674 mkU64( 0ULL ) ) ); 8675 break; 8676 case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer 8677 // and Convert to Unsigned Integer Word format with Saturate) 8678 DIP("xscvdpuxws v%u,v%u\n", (UInt)XT, (UInt)XB); 8679 putVSReg( XT, 8680 binop( Iop_64HLtoV128, 8681 binop( Iop_32HLto64, 8682 mkU32( 0 ), 8683 binop( Iop_F64toI32U, 8684 mkU32( Irrm_ZERO ), 8685 mkexpr( xB ) ) ), 8686 mkU64( 0ULL ) ) ); 8687 break; 8688 case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format) 8689 DIP("xscvspdp v%u,v%u\n", (UInt)XT, (UInt)XB); 8690 putVSReg( XT, 8691 binop( Iop_64HLtoV128, 8692 unop( Iop_ReinterpF64asI64, 8693 unop( Iop_F32toF64, 8694 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 8695 mkU64( 0ULL ) ) ); 8696 break; 8697 case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision 8698 // and Convert to Single-Precision format) 8699 DIP("xvcvdpsp v%u,v%u\n", (UInt)XT, (UInt)XB); 8700 putVSReg( XT, 8701 binop( Iop_64HLtoV128, 8702 binop( Iop_32HLto64, 8703 unop( Iop_ReinterpF32asI32, 8704 unop( Iop_TruncF64asF32, 8705 binop( Iop_RoundF64toF32, 8706 get_IR_roundingmode(), 8707 mkexpr( xB ) ) ) ), 8708 mkU32( 0 ) ), 8709 binop( Iop_32HLto64, 8710 unop( Iop_ReinterpF32asI32, 8711 unop( Iop_TruncF64asF32, 8712 binop( Iop_RoundF64toF32, 8713 get_IR_roundingmode(), 8714 mkexpr( xB2 ) ) ) ), 8715 mkU32( 0 ) ) ) ); 8716 break; 8717 case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer 8718 // and Convert to Unsigned Integer Doubleword format 8719 // with Saturate) 8720 DIP("xvcvdpuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 8721 putVSReg( XT, 8722 binop( Iop_64HLtoV128, 8723 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 8724 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 8725 break; 8726 case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and 8727 // Convert to Unsigned Integer Word format with Saturate) 8728 DIP("xvcvdpuxws v%u,v%u\n", (UInt)XT, (UInt)XB); 8729 putVSReg( XT, 8730 binop( Iop_64HLtoV128, 8731 binop( Iop_32HLto64, 8732 binop( Iop_F64toI32U, 8733 mkU32( Irrm_ZERO ), 8734 mkexpr( xB ) ), 8735 mkU32( 0 ) ), 8736 binop( Iop_32HLto64, 8737 binop( Iop_F64toI32U, 8738 mkU32( Irrm_ZERO ), 8739 mkexpr( xB2 ) ), 8740 mkU32( 0 ) ) ) ); 8741 break; 8742 case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format) 8743 DIP("xvcvspdp v%u,v%u\n", (UInt)XT, (UInt)XB); 8744 putVSReg( XT, 8745 binop( Iop_64HLtoV128, 8746 unop( Iop_ReinterpF64asI64, 8747 unop( Iop_F32toF64, 8748 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 8749 unop( Iop_ReinterpF64asI64, 8750 unop( Iop_F32toF64, 8751 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 8752 break; 8753 case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and 8754 // Convert to Signed Integer Doubleword format with Saturate) 8755 DIP("xvcvspsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 8756 putVSReg( XT, 8757 binop( Iop_64HLtoV128, 8758 binop( Iop_F64toI64S, 8759 mkU32( Irrm_ZERO ), 8760 unop( Iop_F32toF64, 8761 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 8762 binop( Iop_F64toI64S, 8763 mkU32( Irrm_ZERO ), 8764 unop( Iop_F32toF64, 8765 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 8766 break; 8767 case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and 8768 // Convert to Unsigned Integer Doubleword format with Saturate) 8769 DIP("xvcvspuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 8770 putVSReg( XT, 8771 binop( Iop_64HLtoV128, 8772 binop( Iop_F64toI64U, 8773 mkU32( Irrm_ZERO ), 8774 unop( Iop_F32toF64, 8775 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 8776 binop( Iop_F64toI64U, 8777 mkU32( Irrm_ZERO ), 8778 unop( Iop_F32toF64, 8779 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 8780 break; 8781 case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and 8782 // Convert to Signed Integer Doubleword format with Saturate) 8783 DIP("xvcvdpsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 8784 putVSReg( XT, 8785 binop( Iop_64HLtoV128, 8786 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 8787 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 8788 break; 8789 case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword 8790 // to Double-Precision format) 8791 DIP("xvcvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 8792 putVSReg( XT, 8793 binop( Iop_64HLtoV128, 8794 unop( Iop_ReinterpF64asI64, 8795 binop( Iop_I64StoF64, 8796 get_IR_roundingmode(), 8797 mkexpr( xB ) ) ), 8798 unop( Iop_ReinterpF64asI64, 8799 binop( Iop_I64StoF64, 8800 get_IR_roundingmode(), 8801 mkexpr( xB2 ) ) ) ) ); 8802 break; 8803 case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword 8804 // to Double-Precision format) 8805 DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 8806 putVSReg( XT, 8807 binop( Iop_64HLtoV128, 8808 unop( Iop_ReinterpF64asI64, 8809 binop( Iop_I64UtoF64, 8810 get_IR_roundingmode(), 8811 mkexpr( xB ) ) ), 8812 unop( Iop_ReinterpF64asI64, 8813 binop( Iop_I64UtoF64, 8814 get_IR_roundingmode(), 8815 mkexpr( xB2 ) ) ) ) ); 8816 8817 break; 8818 case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword 8819 // to Single-Precision format) 8820 DIP("xvcvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 8821 putVSReg( XT, 8822 binop( Iop_64HLtoV128, 8823 binop( Iop_32HLto64, 8824 unop( Iop_ReinterpF32asI32, 8825 unop( Iop_TruncF64asF32, 8826 binop( Iop_RoundF64toF32, 8827 get_IR_roundingmode(), 8828 binop( Iop_I64StoF64, 8829 get_IR_roundingmode(), 8830 mkexpr( xB ) ) ) ) ), 8831 mkU32( 0 ) ), 8832 binop( Iop_32HLto64, 8833 unop( Iop_ReinterpF32asI32, 8834 unop( Iop_TruncF64asF32, 8835 binop( Iop_RoundF64toF32, 8836 get_IR_roundingmode(), 8837 binop( Iop_I64StoF64, 8838 get_IR_roundingmode(), 8839 mkexpr( xB2 ) ) ) ) ), 8840 mkU32( 0 ) ) ) ); 8841 break; 8842 case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword 8843 // to Single-Precision format) 8844 DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 8845 putVSReg( XT, 8846 binop( Iop_64HLtoV128, 8847 binop( Iop_32HLto64, 8848 unop( Iop_ReinterpF32asI32, 8849 unop( Iop_TruncF64asF32, 8850 binop( Iop_RoundF64toF32, 8851 get_IR_roundingmode(), 8852 binop( Iop_I64UtoF64, 8853 get_IR_roundingmode(), 8854 mkexpr( xB ) ) ) ) ), 8855 mkU32( 0 ) ), 8856 binop( Iop_32HLto64, 8857 unop( Iop_ReinterpF32asI32, 8858 unop( Iop_TruncF64asF32, 8859 binop( Iop_RoundF64toF32, 8860 get_IR_roundingmode(), 8861 binop( Iop_I64UtoF64, 8862 get_IR_roundingmode(), 8863 mkexpr( xB2 ) ) ) ) ), 8864 mkU32( 0 ) ) ) ); 8865 break; 8866 8867 case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format) 8868 DIP("xvcvsxwdp v%u,v%u\n", (UInt)XT, (UInt)XB); 8869 putVSReg( XT, 8870 binop( Iop_64HLtoV128, 8871 unop( Iop_ReinterpF64asI64, 8872 binop( Iop_I64StoF64, get_IR_roundingmode(), 8873 unop( Iop_32Sto64, mkexpr( b3 ) ) ) ), 8874 unop( Iop_ReinterpF64asI64, 8875 binop( Iop_I64StoF64, get_IR_roundingmode(), 8876 unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) ); 8877 break; 8878 case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format) 8879 DIP("xvcvuxwdp v%u,v%u\n", (UInt)XT, (UInt)XB); 8880 putVSReg( XT, 8881 binop( Iop_64HLtoV128, 8882 unop( Iop_ReinterpF64asI64, 8883 binop( Iop_I64UtoF64, get_IR_roundingmode(), 8884 unop( Iop_32Uto64, mkexpr( b3 ) ) ) ), 8885 unop( Iop_ReinterpF64asI64, 8886 binop( Iop_I64UtoF64, get_IR_roundingmode(), 8887 unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) ); 8888 break; 8889 case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format) 8890 DIP("xvcvsxwsp v%u,v%u\n", (UInt)XT, (UInt)XB); 8891 putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) ); 8892 break; 8893 case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format) 8894 DIP("xvcvuxwsp v%u,v%u\n", (UInt)XT, (UInt)XB); 8895 putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) ); 8896 break; 8897 8898 default: 8899 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 8900 return False; 8901 } 8902 return True; 8903} 8904 8905/* 8906 * VSX vector Double Precision Floating Point Arithmetic Instructions 8907 */ 8908static Bool 8909dis_vxv_dp_arith ( UInt theInstr, UInt opc2 ) 8910{ 8911 /* XX3-Form */ 8912 UChar opc1 = ifieldOPC( theInstr ); 8913 UChar XT = ifieldRegXT( theInstr ); 8914 UChar XA = ifieldRegXA( theInstr ); 8915 UChar XB = ifieldRegXB( theInstr ); 8916 IRExpr* rm = get_IR_roundingmode(); 8917 IRTemp frA = newTemp(Ity_F64); 8918 IRTemp frB = newTemp(Ity_F64); 8919 IRTemp frA2 = newTemp(Ity_F64); 8920 IRTemp frB2 = newTemp(Ity_F64); 8921 8922 if (opc1 != 0x3C) { 8923 vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" ); 8924 return False; 8925 } 8926 8927 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 8928 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 8929 assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA )))); 8930 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB )))); 8931 8932 switch (opc2) { 8933 case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision) 8934 case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision) 8935 case 0x180: // xvadddp (VSX Vector Add Double-Precision) 8936 case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision) 8937 { 8938 IROp mOp; 8939 Char * oper_name; 8940 switch (opc2) { 8941 case 0x1E0: 8942 mOp = Iop_DivF64; 8943 oper_name = "div"; 8944 break; 8945 case 0x1C0: 8946 mOp = Iop_MulF64; 8947 oper_name = "mul"; 8948 break; 8949 case 0x180: 8950 mOp = Iop_AddF64; 8951 oper_name = "add"; 8952 break; 8953 case 0x1A0: 8954 mOp = Iop_SubF64; 8955 oper_name = "sub"; 8956 break; 8957 8958 default: 8959 vpanic("The impossible happened: dis_vxv_dp_arith(ppc)"); 8960 } 8961 IRTemp hiResult = newTemp(Ity_I64); 8962 IRTemp loResult = newTemp(Ity_I64); 8963 DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB); 8964 8965 assign( hiResult, 8966 unop( Iop_ReinterpF64asI64, 8967 triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) ); 8968 assign( loResult, 8969 unop( Iop_ReinterpF64asI64, 8970 triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) ); 8971 putVSReg( XT, 8972 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 8973 break; 8974 } 8975 case 0x196: // xvsqrtdp 8976 { 8977 IRTemp hiResult = newTemp(Ity_I64); 8978 IRTemp loResult = newTemp(Ity_I64); 8979 DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 8980 8981 assign( hiResult, 8982 unop( Iop_ReinterpF64asI64, 8983 binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) ); 8984 assign( loResult, 8985 unop( Iop_ReinterpF64asI64, 8986 binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) ); 8987 putVSReg( XT, 8988 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 8989 break; 8990 } 8991 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision) 8992 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision) 8993 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision) 8994 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision) 8995 { 8996 /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . . 8997 * XT == FRC 8998 * XA == FRA 8999 * XB == FRB 9000 * 9001 * and for xvm{add|sub}adp . . . 9002 * XT == FRB 9003 * XA == FRA 9004 * XB == FRC 9005 */ 9006 Bool negate; 9007 IROp mOp = Iop_INVALID; 9008 Char * oper_name = NULL; 9009 Bool mdp = False; 9010 9011 switch (opc2) { 9012 case 0x184: case 0x1A4: 9013 case 0x384: case 0x3A4: 9014 mOp = Iop_MAddF64; 9015 oper_name = "add"; 9016 mdp = (opc2 & 0x0FF) == 0x0A4; 9017 break; 9018 9019 case 0x1C4: case 0x1E4: 9020 case 0x3C4: case 0x3E4: 9021 mOp = Iop_MSubF64; 9022 oper_name = "sub"; 9023 mdp = (opc2 & 0x0FF) == 0x0E4; 9024 break; 9025 9026 default: 9027 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 9028 } 9029 9030 switch (opc2) { 9031 case 0x384: case 0x3A4: 9032 case 0x3C4: case 0x3E4: 9033 negate = True; 9034 break; 9035 default: 9036 negate = False; 9037 } 9038 IRTemp hiResult = newTemp(Ity_I64); 9039 IRTemp loResult = newTemp(Ity_I64); 9040 IRTemp frT = newTemp(Ity_F64); 9041 IRTemp frT2 = newTemp(Ity_F64); 9042 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp", 9043 (UInt)XT, (UInt)XA, (UInt)XB); 9044 assign(frT, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) ); 9045 assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) ); 9046 9047 assign( hiResult, 9048 unop( Iop_ReinterpF64asI64, 9049 qop( mOp, 9050 rm, 9051 mkexpr( frA ), 9052 mkexpr( mdp ? frT : frB ), 9053 mkexpr( mdp ? frB : frT ) ) ) ); 9054 assign( loResult, 9055 unop( Iop_ReinterpF64asI64, 9056 qop( mOp, 9057 rm, 9058 mkexpr( frA2 ), 9059 mkexpr( mdp ? frT2 : frB2 ), 9060 mkexpr( mdp ? frB2 : frT2 ) ) ) ); 9061 putVSReg( XT, 9062 binop( Iop_64HLtoV128, 9063 mkexpr( negate ? getNegatedResult( hiResult ) 9064 : hiResult ), 9065 mkexpr( negate ? getNegatedResult( loResult ) 9066 : loResult ) ) ); 9067 break; 9068 } 9069 case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision) 9070 { 9071 IRTemp frBHi_I64 = newTemp(Ity_I64); 9072 IRTemp frBLo_I64 = newTemp(Ity_I64); 9073 IRTemp flagsHi = newTemp(Ity_I32); 9074 IRTemp flagsLo = newTemp(Ity_I32); 9075 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 9076 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 9077 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 9078 9079 DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB); 9080 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 9081 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 9082 do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi); 9083 do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo); 9084 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 9085 * where fl_flag == 1 on ppc64. 9086 */ 9087 assign( flagsHi, 9088 binop( Iop_Or32, 9089 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9090 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 9091 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 9092 assign( flagsLo, 9093 binop( Iop_Or32, 9094 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9095 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 9096 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 9097 putGST_field( PPC_GST_CR, 9098 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 9099 crfD ); 9100 break; 9101 } 9102 case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision) 9103 { 9104 IRTemp frBHi_I64 = newTemp(Ity_I64); 9105 IRTemp frBLo_I64 = newTemp(Ity_I64); 9106 IRTemp frAHi_I64 = newTemp(Ity_I64); 9107 IRTemp frALo_I64 = newTemp(Ity_I64); 9108 IRTemp flagsHi = newTemp(Ity_I32); 9109 IRTemp flagsLo = newTemp(Ity_I32); 9110 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 9111 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 9112 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 9113 9114 DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB); 9115 assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) ); 9116 assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) ); 9117 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 9118 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 9119 9120 _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi); 9121 _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo); 9122 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 9123 * where fl_flag == 1 on ppc64. 9124 */ 9125 assign( flagsHi, 9126 binop( Iop_Or32, 9127 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9128 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 9129 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 9130 assign( flagsLo, 9131 binop( Iop_Or32, 9132 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9133 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 9134 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 9135 putGST_field( PPC_GST_CR, 9136 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 9137 crfD ); 9138 break; 9139 } 9140 9141 default: 9142 vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" ); 9143 return False; 9144 } 9145 return True; 9146} 9147 9148/* 9149 * VSX vector Single Precision Floating Point Arithmetic Instructions 9150 */ 9151static Bool 9152dis_vxv_sp_arith ( UInt theInstr, UInt opc2 ) 9153{ 9154 /* XX3-Form */ 9155 UChar opc1 = ifieldOPC( theInstr ); 9156 UChar XT = ifieldRegXT( theInstr ); 9157 UChar XA = ifieldRegXA( theInstr ); 9158 UChar XB = ifieldRegXB( theInstr ); 9159 IRExpr* rm = get_IR_roundingmode(); 9160 IRTemp a3, a2, a1, a0; 9161 IRTemp b3, b2, b1, b0; 9162 IRTemp res0 = newTemp(Ity_I32); 9163 IRTemp res1 = newTemp(Ity_I32); 9164 IRTemp res2 = newTemp(Ity_I32); 9165 IRTemp res3 = newTemp(Ity_I32); 9166 9167 a3 = a2 = a1 = a0 = IRTemp_INVALID; 9168 b3 = b2 = b1 = b0 = IRTemp_INVALID; 9169 9170 if (opc1 != 0x3C) { 9171 vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" ); 9172 return False; 9173 } 9174 9175 switch (opc2) { 9176 case 0x100: // xvaddsp (VSX Vector Add Single-Precision) 9177 DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 9178 putVSReg( XT, binop(Iop_Add32Fx4, getVSReg( XA ), getVSReg( XB )) ); 9179 break; 9180 9181 case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision) 9182 DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 9183 putVSReg( XT, binop(Iop_Mul32Fx4, getVSReg( XA ), getVSReg( XB )) ); 9184 break; 9185 9186 case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision) 9187 DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 9188 putVSReg( XT, binop(Iop_Sub32Fx4, getVSReg( XA ), getVSReg( XB )) ); 9189 break; 9190 9191 case 0x160: // xvdivsp (VSX Vector Divide Single-Precision) 9192 { 9193 /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c. 9194 * So there are two choices: 9195 * 1. Implement the xvdivsp with a native insn; or 9196 * 2. Extract the 4 single precision floats from each vector 9197 * register inputs and perform fdivs on each pair 9198 * I will do the latter, due to the general philosophy of 9199 * reusing existing implementations when practical. 9200 */ 9201 DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 9202 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 9203 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 9204 9205 assign( res0, 9206 unop( Iop_ReinterpF32asI32, 9207 unop( Iop_TruncF64asF32, 9208 triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) ); 9209 assign( res1, 9210 unop( Iop_ReinterpF32asI32, 9211 unop( Iop_TruncF64asF32, 9212 triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) ); 9213 assign( res2, 9214 unop( Iop_ReinterpF32asI32, 9215 unop( Iop_TruncF64asF32, 9216 triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) ); 9217 assign( res3, 9218 unop( Iop_ReinterpF32asI32, 9219 unop( Iop_TruncF64asF32, 9220 triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) ); 9221 9222 putVSReg( XT, 9223 binop( Iop_64HLtoV128, 9224 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 9225 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 9226 break; 9227 } 9228 case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision) 9229 { 9230 DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB); 9231 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 9232 /* Note: The native xvsqrtsp insruction does not always give the same precision 9233 * as what we get with Iop_SqrtF64. But it doesn't seem worthwhile to implement 9234 * an Iop_SqrtF32 that would give us a lower precision result, albeit more true 9235 * to the actual instruction. 9236 */ 9237 9238 assign( res0, 9239 unop( Iop_ReinterpF32asI32, 9240 unop( Iop_TruncF64asF32, 9241 binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) ); 9242 assign( res1, 9243 unop( Iop_ReinterpF32asI32, 9244 unop( Iop_TruncF64asF32, 9245 binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) ); 9246 assign( res2, 9247 unop( Iop_ReinterpF32asI32, 9248 unop( Iop_TruncF64asF32, 9249 binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) ); 9250 assign( res3, 9251 unop( Iop_ReinterpF32asI32, 9252 unop( Iop_TruncF64asF32, 9253 binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) ); 9254 9255 putVSReg( XT, 9256 binop( Iop_64HLtoV128, 9257 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 9258 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 9259 break; 9260 } 9261 9262 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision) 9263 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision) 9264 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision) 9265 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision) 9266 { 9267 IRTemp t3, t2, t1, t0; 9268 Bool msp = False; 9269 Bool negate; 9270 Char * oper_name = NULL; 9271 IROp mOp = Iop_INVALID; 9272 switch (opc2) { 9273 case 0x104: case 0x124: 9274 case 0x304: case 0x324: 9275 msp = (opc2 & 0x0FF) == 0x024; 9276 mOp = Iop_MAddF64r32; 9277 oper_name = "madd"; 9278 break; 9279 9280 case 0x144: case 0x164: 9281 case 0x344: case 0x364: 9282 msp = (opc2 & 0x0FF) == 0x064; 9283 mOp = Iop_MSubF64r32; 9284 oper_name = "sub"; 9285 break; 9286 9287 default: 9288 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 9289 } 9290 9291 switch (opc2) { 9292 case 0x304: case 0x324: 9293 case 0x344: case 0x364: 9294 negate = True; 9295 break; 9296 9297 default: 9298 negate = False; 9299 } 9300 9301 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp", 9302 (UInt)XT, (UInt)XA, (UInt)XB); 9303 9304 t3 = t2 = t1 = t0 = IRTemp_INVALID; 9305 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 9306 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 9307 breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 ); 9308 9309 assign( res0, 9310 unop( Iop_ReinterpF32asI32, 9311 unop( Iop_TruncF64asF32, 9312 qop( mOp, 9313 rm, 9314 mkexpr( a0 ), 9315 mkexpr( msp ? t0 : b0 ), 9316 mkexpr( msp ? b0 : t0 ) ) ) ) ); 9317 assign( res1, 9318 unop( Iop_ReinterpF32asI32, 9319 unop( Iop_TruncF64asF32, 9320 qop( mOp, 9321 rm, 9322 mkexpr( a1 ), 9323 mkexpr( msp ? t1 : b1 ), 9324 mkexpr( msp ? b1 : t1 ) ) ) ) ); 9325 assign( res2, 9326 unop( Iop_ReinterpF32asI32, 9327 unop( Iop_TruncF64asF32, 9328 qop( mOp, 9329 rm, 9330 mkexpr( a2 ), 9331 mkexpr( msp ? t2 : b2 ), 9332 mkexpr( msp ? b2 : t2 ) ) ) ) ); 9333 assign( res3, 9334 unop( Iop_ReinterpF32asI32, 9335 unop( Iop_TruncF64asF32, 9336 qop( mOp, 9337 rm, 9338 mkexpr( a3 ), 9339 mkexpr( msp ? t3 : b3 ), 9340 mkexpr( msp ? b3 : t3 ) ) ) ) ); 9341 9342 putVSReg( XT, 9343 binop( Iop_64HLtoV128, 9344 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ), 9345 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ), 9346 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ), 9347 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) ); 9348 9349 break; 9350 } 9351 case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision) 9352 { 9353 IRTemp flags0 = newTemp(Ity_I32); 9354 IRTemp flags1 = newTemp(Ity_I32); 9355 IRTemp flags2 = newTemp(Ity_I32); 9356 IRTemp flags3 = newTemp(Ity_I32); 9357 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 9358 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 9359 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 9360 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 9361 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 9362 DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB); 9363 9364 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 9365 do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0); 9366 do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1); 9367 do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2); 9368 do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3); 9369 9370 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 9371 * where fl_flag == 1 on ppc64. 9372 */ 9373 assign( flags0, 9374 binop( Iop_Or32, 9375 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9376 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 9377 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 9378 assign( flags1, 9379 binop( Iop_Or32, 9380 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9381 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 9382 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 9383 assign( flags2, 9384 binop( Iop_Or32, 9385 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9386 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 9387 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 9388 assign( flags3, 9389 binop( Iop_Or32, 9390 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9391 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 9392 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 9393 putGST_field( PPC_GST_CR, 9394 binop( Iop_Or32, 9395 mkexpr( flags0 ), 9396 binop( Iop_Or32, 9397 mkexpr( flags1 ), 9398 binop( Iop_Or32, 9399 mkexpr( flags2 ), 9400 mkexpr( flags3 ) ) ) ), 9401 crfD ); 9402 9403 break; 9404 } 9405 case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision) 9406 { 9407 IRTemp flags0 = newTemp(Ity_I32); 9408 IRTemp flags1 = newTemp(Ity_I32); 9409 IRTemp flags2 = newTemp(Ity_I32); 9410 IRTemp flags3 = newTemp(Ity_I32); 9411 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 9412 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 9413 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 9414 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 9415 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 9416 DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB); 9417 9418 breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 9419 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 9420 _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0); 9421 _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1); 9422 _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2); 9423 _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3); 9424 9425 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 9426 * where fl_flag == 1 on ppc64. 9427 */ 9428 assign( flags0, 9429 binop( Iop_Or32, 9430 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9431 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 9432 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 9433 assign( flags1, 9434 binop( Iop_Or32, 9435 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9436 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 9437 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 9438 assign( flags2, 9439 binop( Iop_Or32, 9440 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9441 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 9442 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 9443 assign( flags3, 9444 binop( Iop_Or32, 9445 binop( Iop_Or32, mkU32( 8 ), // fl_flag 9446 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 9447 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 9448 putGST_field( PPC_GST_CR, 9449 binop( Iop_Or32, 9450 mkexpr( flags0 ), 9451 binop( Iop_Or32, 9452 mkexpr( flags1 ), 9453 binop( Iop_Or32, 9454 mkexpr( flags2 ), 9455 mkexpr( flags3 ) ) ) ), 9456 crfD ); 9457 9458 break; 9459 } 9460 9461 default: 9462 vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" ); 9463 return False; 9464 } 9465 return True; 9466} 9467 9468typedef enum { 9469 PPC_CMP_EQ = 2, 9470 PPC_CMP_GT = 4, 9471 PPC_CMP_GE = 6, 9472 PPC_CMP_LT = 8 9473} ppc_cmp_t; 9474 9475 9476/* 9477 This helper function takes as input the IRExpr returned 9478 from a binop( Iop_CmpF64, fpA, fpB), whose result is returned 9479 in IR form. This helper function converts it to PPC form. 9480 9481 Map compare result from IR to PPC 9482 9483 FP cmp result | PPC | IR 9484 -------------------------- 9485 UN | 0x1 | 0x45 9486 EQ | 0x2 | 0x40 9487 GT | 0x4 | 0x00 9488 LT | 0x8 | 0x01 9489 9490 condcode = Shl(1, (~(ccIR>>5) & 2) 9491 | ((ccIR ^ (ccIR>>6)) & 1) 9492*/ 9493static IRTemp 9494get_fp_cmp_CR_val (IRExpr * ccIR_expr) 9495{ 9496 IRTemp condcode = newTemp( Ity_I32 ); 9497 IRTemp ccIR = newTemp( Ity_I32 ); 9498 9499 assign(ccIR, ccIR_expr); 9500 assign( condcode, 9501 binop( Iop_Shl32, 9502 mkU32( 1 ), 9503 unop( Iop_32to8, 9504 binop( Iop_Or32, 9505 binop( Iop_And32, 9506 unop( Iop_Not32, 9507 binop( Iop_Shr32, 9508 mkexpr( ccIR ), 9509 mkU8( 5 ) ) ), 9510 mkU32( 2 ) ), 9511 binop( Iop_And32, 9512 binop( Iop_Xor32, 9513 mkexpr( ccIR ), 9514 binop( Iop_Shr32, 9515 mkexpr( ccIR ), 9516 mkU8( 6 ) ) ), 9517 mkU32( 1 ) ) ) ) ) ); 9518 return condcode; 9519} 9520 9521/* 9522 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles 9523 * following these special rules: 9524 * - The max/min of a QNaN and any value is that value 9525 * (When two QNaNs are being compared, the frA QNaN is the return value.) 9526 * - The max/min of any value and an SNaN is that SNaN converted to a QNaN 9527 * (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.) 9528 */ 9529static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64) 9530{ 9531 IRTemp frA_isNaN = newTemp(Ity_I1); 9532 IRTemp frB_isNaN = newTemp(Ity_I1); 9533 IRTemp frA_isSNaN = newTemp(Ity_I1); 9534 IRTemp frB_isSNaN = newTemp(Ity_I1); 9535 IRTemp frA_isQNaN = newTemp(Ity_I1); 9536 IRTemp frB_isQNaN = newTemp(Ity_I1); 9537 9538 assign( frA_isNaN, is_NaN( frA_I64 ) ); 9539 assign( frB_isNaN, is_NaN( frB_I64 ) ); 9540 // If operand is a NAN and bit 12 is '0', then it's an SNaN 9541 assign( frA_isSNaN, 9542 mkAND1( mkexpr(frA_isNaN), 9543 binop( Iop_CmpEQ32, 9544 binop( Iop_And32, 9545 unop( Iop_64HIto32, mkexpr( frA_I64 ) ), 9546 mkU32( 0x00080000 ) ), 9547 mkU32( 0 ) ) ) ); 9548 assign( frB_isSNaN, 9549 mkAND1( mkexpr(frB_isNaN), 9550 binop( Iop_CmpEQ32, 9551 binop( Iop_And32, 9552 unop( Iop_64HIto32, mkexpr( frB_I64 ) ), 9553 mkU32( 0x00080000 ) ), 9554 mkU32( 0 ) ) ) ); 9555 assign( frA_isQNaN, 9556 mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) ); 9557 assign( frB_isQNaN, 9558 mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) ); 9559 9560 /* Based on the rules specified in the function prologue, the algorithm is as follows: 9561 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 9562 * if frA is a SNaN 9563 * result = frA converted to QNaN 9564 * else if frB is a SNaN 9565 * result = frB converted to QNaN 9566 * else if frB is a QNaN 9567 * result = frA 9568 * // One of frA or frB was a NaN in order for this function to be called, so 9569 * // if we get to this point, we KNOW that frA must be a QNaN. 9570 * else // frA is a QNaN 9571 * result = frB 9572 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 9573 */ 9574 9575#define SNAN_MASK 0x0008000000000000ULL 9576 return 9577 IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frA_isSNaN)), 9578 /* else: if frB is a SNaN */ 9579 IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isSNaN)), 9580 /* else: if frB is a QNaN */ 9581 IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isQNaN)), 9582 /* else: frA is a QNaN, so result = frB */ 9583 mkexpr(frB_I64), 9584 /* then: result = frA */ 9585 mkexpr(frA_I64)), 9586 /* then: result = frB converted to QNaN */ 9587 binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK))), 9588 /* then: result = frA converted to QNaN */ 9589 binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK))); 9590} 9591 9592/* 9593 * Helper function for get_max_min_fp. 9594 */ 9595static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin) 9596{ 9597 IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64, 9598 unop( Iop_ReinterpI64asF64, 9599 mkexpr( src1 ) ), 9600 unop( Iop_ReinterpI64asF64, 9601 mkexpr( src2 ) ) ) ); 9602 9603 return IRExpr_Mux0X( unop( Iop_1Uto8, 9604 binop( Iop_CmpEQ32, 9605 mkexpr( src1cmpsrc2 ), 9606 mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ) ), 9607 /* else: use src2 */ 9608 mkexpr( src2 ), 9609 /* then: use src1 */ 9610 mkexpr( src1 ) ); 9611} 9612 9613/* 9614 * Helper function for "Maximum/Minimum Double Precision" operations. 9615 * Arguments: frA and frb are Ity_I64 9616 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question 9617 */ 9618static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin) 9619{ 9620 /* There are three special cases where get_fp_cmp_CR_val is not helpful 9621 * for ascertaining the maximum between two doubles: 9622 * 1. The max/min of +0 and -0 is +0. 9623 * 2. The max/min of a QNaN and any value is that value. 9624 * 3. The max/min of any value and an SNaN is that SNaN converted to a QNaN. 9625 * We perform the check for [+/-]0 here in this function and use the 9626 * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp 9627 * to do the standard comparison function. 9628 */ 9629 IRTemp anyNaN = newTemp(Ity_I1); 9630 IRTemp frA_isZero = newTemp(Ity_I1); 9631 IRTemp frB_isZero = newTemp(Ity_I1); 9632 assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ )); 9633 assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ )); 9634 assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64))); 9635#define MINUS_ZERO 0x8000000000000000ULL 9636 9637 return IRExpr_Mux0X( unop( Iop_1Uto8, 9638 /* If both arguments are zero . . . */ 9639 mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ) ), 9640 /* else: check if either input is a NaN*/ 9641 IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( anyNaN ) ), 9642 /* else: use "comparison helper" */ 9643 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ), 9644 /* then: use "NaN helper" */ 9645 _get_maxmin_fp_NaN( frA_I64, frB_I64 ) ), 9646 /* then: if frA is -0 and isMin==True, return -0; 9647 * else if frA is +0 and isMin==False; return +0; 9648 * otherwise, simply return frB. */ 9649 IRExpr_Mux0X( unop( Iop_1Uto8, 9650 binop( Iop_CmpEQ32, 9651 unop( Iop_64HIto32, 9652 mkexpr( frA_I64 ) ), 9653 mkU32( isMin ? 0x80000000 : 0 ) ) ), 9654 mkexpr( frB_I64 ), 9655 mkU64( isMin ? MINUS_ZERO : 0ULL ) ) ); 9656} 9657 9658/* 9659 * Helper function for vector/scalar double precision fp round to integer instructions. 9660 */ 9661static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2, UChar * insn_suffix) 9662{ 9663 9664 /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */ 9665 IRTemp frB = newTemp(Ity_F64); 9666 IRTemp frD = newTemp(Ity_F64); 9667 IRTemp intermediateResult = newTemp(Ity_I64); 9668 IRTemp is_SNAN = newTemp(Ity_I1); 9669 IRExpr * hi32; 9670 IRExpr * rxpi_rm; 9671 switch (opc2 & 0x7F) { 9672 case 0x72: 9673 insn_suffix = "m"; 9674 rxpi_rm = mkU32(Irrm_NegINF); 9675 break; 9676 case 0x52: 9677 insn_suffix = "p"; 9678 rxpi_rm = mkU32(Irrm_PosINF); 9679 break; 9680 case 0x56: 9681 insn_suffix = "c"; 9682 rxpi_rm = get_IR_roundingmode(); 9683 break; 9684 case 0x32: 9685 insn_suffix = "z"; 9686 rxpi_rm = mkU32(Irrm_ZERO); 9687 break; 9688 case 0x12: 9689 insn_suffix = ""; 9690 rxpi_rm = mkU32(Irrm_NEAREST); 9691 break; 9692 9693 default: // Impossible to get here 9694 vex_printf( "_do_vsx_fp_roundToInt(ppc)(opc2)\n" ); 9695 return NULL; 9696 } 9697 assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64))); 9698 assign( intermediateResult, 9699 binop( Iop_F64toI64S, rxpi_rm, 9700 mkexpr( frB ) ) ); 9701 9702 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 9703 /* F64 has only log10(2**52) significant digits anyway */ 9704 /* need to preserve sign of zero */ 9705 /* frD = (fabs(frB) > 9e18) ? frB : 9706 (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult */ 9707 assign( frD, 9708 IRExpr_Mux0X( unop( Iop_32to8, 9709 binop( Iop_CmpF64, 9710 IRExpr_Const( IRConst_F64( 9e18 ) ), 9711 unop( Iop_AbsF64, mkexpr( frB ) ) ) ), 9712 IRExpr_Mux0X( unop( Iop_32to8, 9713 binop( Iop_Shr32, 9714 unop( Iop_64HIto32, 9715 mkexpr( frB_I64 ) ), 9716 mkU8( 31 ) ) ), 9717 binop( Iop_I64StoF64, 9718 mkU32( 0 ), 9719 mkexpr( intermediateResult ) ), 9720 unop( Iop_NegF64, 9721 unop( Iop_AbsF64, 9722 binop( Iop_I64StoF64, 9723 mkU32( 0 ), 9724 mkexpr( intermediateResult ) ) ) ) ), 9725 mkexpr( frB ) ) ); 9726 9727 /* See Appendix "Floating-Point Round to Integer Model" in ISA doc. 9728 * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'. 9729 */ 9730#define SNAN_MASK 0x0008000000000000ULL 9731 hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) ); 9732 assign( is_SNAN, 9733 mkAND1( is_NaN( frB_I64 ), 9734 binop( Iop_CmpEQ32, 9735 binop( Iop_And32, hi32, mkU32( 0x00080000 ) ), 9736 mkU32( 0 ) ) ) ); 9737 9738 return IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( is_SNAN ) ), 9739 mkexpr( frD ), 9740 unop( Iop_ReinterpI64asF64, 9741 binop( Iop_Xor64, 9742 mkU64( SNAN_MASK ), 9743 mkexpr( frB_I64 ) ) ) ); 9744} 9745 9746/* 9747 * Miscellaneous VSX vector instructions 9748 */ 9749static Bool 9750dis_vxv_misc ( UInt theInstr, UInt opc2 ) 9751{ 9752 /* XX3-Form */ 9753 UChar opc1 = ifieldOPC( theInstr ); 9754 UChar XT = ifieldRegXT( theInstr ); 9755 UChar XB = ifieldRegXB( theInstr ); 9756 9757 if (opc1 != 0x3C) { 9758 vex_printf( "dis_vxv_misc(ppc)(instr)\n" ); 9759 return False; 9760 } 9761 9762 switch (opc2) { 9763 case 0x1B4: // xvredp (VSX Vector Reciprocal Estimate Double-Precision) 9764 case 0x194: // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate 9765 // Double-Precision) 9766 { 9767 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 9768 IRExpr* rm = get_IR_roundingmode(); 9769 IRTemp frB = newTemp(Ity_I64); 9770 IRTemp frB2 = newTemp(Ity_I64); 9771 Bool redp = opc2 == 0x1B4; 9772 IRTemp sqrtHi = newTemp(Ity_F64); 9773 IRTemp sqrtLo = newTemp(Ity_F64); 9774 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 9775 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 9776 9777 DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB); 9778 if (!redp) { 9779 assign( sqrtHi, 9780 binop( Iop_SqrtF64, 9781 rm, 9782 unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) ); 9783 assign( sqrtLo, 9784 binop( Iop_SqrtF64, 9785 rm, 9786 unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) ); 9787 } 9788 putVSReg( XT, 9789 binop( Iop_64HLtoV128, 9790 unop( Iop_ReinterpF64asI64, 9791 triop( Iop_DivF64, 9792 rm, 9793 ieee_one, 9794 redp ? unop( Iop_ReinterpI64asF64, 9795 mkexpr( frB ) ) 9796 : mkexpr( sqrtHi ) ) ), 9797 unop( Iop_ReinterpF64asI64, 9798 triop( Iop_DivF64, 9799 rm, 9800 ieee_one, 9801 redp ? unop( Iop_ReinterpI64asF64, 9802 mkexpr( frB2 ) ) 9803 : mkexpr( sqrtLo ) ) ) ) ); 9804 break; 9805 9806 } 9807 case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision) 9808 case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision) 9809 { 9810 IRTemp b3, b2, b1, b0; 9811 IRTemp res0 = newTemp(Ity_I32); 9812 IRTemp res1 = newTemp(Ity_I32); 9813 IRTemp res2 = newTemp(Ity_I32); 9814 IRTemp res3 = newTemp(Ity_I32); 9815 IRTemp sqrt3 = newTemp(Ity_F64); 9816 IRTemp sqrt2 = newTemp(Ity_F64); 9817 IRTemp sqrt1 = newTemp(Ity_F64); 9818 IRTemp sqrt0 = newTemp(Ity_F64); 9819 IRExpr* rm = get_IR_roundingmode(); 9820 Bool resp = opc2 == 0x134; 9821 9822 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 9823 9824 b3 = b2 = b1 = b0 = IRTemp_INVALID; 9825 DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB); 9826 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 9827 9828 if (!resp) { 9829 assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) ); 9830 assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) ); 9831 assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) ); 9832 assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) ); 9833 } 9834 9835 assign( res0, 9836 unop( Iop_ReinterpF32asI32, 9837 unop( Iop_TruncF64asF32, 9838 triop( Iop_DivF64r32, 9839 rm, 9840 ieee_one, 9841 resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) ); 9842 assign( res1, 9843 unop( Iop_ReinterpF32asI32, 9844 unop( Iop_TruncF64asF32, 9845 triop( Iop_DivF64r32, 9846 rm, 9847 ieee_one, 9848 resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) ); 9849 assign( res2, 9850 unop( Iop_ReinterpF32asI32, 9851 unop( Iop_TruncF64asF32, 9852 triop( Iop_DivF64r32, 9853 rm, 9854 ieee_one, 9855 resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) ); 9856 assign( res3, 9857 unop( Iop_ReinterpF32asI32, 9858 unop( Iop_TruncF64asF32, 9859 triop( Iop_DivF64r32, 9860 rm, 9861 ieee_one, 9862 resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) ); 9863 putVSReg( XT, 9864 binop( Iop_64HLtoV128, 9865 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 9866 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 9867 break; 9868 } 9869 case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision) 9870 case 0x320: // xvminsp (VSX Vector Minimum Single-Precision) 9871 { 9872 UChar XA = ifieldRegXA( theInstr ); 9873 IRTemp a3, a2, a1, a0; 9874 IRTemp b3, b2, b1, b0; 9875 IRTemp res0 = newTemp( Ity_I32 ); 9876 IRTemp res1 = newTemp( Ity_I32 ); 9877 IRTemp res2 = newTemp( Ity_I32 ); 9878 IRTemp res3 = newTemp( Ity_I32 ); 9879 IRTemp a0_I64 = newTemp( Ity_I64 ); 9880 IRTemp a1_I64 = newTemp( Ity_I64 ); 9881 IRTemp a2_I64 = newTemp( Ity_I64 ); 9882 IRTemp a3_I64 = newTemp( Ity_I64 ); 9883 IRTemp b0_I64 = newTemp( Ity_I64 ); 9884 IRTemp b1_I64 = newTemp( Ity_I64 ); 9885 IRTemp b2_I64 = newTemp( Ity_I64 ); 9886 IRTemp b3_I64 = newTemp( Ity_I64 ); 9887 9888 Bool isMin = opc2 == 0x320 ? True : False; 9889 9890 a3 = a2 = a1 = a0 = IRTemp_INVALID; 9891 b3 = b2 = b1 = b0 = IRTemp_INVALID; 9892 DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB); 9893 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 9894 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 9895 assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) ); 9896 assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) ); 9897 assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) ); 9898 assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) ); 9899 assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) ); 9900 assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) ); 9901 assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) ); 9902 assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) ); 9903 assign( res0, 9904 unop( Iop_ReinterpF32asI32, 9905 unop( Iop_TruncF64asF32, 9906 unop( Iop_ReinterpI64asF64, 9907 get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) ); 9908 assign( res1, 9909 unop( Iop_ReinterpF32asI32, 9910 unop( Iop_TruncF64asF32, 9911 unop( Iop_ReinterpI64asF64, 9912 get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) ); 9913 assign( res2, 9914 unop( Iop_ReinterpF32asI32, 9915 unop( Iop_TruncF64asF32, 9916 unop( Iop_ReinterpI64asF64, 9917 get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) ); 9918 assign( res3, 9919 unop( Iop_ReinterpF32asI32, 9920 unop( Iop_TruncF64asF32, 9921 unop( Iop_ReinterpI64asF64, 9922 get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) ); 9923 putVSReg( XT, 9924 binop( Iop_64HLtoV128, 9925 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 9926 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 9927 break; 9928 } 9929 case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision) 9930 case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision) 9931 { 9932 UChar XA = ifieldRegXA( theInstr ); 9933 IRTemp frA = newTemp(Ity_I64); 9934 IRTemp frB = newTemp(Ity_I64); 9935 IRTemp frA2 = newTemp(Ity_I64); 9936 IRTemp frB2 = newTemp(Ity_I64); 9937 Bool isMin = opc2 == 0x3A0 ? True : False; 9938 9939 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 9940 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 9941 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 9942 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 9943 DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB); 9944 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) ); 9945 9946 break; 9947 } 9948 case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision) 9949 { 9950 UChar XA = ifieldRegXA( theInstr ); 9951 IRTemp frA = newTemp(Ity_I64); 9952 IRTemp frB = newTemp(Ity_I64); 9953 IRTemp frA2 = newTemp(Ity_I64); 9954 IRTemp frB2 = newTemp(Ity_I64); 9955 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 9956 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 9957 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 9958 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 9959 9960 DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 9961 putVSReg( XT, 9962 binop( Iop_64HLtoV128, 9963 binop( Iop_Or64, 9964 binop( Iop_And64, 9965 mkexpr( frA ), 9966 mkU64( SIGN_BIT ) ), 9967 binop( Iop_And64, 9968 mkexpr( frB ), 9969 mkU64( SIGN_MASK ) ) ), 9970 binop( Iop_Or64, 9971 binop( Iop_And64, 9972 mkexpr( frA2 ), 9973 mkU64( SIGN_BIT ) ), 9974 binop( Iop_And64, 9975 mkexpr( frB2 ), 9976 mkU64( SIGN_MASK ) ) ) ) ); 9977 break; 9978 } 9979 case 0x340: // xvcpsgnsp 9980 { 9981 UChar XA = ifieldRegXA( theInstr ); 9982 IRTemp a3_I64, a2_I64, a1_I64, a0_I64; 9983 IRTemp b3_I64, b2_I64, b1_I64, b0_I64; 9984 IRTemp resHi = newTemp(Ity_I64); 9985 IRTemp resLo = newTemp(Ity_I64); 9986 9987 a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID; 9988 b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID; 9989 DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB); 9990 breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 ); 9991 breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 ); 9992 9993 assign( resHi, 9994 binop( Iop_32HLto64, 9995 binop( Iop_Or32, 9996 binop( Iop_And32, 9997 unop(Iop_64to32, mkexpr( a3_I64 ) ), 9998 mkU32( SIGN_BIT32 ) ), 9999 binop( Iop_And32, 10000 unop(Iop_64to32, mkexpr( b3_I64 ) ), 10001 mkU32( SIGN_MASK32) ) ), 10002 10003 binop( Iop_Or32, 10004 binop( Iop_And32, 10005 unop(Iop_64to32, mkexpr( a2_I64 ) ), 10006 mkU32( SIGN_BIT32 ) ), 10007 binop( Iop_And32, 10008 unop(Iop_64to32, mkexpr( b2_I64 ) ), 10009 mkU32( SIGN_MASK32 ) ) ) ) ); 10010 assign( resLo, 10011 binop( Iop_32HLto64, 10012 binop( Iop_Or32, 10013 binop( Iop_And32, 10014 unop(Iop_64to32, mkexpr( a1_I64 ) ), 10015 mkU32( SIGN_BIT32 ) ), 10016 binop( Iop_And32, 10017 unop(Iop_64to32, mkexpr( b1_I64 ) ), 10018 mkU32( SIGN_MASK32 ) ) ), 10019 10020 binop( Iop_Or32, 10021 binop( Iop_And32, 10022 unop(Iop_64to32, mkexpr( a0_I64 ) ), 10023 mkU32( SIGN_BIT32 ) ), 10024 binop( Iop_And32, 10025 unop(Iop_64to32, mkexpr( b0_I64 ) ), 10026 mkU32( SIGN_MASK32 ) ) ) ) ); 10027 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) ); 10028 break; 10029 } 10030 case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision) 10031 case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision) 10032 { 10033 IRTemp frB = newTemp(Ity_F64); 10034 IRTemp frB2 = newTemp(Ity_F64); 10035 IRTemp abs_resultHi = newTemp(Ity_F64); 10036 IRTemp abs_resultLo = newTemp(Ity_F64); 10037 Bool make_negative = (opc2 == 0x3D2) ? True : False; 10038 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 10039 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 10040 10041 DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB); 10042 if (make_negative) { 10043 assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) ); 10044 assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) ); 10045 10046 } else { 10047 assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) ); 10048 assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) ); 10049 } 10050 putVSReg( XT, binop( Iop_64HLtoV128, 10051 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ), 10052 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) ); 10053 break; 10054 } 10055 case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision) 10056 case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision) 10057 { 10058 /* 10059 * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction 10060 * of xvabssp, there has not been an abs(sp) type of instruction. But since emulation 10061 * of this function is so easy using shifts, I choose to emulate this instruction that 10062 * way versus a native instruction method of implementation. 10063 */ 10064 Bool make_negative = (opc2 == 0x352) ? True : False; 10065 IRTemp shiftVector = newTemp(Ity_V128); 10066 IRTemp absVal_vector = newTemp(Ity_V128); 10067 assign( shiftVector, 10068 binop( Iop_64HLtoV128, 10069 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ), 10070 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) ); 10071 assign( absVal_vector, 10072 binop( Iop_Shr32x4, 10073 binop( Iop_Shl32x4, 10074 getVSReg( XB ), 10075 mkexpr( shiftVector ) ), 10076 mkexpr( shiftVector ) ) ); 10077 if (make_negative) { 10078 IRTemp signBit_vector = newTemp(Ity_V128); 10079 assign( signBit_vector, 10080 binop( Iop_64HLtoV128, 10081 binop( Iop_32HLto64, 10082 mkU32( 0x80000000 ), 10083 mkU32( 0x80000000 ) ), 10084 binop( Iop_32HLto64, 10085 mkU32( 0x80000000 ), 10086 mkU32( 0x80000000 ) ) ) ); 10087 putVSReg( XT, 10088 binop( Iop_OrV128, 10089 mkexpr( absVal_vector ), 10090 mkexpr( signBit_vector ) ) ); 10091 } else { 10092 putVSReg( XT, mkexpr( absVal_vector ) ); 10093 } 10094 break; 10095 } 10096 case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision) 10097 { 10098 IRTemp frB = newTemp(Ity_F64); 10099 IRTemp frB2 = newTemp(Ity_F64); 10100 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 10101 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 10102 DIP("xvnegdp v%d,v%d\n", (UInt)XT, (UInt)XB); 10103 putVSReg( XT, 10104 binop( Iop_64HLtoV128, 10105 unop( Iop_ReinterpF64asI64, 10106 unop( Iop_NegF64, mkexpr( frB ) ) ), 10107 unop( Iop_ReinterpF64asI64, 10108 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) ); 10109 break; 10110 } 10111 case 0x192: // xvrdpi (VSX Vector Round to Double-Precision Integer using round toward Nearest Away) 10112 case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode) 10113 case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity) 10114 case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity) 10115 case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero) 10116 { 10117 IRTemp frBHi_I64 = newTemp(Ity_I64); 10118 IRTemp frBLo_I64 = newTemp(Ity_I64); 10119 IRExpr * frD_fp_roundHi = NULL; 10120 IRExpr * frD_fp_roundLo = NULL; 10121 UChar * insn_suffix = NULL; 10122 10123 assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 10124 frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2, insn_suffix); 10125 assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) ); 10126 frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2, insn_suffix); 10127 10128 DIP("xvrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB); 10129 putVSReg( XT, 10130 binop( Iop_64HLtoV128, 10131 unop( Iop_ReinterpF64asI64, frD_fp_roundHi ), 10132 unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) ); 10133 break; 10134 } 10135 case 0x112: // xvrspi (VSX Vector Round to Single-Precision Integer using round toward Nearest Away) 10136 case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode) 10137 case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity) 10138 case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity) 10139 case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero) 10140 { 10141 UChar * insn_suffix = NULL; 10142 IROp op; 10143 if (opc2 != 0x156) { 10144 // Use pre-defined IRop's for vrfi{m|n|p|z} 10145 switch (opc2) { 10146 case 0x112: 10147 insn_suffix = ""; 10148 op = Iop_RoundF32x4_RN; 10149 break; 10150 case 0x172: 10151 insn_suffix = "m"; 10152 op = Iop_RoundF32x4_RM; 10153 break; 10154 case 0x152: 10155 insn_suffix = "p"; 10156 op = Iop_RoundF32x4_RP; 10157 break; 10158 case 0x132: 10159 insn_suffix = "z"; 10160 op = Iop_RoundF32x4_RZ; 10161 break; 10162 10163 default: 10164 vex_printf( "dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n" ); 10165 return False; 10166 } 10167 DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB); 10168 putVSReg( XT, unop( op, getVSReg(XB) ) ); 10169 } else { 10170 // Handle xvrspic. Unfortunately there is no corresponding "vfric" instruction. 10171 IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0; 10172 IRTemp b3_F64, b2_F64, b1_F64, b0_F64; 10173 IRTemp b3_I64 = newTemp(Ity_I64); 10174 IRTemp b2_I64 = newTemp(Ity_I64); 10175 IRTemp b1_I64 = newTemp(Ity_I64); 10176 IRTemp b0_I64 = newTemp(Ity_I64); 10177 10178 b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID; 10179 frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL; 10180 breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64); 10181 assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64))); 10182 assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64))); 10183 assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64))); 10184 assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64))); 10185 frD_fp_roundb3 = unop(Iop_TruncF64asF32, 10186 _do_vsx_fp_roundToInt(b3_I64, opc2, insn_suffix)); 10187 frD_fp_roundb2 = unop(Iop_TruncF64asF32, 10188 _do_vsx_fp_roundToInt(b2_I64, opc2, insn_suffix)); 10189 frD_fp_roundb1 = unop(Iop_TruncF64asF32, 10190 _do_vsx_fp_roundToInt(b1_I64, opc2, insn_suffix)); 10191 frD_fp_roundb0 = unop(Iop_TruncF64asF32, 10192 _do_vsx_fp_roundToInt(b0_I64, opc2, insn_suffix)); 10193 DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB); 10194 putVSReg( XT, 10195 binop( Iop_64HLtoV128, 10196 binop( Iop_32HLto64, 10197 unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ), 10198 unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ), 10199 binop( Iop_32HLto64, 10200 unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ), 10201 unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) ); 10202 } 10203 break; 10204 } 10205 10206 default: 10207 vex_printf( "dis_vxv_misc(ppc)(opc2)\n" ); 10208 return False; 10209 } 10210 return True; 10211} 10212 10213 10214/* 10215 * VSX Scalar Floating Point Arithmetic Instructions 10216 */ 10217static Bool 10218dis_vxs_arith ( UInt theInstr, UInt opc2 ) 10219{ 10220 /* XX3-Form */ 10221 UChar opc1 = ifieldOPC( theInstr ); 10222 UChar XT = ifieldRegXT( theInstr ); 10223 UChar XA = ifieldRegXA( theInstr ); 10224 UChar XB = ifieldRegXB( theInstr ); 10225 IRExpr* rm = get_IR_roundingmode(); 10226 IRTemp frA = newTemp(Ity_F64); 10227 IRTemp frB = newTemp(Ity_F64); 10228 10229 if (opc1 != 0x3C) { 10230 vex_printf( "dis_vxs_arith(ppc)(instr)\n" ); 10231 return False; 10232 } 10233 10234 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 10235 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 10236 10237 /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1 10238 * of VSX[XT] are undefined after the operation; therefore, we can simply set 10239 * element to zero where it makes sense to do so. 10240 */ 10241 switch (opc2) { 10242 case 0x080: // xsadddp (VSX scalar add double-precision) 10243 DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 10244 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 10245 triop( Iop_AddF64, rm, 10246 mkexpr( frA ), 10247 mkexpr( frB ) ) ), 10248 mkU64( 0 ) ) ); 10249 break; 10250 case 0x0E0: // xsdivdp (VSX scalar divide double-precision) 10251 DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 10252 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 10253 triop( Iop_DivF64, rm, 10254 mkexpr( frA ), 10255 mkexpr( frB ) ) ), 10256 mkU64( 0 ) ) ); 10257 break; 10258 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision) 10259 { 10260 IRTemp frT = newTemp(Ity_F64); 10261 Bool mdp = opc2 == 0x0A4; 10262 DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 10263 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 10264 getVSReg( XT ) ) ) ); 10265 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 10266 qop( Iop_MAddF64, rm, 10267 mkexpr( frA ), 10268 mkexpr( mdp ? frT : frB ), 10269 mkexpr( mdp ? frB : frT ) ) ), 10270 mkU64( 0 ) ) ); 10271 break; 10272 } 10273 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision) 10274 { 10275 IRTemp frT = newTemp(Ity_F64); 10276 Bool mdp = opc2 == 0x0E4; 10277 DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 10278 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 10279 getVSReg( XT ) ) ) ); 10280 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 10281 qop( Iop_MSubF64, rm, 10282 mkexpr( frA ), 10283 mkexpr( mdp ? frT : frB ), 10284 mkexpr( mdp ? frB : frT ) ) ), 10285 mkU64( 0 ) ) ); 10286 break; 10287 } 10288 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision) 10289 { 10290 /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation 10291 * of fnmadd and use pretty much the same code. However, that code has a bug in the 10292 * way it blindly negates the signbit, even if the floating point result is a NaN. 10293 * So, the TODO is to fix fnmadd (which I'll do in a different patch). 10294 */ 10295 Bool mdp = opc2 == 0x2A4; 10296 IRTemp frT = newTemp(Ity_F64); 10297 IRTemp maddResult = newTemp(Ity_I64); 10298 10299 DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 10300 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 10301 getVSReg( XT ) ) ) ); 10302 assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm, 10303 mkexpr( frA ), 10304 mkexpr( mdp ? frT : frB ), 10305 mkexpr( mdp ? frB : frT ) ) ) ); 10306 10307 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ), 10308 mkU64( 0 ) ) ); 10309 break; 10310 } 10311 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision) 10312 { 10313 IRTemp frT = newTemp(Ity_F64); 10314 Bool mdp = opc2 == 0x2E4; 10315 IRTemp msubResult = newTemp(Ity_I64); 10316 10317 DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 10318 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 10319 getVSReg( XT ) ) ) ); 10320 assign(msubResult, unop( Iop_ReinterpF64asI64, 10321 qop( Iop_MSubF64, 10322 rm, 10323 mkexpr( frA ), 10324 mkexpr( mdp ? frT : frB ), 10325 mkexpr( mdp ? frB : frT ) ) )); 10326 10327 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) ); 10328 10329 break; 10330 } 10331 10332 case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision) 10333 DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 10334 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 10335 triop( Iop_MulF64, rm, 10336 mkexpr( frA ), 10337 mkexpr( frB ) ) ), 10338 mkU64( 0 ) ) ); 10339 break; 10340 case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision) 10341 DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 10342 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 10343 triop( Iop_SubF64, rm, 10344 mkexpr( frA ), 10345 mkexpr( frB ) ) ), 10346 mkU64( 0 ) ) ); 10347 break; 10348 10349 case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision) 10350 DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 10351 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 10352 binop( Iop_SqrtF64, rm, 10353 mkexpr( frB ) ) ), 10354 mkU64( 0 ) ) ); 10355 break; 10356 10357 case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision) 10358 { 10359 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 10360 IRTemp frA_I64 = newTemp(Ity_I64); 10361 IRTemp frB_I64 = newTemp(Ity_I64); 10362 DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB); 10363 assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) ); 10364 assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 10365 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 10366 break; 10367 } 10368 case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision) 10369 { 10370 IRTemp frB_I64 = newTemp(Ity_I64); 10371 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 10372 IRTemp flags = newTemp(Ity_I32); 10373 IRTemp fe_flag, fg_flag; 10374 fe_flag = fg_flag = IRTemp_INVALID; 10375 DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 10376 assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 10377 do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag); 10378 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 10379 * where fl_flag == 1 on ppc64. 10380 */ 10381 assign( flags, 10382 binop( Iop_Or32, 10383 binop( Iop_Or32, mkU32( 8 ), // fl_flag 10384 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 10385 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 10386 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 10387 break; 10388 } 10389 10390 default: 10391 vex_printf( "dis_vxs_arith(ppc)(opc2)\n" ); 10392 return False; 10393 } 10394 10395 return True; 10396} 10397 10398 10399/* 10400 * VSX Floating Point Compare Instructions 10401 */ 10402static Bool 10403dis_vx_cmp( UInt theInstr, UInt opc2 ) 10404{ 10405 /* XX3-Form and XX2-Form */ 10406 UChar opc1 = ifieldOPC( theInstr ); 10407 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 10408 IRTemp ccPPC32; 10409 UChar XA = ifieldRegXA ( theInstr ); 10410 UChar XB = ifieldRegXB ( theInstr ); 10411 IRTemp frA = newTemp(Ity_F64); 10412 IRTemp frB = newTemp(Ity_F64); 10413 10414 if (opc1 != 0x3C) { 10415 vex_printf( "dis_vx_cmp(ppc)(instr)\n" ); 10416 return False; 10417 } 10418 10419 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 10420 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 10421 switch (opc2) { 10422 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 10423 /* Note: Differences between xscmpudp and xscmpodp are only in 10424 * exception flag settings, which aren't supported anyway. */ 10425 DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o", 10426 crfD, (UInt)XA, (UInt)XB); 10427 ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB))); 10428 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 10429 break; 10430 10431 default: 10432 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" ); 10433 return False; 10434 } 10435 return True; 10436} 10437 10438static void 10439do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC, 10440 ppc_cmp_t cmp_type ) 10441{ 10442 IRTemp frA_hi = newTemp(Ity_F64); 10443 IRTemp frB_hi = newTemp(Ity_F64); 10444 IRTemp frA_lo = newTemp(Ity_F64); 10445 IRTemp frB_lo = newTemp(Ity_F64); 10446 IRTemp ccPPC32 = newTemp(Ity_I32); 10447 IRTemp ccIR_hi; 10448 IRTemp ccIR_lo; 10449 10450 IRTemp hiResult = newTemp(Ity_I64); 10451 IRTemp loResult = newTemp(Ity_I64); 10452 IRTemp hiEQlo = newTemp(Ity_I1); 10453 IRTemp all_elem_true = newTemp(Ity_I32); 10454 IRTemp all_elem_false = newTemp(Ity_I32); 10455 10456 assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA )))); 10457 assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB )))); 10458 assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA )))); 10459 assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB )))); 10460 10461 ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64, 10462 mkexpr( frA_hi ), 10463 mkexpr( frB_hi ) ) ); 10464 ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64, 10465 mkexpr( frA_lo ), 10466 mkexpr( frB_lo ) ) ); 10467 10468 if (cmp_type != PPC_CMP_GE) { 10469 assign( hiResult, 10470 unop( Iop_1Sto64, 10471 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) ); 10472 assign( loResult, 10473 unop( Iop_1Sto64, 10474 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) ); 10475 } else { 10476 // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and 10477 // the other element compare may return "2" (for "equal to"). 10478 IRTemp lo_GE = newTemp(Ity_I1); 10479 IRTemp hi_GE = newTemp(Ity_I1); 10480 10481 assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ), 10482 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) ); 10483 assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) ); 10484 10485 assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ), 10486 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) ); 10487 assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) ); 10488 } 10489 10490 // The [hi/lo]Result will be all 1's or all 0's. We just look at the lower word. 10491 assign( hiEQlo, 10492 binop( Iop_CmpEQ32, 10493 unop( Iop_64to32, mkexpr( hiResult ) ), 10494 unop( Iop_64to32, mkexpr( loResult ) ) ) ); 10495 putVSReg( XT, 10496 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 10497 10498 assign( all_elem_true, 10499 unop( Iop_1Uto32, 10500 mkAND1( mkexpr( hiEQlo ), 10501 binop( Iop_CmpEQ32, 10502 mkU32( 0xffffffff ), 10503 unop( Iop_64to32, 10504 mkexpr( hiResult ) ) ) ) ) ); 10505 10506 assign( all_elem_false, 10507 unop( Iop_1Uto32, 10508 mkAND1( mkexpr( hiEQlo ), 10509 binop( Iop_CmpEQ32, 10510 mkU32( 0 ), 10511 unop( Iop_64to32, 10512 mkexpr( hiResult ) ) ) ) ) ); 10513 assign( ccPPC32, 10514 binop( Iop_Or32, 10515 binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ), 10516 binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) ); 10517 10518 if (flag_rC) { 10519 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 ); 10520 } 10521} 10522 10523/* 10524 * VSX Vector Compare Instructions 10525 */ 10526static Bool 10527dis_vvec_cmp( UInt theInstr, UInt opc2 ) 10528{ 10529 /* XX3-Form */ 10530 UChar opc1 = ifieldOPC( theInstr ); 10531 UChar XT = ifieldRegXT ( theInstr ); 10532 UChar XA = ifieldRegXA ( theInstr ); 10533 UChar XB = ifieldRegXB ( theInstr ); 10534 UChar flag_rC = ifieldBIT10(theInstr); 10535 IRTemp vA = newTemp( Ity_V128 ); 10536 IRTemp vB = newTemp( Ity_V128 ); 10537 10538 if (opc1 != 0x3C) { 10539 vex_printf( "dis_vvec_cmp(ppc)(instr)\n" ); 10540 return False; 10541 } 10542 10543 assign( vA, getVSReg( XA ) ); 10544 assign( vB, getVSReg( XB ) ); 10545 10546 switch (opc2) { 10547 case 0x18C: case 0x38C: // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ]) 10548 { 10549 DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 10550 (UInt)XT, (UInt)XA, (UInt)XB); 10551 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ); 10552 break; 10553 } 10554 10555 case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ]) 10556 { 10557 DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 10558 (UInt)XT, (UInt)XA, (UInt)XB); 10559 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE); 10560 break; 10561 } 10562 10563 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ]) 10564 { 10565 DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 10566 (UInt)XT, (UInt)XA, (UInt)XB); 10567 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT); 10568 break; 10569 } 10570 10571 case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ]) 10572 { 10573 IRTemp vD = newTemp(Ity_V128); 10574 10575 DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 10576 (UInt)XT, (UInt)XA, (UInt)XB); 10577 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 10578 putVSReg( XT, mkexpr(vD) ); 10579 if (flag_rC) { 10580 set_AV_CR6( mkexpr(vD), True ); 10581 } 10582 break; 10583 } 10584 10585 case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ]) 10586 { 10587 IRTemp vD = newTemp(Ity_V128); 10588 10589 DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 10590 (UInt)XT, (UInt)XA, (UInt)XB); 10591 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 10592 putVSReg( XT, mkexpr(vD) ); 10593 if (flag_rC) { 10594 set_AV_CR6( mkexpr(vD), True ); 10595 } 10596 break; 10597 } 10598 10599 case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ]) 10600 { 10601 IRTemp vD = newTemp(Ity_V128); 10602 10603 DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 10604 (UInt)XT, (UInt)XA, (UInt)XB); 10605 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 10606 putVSReg( XT, mkexpr(vD) ); 10607 if (flag_rC) { 10608 set_AV_CR6( mkexpr(vD), True ); 10609 } 10610 break; 10611 } 10612 10613 default: 10614 vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" ); 10615 return False; 10616 } 10617 return True; 10618} 10619/* 10620 * Miscellaneous VSX Scalar Instructions 10621 */ 10622static Bool 10623dis_vxs_misc( UInt theInstr, UInt opc2 ) 10624{ 10625 /* XX3-Form and XX2-Form */ 10626 UChar opc1 = ifieldOPC( theInstr ); 10627 UChar XT = ifieldRegXT ( theInstr ); 10628 UChar XA = ifieldRegXA ( theInstr ); 10629 UChar XB = ifieldRegXB ( theInstr ); 10630 IRTemp vA = newTemp( Ity_V128 ); 10631 IRTemp vB = newTemp( Ity_V128 ); 10632 10633 if (opc1 != 0x3C) { 10634 vex_printf( "dis_vxs_misc(ppc)(instr)\n" ); 10635 return False; 10636 } 10637 10638 assign( vA, getVSReg( XA ) ); 10639 assign( vB, getVSReg( XB ) ); 10640 10641 /* For all the VSX move instructions, the contents of doubleword element 1 10642 * of VSX[XT] are undefined after the operation; therefore, we can simply 10643 * move the entire array element where it makes sense to do so. 10644 */ 10645 10646 switch (opc2) { 10647 case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision 10648 { 10649 /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */ 10650 IRTemp absVal = newTemp(Ity_V128); 10651 assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1))); 10652 DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 10653 putVSReg(XT, mkexpr(absVal)); 10654 break; 10655 } 10656 case 0x2C0: // xscpsgndp 10657 { 10658 /* Scalar copy sign double-precision */ 10659 IRTemp vecA_signbit = newTemp(Ity_V128); 10660 IRTemp vecB_no_signbit = newTemp(Ity_V128); 10661 IRTemp vec_result = newTemp(Ity_V128); 10662 DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 10663 assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128, 10664 mkexpr( vB ), 10665 mkU8( 1 ) ), 10666 mkU8( 1 ) ) ); 10667 assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128, 10668 mkexpr( vA ), 10669 mkU8( 127 ) ), 10670 mkU8( 127 ) ) ); 10671 assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) ); 10672 putVSReg(XT, mkexpr(vec_result)); 10673 break; 10674 } 10675 case 0x2D2: // xsnabsdp 10676 { 10677 /* Scalar negative absolute value double-precision */ 10678 IRTemp vec_neg_signbit = newTemp(Ity_V128); 10679 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 10680 assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128, 10681 mkV128( 0xffff ), 10682 mkU8( 1 ) ) ) ); 10683 putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB))); 10684 break; 10685 } 10686 case 0x2F2: // xsnegdp 10687 { 10688 /* Scalar negate double-precision */ 10689 IRTemp vecB_no_signbit = newTemp(Ity_V128); 10690 IRTemp vecB_signbit_comp = newTemp(Ity_V128); 10691 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 10692 assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128, 10693 mkexpr( vB ), 10694 mkU8( 1 ) ), 10695 mkU8( 1 ) ) ); 10696 assign( vecB_signbit_comp, binop( Iop_ShlV128, 10697 unop( Iop_NotV128, 10698 binop( Iop_ShrV128, 10699 mkexpr( vB ), 10700 mkU8( 127 ) ) ), 10701 mkU8( 127 ) ) ); 10702 putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ), 10703 mkexpr( vecB_signbit_comp ) ) ); 10704 break; 10705 } 10706 case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision) 10707 case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision) 10708 { 10709 IRTemp frA = newTemp(Ity_I64); 10710 IRTemp frB = newTemp(Ity_I64); 10711 Bool isMin = opc2 == 0x2A0 ? True : False; 10712 DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB); 10713 10714 assign(frA, unop(Iop_V128HIto64, mkexpr( vA ))); 10715 assign(frB, unop(Iop_V128HIto64, mkexpr( vB ))); 10716 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) ); 10717 10718 break; 10719 } 10720 case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity) 10721 case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity) 10722 case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode) 10723 case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero) 10724 case 0x092: // xsrdpi (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away) 10725 { 10726 IRTemp frB_I64 = newTemp(Ity_I64); 10727 IRExpr * frD_fp_round = NULL; 10728 UChar * insn_suffix = NULL; 10729 10730 assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB ))); 10731 frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2, insn_suffix); 10732 10733 DIP("xsrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB); 10734 putVSReg( XT, 10735 binop( Iop_64HLtoV128, 10736 unop( Iop_ReinterpF64asI64, frD_fp_round), 10737 mkU64( 0 ) ) ); 10738 break; 10739 } 10740 case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision) 10741 case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision) 10742 10743 { 10744 IRTemp frB = newTemp(Ity_F64); 10745 IRTemp sqrt = newTemp(Ity_F64); 10746 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 10747 IRExpr* rm = get_IR_roundingmode(); 10748 Bool redp = opc2 == 0x0B4; 10749 DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB); 10750 assign( frB, 10751 unop( Iop_ReinterpI64asF64, 10752 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 10753 10754 if (!redp) 10755 assign( sqrt, 10756 binop( Iop_SqrtF64, 10757 rm, 10758 mkexpr(frB) ) ); 10759 putVSReg( XT, 10760 binop( Iop_64HLtoV128, 10761 unop( Iop_ReinterpF64asI64, 10762 triop( Iop_DivF64, 10763 rm, 10764 ieee_one, 10765 redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ), 10766 mkU64( 0 ) ) ); 10767 break; 10768 } 10769 10770 default: 10771 vex_printf( "dis_vxs_misc(ppc)(opc2)\n" ); 10772 return False; 10773 } 10774 return True; 10775} 10776 10777/* 10778 * VSX Logical Instructions 10779 */ 10780static Bool 10781dis_vx_logic ( UInt theInstr, UInt opc2 ) 10782{ 10783 /* XX3-Form */ 10784 UChar opc1 = ifieldOPC( theInstr ); 10785 UChar XT = ifieldRegXT ( theInstr ); 10786 UChar XA = ifieldRegXA ( theInstr ); 10787 UChar XB = ifieldRegXB ( theInstr ); 10788 IRTemp vA = newTemp( Ity_V128 ); 10789 IRTemp vB = newTemp( Ity_V128 ); 10790 10791 if (opc1 != 0x3C) { 10792 vex_printf( "dis_vx_logic(ppc)(instr)\n" ); 10793 return False; 10794 } 10795 10796 assign( vA, getVSReg( XA ) ); 10797 assign( vB, getVSReg( XB ) ); 10798 10799 switch (opc2) { 10800 case 0x268: // xxlxor 10801 DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 10802 putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) ); 10803 break; 10804 case 0x248: // xxlor 10805 DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 10806 putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) ); 10807 break; 10808 case 0x288: // xxlnor 10809 DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 10810 putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ), 10811 mkexpr( vB ) ) ) ); 10812 break; 10813 case 0x208: // xxland 10814 DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 10815 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) ); 10816 break; 10817 case 0x228: //xxlandc 10818 DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 10819 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128, 10820 mkexpr( vB ) ) ) ); 10821 break; 10822 default: 10823 vex_printf( "dis_vx_logic(ppc)(opc2)\n" ); 10824 return False; 10825 } 10826 return True; 10827} 10828 10829/* 10830 * VSX Load Instructions 10831 * NOTE: VSX supports word-aligned storage access. 10832 */ 10833static Bool 10834dis_vx_load ( UInt theInstr ) 10835{ 10836 /* XX1-Form */ 10837 UChar opc1 = ifieldOPC( theInstr ); 10838 UChar XT = ifieldRegXT ( theInstr ); 10839 UChar rA_addr = ifieldRegA( theInstr ); 10840 UChar rB_addr = ifieldRegB( theInstr ); 10841 UInt opc2 = ifieldOPClo10( theInstr ); 10842 10843 IRType ty = mode64 ? Ity_I64 : Ity_I32; 10844 IRTemp EA = newTemp( ty ); 10845 10846 if (opc1 != 0x1F) { 10847 vex_printf( "dis_vx_load(ppc)(instr)\n" ); 10848 return False; 10849 } 10850 10851 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 10852 10853 switch (opc2) { 10854 case 0x24C: // lxsdx 10855 { 10856 IRExpr * exp; 10857 DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 10858 exp = loadBE( Ity_I64, mkexpr( EA ) ); 10859 // We need to pass an expression of type Ity_V128 with putVSReg, but the load 10860 // we just performed is only a DW. But since the contents of VSR[XT] element 1 10861 // are undefined after this operation, we can just do a splat op. 10862 putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) ); 10863 break; 10864 } 10865 case 0x34C: // lxvd2x 10866 { 10867 IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32; 10868 IRExpr * high, *low; 10869 ULong ea_off = 8; 10870 IRExpr* high_addr; 10871 DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 10872 high = loadBE( Ity_I64, mkexpr( EA ) ); 10873 high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off ) 10874 : mkU32( ea_off ) ); 10875 low = loadBE( Ity_I64, high_addr ); 10876 putVSReg( XT, binop( Iop_64HLtoV128, high, low ) ); 10877 break; 10878 } 10879 case 0x14C: // lxvdsx 10880 { 10881 IRTemp data = newTemp(Ity_I64); 10882 DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 10883 assign( data, loadBE( Ity_I64, mkexpr( EA ) ) ); 10884 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) ); 10885 break; 10886 } 10887 case 0x30C: 10888 { 10889 IRExpr * t3, *t2, *t1, *t0; 10890 UInt ea_off = 0; 10891 IRExpr* irx_addr; 10892 10893 DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 10894 t3 = loadBE( Ity_I32, mkexpr( EA ) ); 10895 ea_off += 4; 10896 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 10897 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 10898 t2 = loadBE( Ity_I32, irx_addr ); 10899 ea_off += 4; 10900 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 10901 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 10902 t1 = loadBE( Ity_I32, irx_addr ); 10903 ea_off += 4; 10904 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 10905 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 10906 t0 = loadBE( Ity_I32, irx_addr ); 10907 putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ), 10908 binop( Iop_32HLto64, t1, t0 ) ) ); 10909 break; 10910 } 10911 default: 10912 vex_printf( "dis_vx_load(ppc)(opc2)\n" ); 10913 return False; 10914 } 10915 return True; 10916} 10917 10918/* 10919 * VSX Store Instructions 10920 * NOTE: VSX supports word-aligned storage access. 10921 */ 10922static Bool 10923dis_vx_store ( UInt theInstr ) 10924{ 10925 /* XX1-Form */ 10926 UChar opc1 = ifieldOPC( theInstr ); 10927 UChar XS = ifieldRegXS( theInstr ); 10928 UChar rA_addr = ifieldRegA( theInstr ); 10929 UChar rB_addr = ifieldRegB( theInstr ); 10930 IRTemp vS = newTemp( Ity_V128 ); 10931 UInt opc2 = ifieldOPClo10( theInstr ); 10932 10933 IRType ty = mode64 ? Ity_I64 : Ity_I32; 10934 IRTemp EA = newTemp( ty ); 10935 10936 if (opc1 != 0x1F) { 10937 vex_printf( "dis_vx_store(ppc)(instr)\n" ); 10938 return False; 10939 } 10940 10941 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 10942 assign( vS, getVSReg( XS ) ); 10943 10944 switch (opc2) { 10945 case 0x2CC: 10946 { 10947 IRExpr * high64; 10948 DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 10949 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 10950 storeBE( mkexpr( EA ), high64 ); 10951 break; 10952 } 10953 case 0x3CC: 10954 { 10955 IRExpr * high64, *low64; 10956 DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 10957 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 10958 low64 = unop( Iop_V128to64, mkexpr( vS ) ); 10959 storeBE( mkexpr( EA ), high64 ); 10960 storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 ) 10961 : mkU32( 8 ) ), low64 ); 10962 break; 10963 } 10964 case 0x38C: 10965 { 10966 UInt ea_off = 0; 10967 IRExpr* irx_addr; 10968 IRTemp hi64 = newTemp( Ity_I64 ); 10969 IRTemp lo64 = newTemp( Ity_I64 ); 10970 10971 DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 10972 10973 // This instruction supports word-aligned stores, so EA may not be 10974 // quad-word aligned. Therefore, do 4 individual word-size stores. 10975 assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) ); 10976 assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) ); 10977 10978 storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) ); 10979 ea_off += 4; 10980 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 10981 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 10982 storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) ); 10983 ea_off += 4; 10984 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 10985 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 10986 storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) ); 10987 ea_off += 4; 10988 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 10989 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 10990 storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) ); 10991 10992 break; 10993 } 10994 default: 10995 vex_printf( "dis_vx_store(ppc)(opc2)\n" ); 10996 return False; 10997 } 10998 return True; 10999} 11000 11001/* 11002 * VSX permute and other miscealleous instructions 11003 */ 11004static Bool 11005dis_vx_permute_misc( UInt theInstr, UInt opc2 ) 11006{ 11007 /* XX3-Form */ 11008 UChar opc1 = ifieldOPC( theInstr ); 11009 UChar XT = ifieldRegXT ( theInstr ); 11010 UChar XA = ifieldRegXA ( theInstr ); 11011 UChar XB = ifieldRegXB ( theInstr ); 11012 IRTemp vT = newTemp( Ity_V128 ); 11013 IRTemp vA = newTemp( Ity_V128 ); 11014 IRTemp vB = newTemp( Ity_V128 ); 11015 11016 if (opc1 != 0x3C) { 11017 vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" ); 11018 return False; 11019 } 11020 11021 assign( vA, getVSReg( XA ) ); 11022 assign( vB, getVSReg( XB ) ); 11023 11024 switch (opc2) { 11025 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate) 11026 { 11027 UChar SHW = ifieldSHW ( theInstr ); 11028 IRTemp result = newTemp(Ity_V128); 11029 if ( SHW != 0 ) { 11030 IRTemp hi = newTemp(Ity_V128); 11031 IRTemp lo = newTemp(Ity_V128); 11032 assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) ); 11033 assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) ); 11034 assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) ); 11035 } else 11036 assign ( result, mkexpr(vA) ); 11037 DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW); 11038 putVSReg( XT, mkexpr(result) ); 11039 break; 11040 } 11041 case 0x28: // xpermdi (VSX Permute Doubleword Immediate) 11042 { 11043 UChar DM = ifieldDM ( theInstr ); 11044 IRTemp hi = newTemp(Ity_I64); 11045 IRTemp lo = newTemp(Ity_I64); 11046 11047 if (DM & 0x2) 11048 assign( hi, unop(Iop_V128to64, mkexpr(vA)) ); 11049 else 11050 assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) ); 11051 11052 if (DM & 0x1) 11053 assign( lo, unop(Iop_V128to64, mkexpr(vB)) ); 11054 else 11055 assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) ); 11056 11057 assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) ); 11058 11059 DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM); 11060 putVSReg( XT, mkexpr( vT ) ); 11061 break; 11062 } 11063 case 0x48: // xxmrghw (VSX Merge High Word) 11064 case 0xc8: // xxmrglw (VSX Merge Low Word) 11065 { 11066 char type = (opc2 == 0x48) ? 'h' : 'l'; 11067 IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64; 11068 IRTemp a64 = newTemp(Ity_I64); 11069 IRTemp ahi32 = newTemp(Ity_I32); 11070 IRTemp alo32 = newTemp(Ity_I32); 11071 IRTemp b64 = newTemp(Ity_I64); 11072 IRTemp bhi32 = newTemp(Ity_I32); 11073 IRTemp blo32 = newTemp(Ity_I32); 11074 11075 assign( a64, unop(word_op, mkexpr(vA)) ); 11076 assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) ); 11077 assign( alo32, unop(Iop_64to32, mkexpr(a64)) ); 11078 11079 assign( b64, unop(word_op, mkexpr(vB)) ); 11080 assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) ); 11081 assign( blo32, unop(Iop_64to32, mkexpr(b64)) ); 11082 11083 assign( vT, binop(Iop_64HLtoV128, 11084 binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)), 11085 binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) ); 11086 11087 DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB); 11088 putVSReg( XT, mkexpr( vT ) ); 11089 break; 11090 } 11091 case 0x018: // xxsel (VSX Select) 11092 { 11093 UChar XC = ifieldRegXC(theInstr); 11094 IRTemp vC = newTemp( Ity_V128 ); 11095 assign( vC, getVSReg( XC ) ); 11096 DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC); 11097 /* vD = (vA & ~vC) | (vB & vC) */ 11098 putVSReg( XT, binop(Iop_OrV128, 11099 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 11100 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 11101 break; 11102 } 11103 case 0x148: // xxspltw (VSX Splat Word) 11104 { 11105 UChar UIM = ifieldRegA(theInstr) & 3; 11106 UChar sh_uim = (3 - (UIM)) * 32; 11107 DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM); 11108 putVSReg( XT, 11109 unop( Iop_Dup32x4, 11110 unop( Iop_V128to32, 11111 binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) ); 11112 break; 11113 } 11114 11115 default: 11116 vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" ); 11117 return False; 11118 } 11119 return True; 11120} 11121 11122/* 11123 AltiVec Load Instructions 11124*/ 11125static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr ) 11126{ 11127 /* X-Form */ 11128 UChar opc1 = ifieldOPC(theInstr); 11129 UChar vD_addr = ifieldRegDS(theInstr); 11130 UChar rA_addr = ifieldRegA(theInstr); 11131 UChar rB_addr = ifieldRegB(theInstr); 11132 UInt opc2 = ifieldOPClo10(theInstr); 11133 UChar b0 = ifieldBIT0(theInstr); 11134 11135 IRType ty = mode64 ? Ity_I64 : Ity_I32; 11136 IRTemp EA = newTemp(ty); 11137 IRTemp EA_align16 = newTemp(ty); 11138 11139 if (opc1 != 0x1F || b0 != 0) { 11140 vex_printf("dis_av_load(ppc)(instr)\n"); 11141 return False; 11142 } 11143 11144 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 11145 assign( EA_align16, addr_align( mkexpr(EA), 16 ) ); 11146 11147 switch (opc2) { 11148 11149 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123) 11150 IRDirty* d; 11151 UInt vD_off = vectorGuestRegOffset(vD_addr); 11152 IRExpr** args = mkIRExprVec_3( 11153 mkU32(vD_off), 11154 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 11155 mkU32(0xF)), 11156 mkU32(0)/*left*/ ); 11157 if (!mode64) { 11158 d = unsafeIRDirty_0_N ( 11159 0/*regparms*/, 11160 "ppc32g_dirtyhelper_LVS", 11161 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 11162 args ); 11163 } else { 11164 d = unsafeIRDirty_0_N ( 11165 0/*regparms*/, 11166 "ppc64g_dirtyhelper_LVS", 11167 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 11168 args ); 11169 } 11170 DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 11171 /* declare guest state effects */ 11172 d->needsBBP = True; 11173 d->nFxState = 1; 11174 d->fxState[0].fx = Ifx_Write; 11175 d->fxState[0].offset = vD_off; 11176 d->fxState[0].size = sizeof(U128); 11177 11178 /* execute the dirty call, side-effecting guest state */ 11179 stmt( IRStmt_Dirty(d) ); 11180 break; 11181 } 11182 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125) 11183 IRDirty* d; 11184 UInt vD_off = vectorGuestRegOffset(vD_addr); 11185 IRExpr** args = mkIRExprVec_3( 11186 mkU32(vD_off), 11187 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 11188 mkU32(0xF)), 11189 mkU32(1)/*right*/ ); 11190 if (!mode64) { 11191 d = unsafeIRDirty_0_N ( 11192 0/*regparms*/, 11193 "ppc32g_dirtyhelper_LVS", 11194 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 11195 args ); 11196 } else { 11197 d = unsafeIRDirty_0_N ( 11198 0/*regparms*/, 11199 "ppc64g_dirtyhelper_LVS", 11200 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 11201 args ); 11202 } 11203 DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 11204 /* declare guest state effects */ 11205 d->needsBBP = True; 11206 d->nFxState = 1; 11207 d->fxState[0].fx = Ifx_Write; 11208 d->fxState[0].offset = vD_off; 11209 d->fxState[0].size = sizeof(U128); 11210 11211 /* execute the dirty call, side-effecting guest state */ 11212 stmt( IRStmt_Dirty(d) ); 11213 break; 11214 } 11215 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119) 11216 DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 11217 /* loads addressed byte into vector[EA[0:3] 11218 since all other destination bytes are undefined, 11219 can simply load entire vector from 16-aligned EA */ 11220 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 11221 break; 11222 11223 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121) 11224 DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 11225 /* see note for lvebx */ 11226 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 11227 break; 11228 11229 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122) 11230 DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 11231 /* see note for lvebx */ 11232 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 11233 break; 11234 11235 case 0x067: // lvx (Load Vector Indexed, AV p127) 11236 DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 11237 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 11238 break; 11239 11240 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128) 11241 DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 11242 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 11243 break; 11244 11245 default: 11246 vex_printf("dis_av_load(ppc)(opc2)\n"); 11247 return False; 11248 } 11249 return True; 11250} 11251 11252/* 11253 AltiVec Store Instructions 11254*/ 11255static Bool dis_av_store ( UInt theInstr ) 11256{ 11257 /* X-Form */ 11258 UChar opc1 = ifieldOPC(theInstr); 11259 UChar vS_addr = ifieldRegDS(theInstr); 11260 UChar rA_addr = ifieldRegA(theInstr); 11261 UChar rB_addr = ifieldRegB(theInstr); 11262 UInt opc2 = ifieldOPClo10(theInstr); 11263 UChar b0 = ifieldBIT0(theInstr); 11264 11265 IRType ty = mode64 ? Ity_I64 : Ity_I32; 11266 IRTemp EA = newTemp(ty); 11267 IRTemp addr_aligned = newTemp(ty); 11268 IRTemp vS = newTemp(Ity_V128); 11269 IRTemp eb = newTemp(Ity_I8); 11270 IRTemp idx = newTemp(Ity_I8); 11271 11272 if (opc1 != 0x1F || b0 != 0) { 11273 vex_printf("dis_av_store(ppc)(instr)\n"); 11274 return False; 11275 } 11276 11277 assign( vS, getVReg(vS_addr)); 11278 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 11279 11280 switch (opc2) { 11281 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131) 11282 DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 11283 assign( eb, binop(Iop_And8, mkU8(0xF), 11284 unop(Iop_32to8, 11285 mkNarrowTo32(ty, mkexpr(EA)) )) ); 11286 assign( idx, binop(Iop_Shl8, 11287 binop(Iop_Sub8, mkU8(15), mkexpr(eb)), 11288 mkU8(3)) ); 11289 storeBE( mkexpr(EA), 11290 unop(Iop_32to8, unop(Iop_V128to32, 11291 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 11292 break; 11293 } 11294 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132) 11295 DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 11296 assign( addr_aligned, addr_align(mkexpr(EA), 2) ); 11297 assign( eb, binop(Iop_And8, mkU8(0xF), 11298 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 11299 assign( idx, binop(Iop_Shl8, 11300 binop(Iop_Sub8, mkU8(14), mkexpr(eb)), 11301 mkU8(3)) ); 11302 storeBE( mkexpr(addr_aligned), 11303 unop(Iop_32to16, unop(Iop_V128to32, 11304 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 11305 break; 11306 } 11307 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133) 11308 DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 11309 assign( addr_aligned, addr_align(mkexpr(EA), 4) ); 11310 assign( eb, binop(Iop_And8, mkU8(0xF), 11311 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 11312 assign( idx, binop(Iop_Shl8, 11313 binop(Iop_Sub8, mkU8(12), mkexpr(eb)), 11314 mkU8(3)) ); 11315 storeBE( mkexpr(addr_aligned), 11316 unop(Iop_V128to32, 11317 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) ); 11318 break; 11319 } 11320 11321 case 0x0E7: // stvx (Store Vector Indexed, AV p134) 11322 DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 11323 storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 11324 break; 11325 11326 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135) 11327 DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 11328 storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 11329 break; 11330 11331 default: 11332 vex_printf("dis_av_store(ppc)(opc2)\n"); 11333 return False; 11334 } 11335 return True; 11336} 11337 11338/* 11339 AltiVec Arithmetic Instructions 11340*/ 11341static Bool dis_av_arith ( UInt theInstr ) 11342{ 11343 /* VX-Form */ 11344 UChar opc1 = ifieldOPC(theInstr); 11345 UChar vD_addr = ifieldRegDS(theInstr); 11346 UChar vA_addr = ifieldRegA(theInstr); 11347 UChar vB_addr = ifieldRegB(theInstr); 11348 UInt opc2 = IFIELD( theInstr, 0, 11 ); 11349 11350 IRTemp vA = newTemp(Ity_V128); 11351 IRTemp vB = newTemp(Ity_V128); 11352 IRTemp z3 = newTemp(Ity_I64); 11353 IRTemp z2 = newTemp(Ity_I64); 11354 IRTemp z1 = newTemp(Ity_I64); 11355 IRTemp z0 = newTemp(Ity_I64); 11356 IRTemp aEvn, aOdd; 11357 IRTemp a15, a14, a13, a12, a11, a10, a9, a8; 11358 IRTemp a7, a6, a5, a4, a3, a2, a1, a0; 11359 IRTemp b3, b2, b1, b0; 11360 11361 aEvn = aOdd = IRTemp_INVALID; 11362 a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID; 11363 a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID; 11364 b3 = b2 = b1 = b0 = IRTemp_INVALID; 11365 11366 assign( vA, getVReg(vA_addr)); 11367 assign( vB, getVReg(vB_addr)); 11368 11369 if (opc1 != 0x4) { 11370 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n"); 11371 return False; 11372 } 11373 11374 switch (opc2) { 11375 /* Add */ 11376 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136) 11377 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11378 /* unsigned_ov(x+y) = (y >u not(x)) */ 11379 putVReg( vD_addr, binop(Iop_ShrN32x4, 11380 binop(Iop_CmpGT32Ux4, mkexpr(vB), 11381 unop(Iop_NotV128, mkexpr(vA))), 11382 mkU8(31)) ); 11383 break; 11384 } 11385 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141) 11386 DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11387 putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) ); 11388 break; 11389 11390 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143) 11391 DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11392 putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) ); 11393 break; 11394 11395 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145) 11396 DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11397 putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) ); 11398 break; 11399 11400 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142) 11401 DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11402 putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) ); 11403 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16 11404 break; 11405 11406 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144) 11407 DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11408 putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) ); 11409 // TODO: set VSCR[SAT] 11410 break; 11411 11412 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146) 11413 DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11414 putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) ); 11415 // TODO: set VSCR[SAT] 11416 break; 11417 11418 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138) 11419 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11420 putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) ); 11421 // TODO: set VSCR[SAT] 11422 break; 11423 11424 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139) 11425 DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11426 putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) ); 11427 // TODO: set VSCR[SAT] 11428 break; 11429 11430 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140) 11431 DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11432 putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) ); 11433 // TODO: set VSCR[SAT] 11434 break; 11435 11436 11437 /* Subtract */ 11438 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260) 11439 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11440 /* unsigned_ov(x-y) = (y >u x) */ 11441 putVReg( vD_addr, binop(Iop_ShrN32x4, 11442 unop(Iop_NotV128, 11443 binop(Iop_CmpGT32Ux4, mkexpr(vB), 11444 mkexpr(vA))), 11445 mkU8(31)) ); 11446 break; 11447 } 11448 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265) 11449 DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11450 putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) ); 11451 break; 11452 11453 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267) 11454 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11455 putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) ); 11456 break; 11457 11458 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269) 11459 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11460 putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) ); 11461 break; 11462 11463 case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266) 11464 DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11465 putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) ); 11466 // TODO: set VSCR[SAT] 11467 break; 11468 11469 case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268) 11470 DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11471 putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) ); 11472 // TODO: set VSCR[SAT] 11473 break; 11474 11475 case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270) 11476 DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11477 putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) ); 11478 // TODO: set VSCR[SAT] 11479 break; 11480 11481 case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262) 11482 DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11483 putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) ); 11484 // TODO: set VSCR[SAT] 11485 break; 11486 11487 case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263) 11488 DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11489 putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) ); 11490 // TODO: set VSCR[SAT] 11491 break; 11492 11493 case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264) 11494 DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11495 putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) ); 11496 // TODO: set VSCR[SAT] 11497 break; 11498 11499 11500 /* Maximum */ 11501 case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182) 11502 DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11503 putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) ); 11504 break; 11505 11506 case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183) 11507 DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11508 putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) ); 11509 break; 11510 11511 case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184) 11512 DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11513 putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) ); 11514 break; 11515 11516 case 0x102: // vmaxsb (Maximum Signed Byte, AV p179) 11517 DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11518 putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) ); 11519 break; 11520 11521 case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180) 11522 DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11523 putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) ); 11524 break; 11525 11526 case 0x182: // vmaxsw (Maximum Signed Word, AV p181) 11527 DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11528 putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) ); 11529 break; 11530 11531 11532 /* Minimum */ 11533 case 0x202: // vminub (Minimum Unsigned Byte, AV p191) 11534 DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11535 putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) ); 11536 break; 11537 11538 case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192) 11539 DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11540 putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) ); 11541 break; 11542 11543 case 0x282: // vminuw (Minimum Unsigned Word, AV p193) 11544 DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11545 putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) ); 11546 break; 11547 11548 case 0x302: // vminsb (Minimum Signed Byte, AV p188) 11549 DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11550 putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) ); 11551 break; 11552 11553 case 0x342: // vminsh (Minimum Signed Half Word, AV p189) 11554 DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11555 putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) ); 11556 break; 11557 11558 case 0x382: // vminsw (Minimum Signed Word, AV p190) 11559 DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11560 putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) ); 11561 break; 11562 11563 11564 /* Average */ 11565 case 0x402: // vavgub (Average Unsigned Byte, AV p152) 11566 DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11567 putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) ); 11568 break; 11569 11570 case 0x442: // vavguh (Average Unsigned Half Word, AV p153) 11571 DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11572 putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) ); 11573 break; 11574 11575 case 0x482: // vavguw (Average Unsigned Word, AV p154) 11576 DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11577 putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) ); 11578 break; 11579 11580 case 0x502: // vavgsb (Average Signed Byte, AV p149) 11581 DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11582 putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) ); 11583 break; 11584 11585 case 0x542: // vavgsh (Average Signed Half Word, AV p150) 11586 DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11587 putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) ); 11588 break; 11589 11590 case 0x582: // vavgsw (Average Signed Word, AV p151) 11591 DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11592 putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) ); 11593 break; 11594 11595 11596 /* Multiply */ 11597 case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213) 11598 DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11599 putVReg( vD_addr, 11600 binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB))); 11601 break; 11602 11603 case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214) 11604 DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11605 putVReg( vD_addr, 11606 binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB))); 11607 break; 11608 11609 case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211) 11610 DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11611 putVReg( vD_addr, 11612 binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB))); 11613 break; 11614 11615 case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212) 11616 DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11617 putVReg( vD_addr, 11618 binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB))); 11619 break; 11620 11621 case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209) 11622 DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11623 putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 11624 break; 11625 11626 case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210) 11627 DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11628 putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 11629 break; 11630 11631 case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207) 11632 DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11633 putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) )); 11634 break; 11635 11636 case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208) 11637 DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11638 putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 11639 break; 11640 11641 11642 /* Sum Across Partial */ 11643 case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275) 11644 IRTemp aEE, aEO, aOE, aOO; 11645 aEE = aEO = aOE = aOO = IRTemp_INVALID; 11646 DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11647 11648 /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */ 11649 expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 11650 expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 11651 expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 11652 11653 /* break V128 to 4xI32's, zero-extending to I64's */ 11654 breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 11655 breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 11656 breakV128to4x64U( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 11657 breakV128to4x64U( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 11658 breakV128to4x64U( mkexpr(vB), &b3, &b2, &b1, &b0 ); 11659 11660 /* add lanes */ 11661 assign( z3, binop(Iop_Add64, mkexpr(b3), 11662 binop(Iop_Add64, 11663 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 11664 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 11665 assign( z2, binop(Iop_Add64, mkexpr(b2), 11666 binop(Iop_Add64, 11667 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 11668 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 11669 assign( z1, binop(Iop_Add64, mkexpr(b1), 11670 binop(Iop_Add64, 11671 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 11672 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 11673 assign( z0, binop(Iop_Add64, mkexpr(b0), 11674 binop(Iop_Add64, 11675 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 11676 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 11677 11678 /* saturate-narrow to 32bit, and combine to V128 */ 11679 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 11680 mkexpr(z1), mkexpr(z0)) ); 11681 break; 11682 } 11683 case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273) 11684 IRTemp aEE, aEO, aOE, aOO; 11685 aEE = aEO = aOE = aOO = IRTemp_INVALID; 11686 DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11687 11688 /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */ 11689 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 11690 expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 11691 expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 11692 11693 /* break V128 to 4xI32's, sign-extending to I64's */ 11694 breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 11695 breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 11696 breakV128to4x64S( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 11697 breakV128to4x64S( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 11698 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 11699 11700 /* add lanes */ 11701 assign( z3, binop(Iop_Add64, mkexpr(b3), 11702 binop(Iop_Add64, 11703 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 11704 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 11705 assign( z2, binop(Iop_Add64, mkexpr(b2), 11706 binop(Iop_Add64, 11707 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 11708 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 11709 assign( z1, binop(Iop_Add64, mkexpr(b1), 11710 binop(Iop_Add64, 11711 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 11712 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 11713 assign( z0, binop(Iop_Add64, mkexpr(b0), 11714 binop(Iop_Add64, 11715 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 11716 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 11717 11718 /* saturate-narrow to 32bit, and combine to V128 */ 11719 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 11720 mkexpr(z1), mkexpr(z0)) ); 11721 break; 11722 } 11723 case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274) 11724 DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11725 11726 /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */ 11727 expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...) 11728 11729 /* break V128 to 4xI32's, sign-extending to I64's */ 11730 breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 ); 11731 breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 ); 11732 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 11733 11734 /* add lanes */ 11735 assign( z3, binop(Iop_Add64, mkexpr(b3), 11736 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)))); 11737 assign( z2, binop(Iop_Add64, mkexpr(b2), 11738 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))); 11739 assign( z1, binop(Iop_Add64, mkexpr(b1), 11740 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)))); 11741 assign( z0, binop(Iop_Add64, mkexpr(b0), 11742 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))); 11743 11744 /* saturate-narrow to 32bit, and combine to V128 */ 11745 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 11746 mkexpr(z1), mkexpr(z0)) ); 11747 break; 11748 } 11749 case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272) 11750 DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11751 11752 /* break V128 to 4xI32's, sign-extending to I64's */ 11753 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 11754 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 11755 11756 /* add lanes */ 11757 assign( z2, binop(Iop_Add64, mkexpr(b2), 11758 binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) ); 11759 assign( z0, binop(Iop_Add64, mkexpr(b0), 11760 binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) ); 11761 11762 /* saturate-narrow to 32bit, and combine to V128 */ 11763 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2), 11764 mkU64(0), mkexpr(z0)) ); 11765 break; 11766 } 11767 case 0x788: { // vsumsws (Sum SW Saturate, AV p271) 11768 DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11769 11770 /* break V128 to 4xI32's, sign-extending to I64's */ 11771 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 11772 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 11773 11774 /* add lanes */ 11775 assign( z0, binop(Iop_Add64, mkexpr(b0), 11776 binop(Iop_Add64, 11777 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 11778 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 11779 11780 /* saturate-narrow to 32bit, and combine to V128 */ 11781 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0), 11782 mkU64(0), mkexpr(z0)) ); 11783 break; 11784 } 11785 default: 11786 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2); 11787 return False; 11788 } 11789 return True; 11790} 11791 11792/* 11793 AltiVec Logic Instructions 11794*/ 11795static Bool dis_av_logic ( UInt theInstr ) 11796{ 11797 /* VX-Form */ 11798 UChar opc1 = ifieldOPC(theInstr); 11799 UChar vD_addr = ifieldRegDS(theInstr); 11800 UChar vA_addr = ifieldRegA(theInstr); 11801 UChar vB_addr = ifieldRegB(theInstr); 11802 UInt opc2 = IFIELD( theInstr, 0, 11 ); 11803 11804 IRTemp vA = newTemp(Ity_V128); 11805 IRTemp vB = newTemp(Ity_V128); 11806 assign( vA, getVReg(vA_addr)); 11807 assign( vB, getVReg(vB_addr)); 11808 11809 if (opc1 != 0x4) { 11810 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n"); 11811 return False; 11812 } 11813 11814 switch (opc2) { 11815 case 0x404: // vand (And, AV p147) 11816 DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11817 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) ); 11818 break; 11819 11820 case 0x444: // vandc (And, AV p148) 11821 DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11822 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), 11823 unop(Iop_NotV128, mkexpr(vB))) ); 11824 break; 11825 11826 case 0x484: // vor (Or, AV p217) 11827 DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11828 putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) ); 11829 break; 11830 11831 case 0x4C4: // vxor (Xor, AV p282) 11832 DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11833 putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) ); 11834 break; 11835 11836 case 0x504: // vnor (Nor, AV p216) 11837 DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 11838 putVReg( vD_addr, 11839 unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) ); 11840 break; 11841 11842 default: 11843 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2); 11844 return False; 11845 } 11846 return True; 11847} 11848 11849/* 11850 AltiVec Compare Instructions 11851*/ 11852static Bool dis_av_cmp ( UInt theInstr ) 11853{ 11854 /* VXR-Form */ 11855 UChar opc1 = ifieldOPC(theInstr); 11856 UChar vD_addr = ifieldRegDS(theInstr); 11857 UChar vA_addr = ifieldRegA(theInstr); 11858 UChar vB_addr = ifieldRegB(theInstr); 11859 UChar flag_rC = ifieldBIT10(theInstr); 11860 UInt opc2 = IFIELD( theInstr, 0, 10 ); 11861 11862 IRTemp vA = newTemp(Ity_V128); 11863 IRTemp vB = newTemp(Ity_V128); 11864 IRTemp vD = newTemp(Ity_V128); 11865 assign( vA, getVReg(vA_addr)); 11866 assign( vB, getVReg(vB_addr)); 11867 11868 if (opc1 != 0x4) { 11869 vex_printf("dis_av_cmp(ppc)(instr)\n"); 11870 return False; 11871 } 11872 11873 switch (opc2) { 11874 case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160) 11875 DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 11876 vD_addr, vA_addr, vB_addr); 11877 assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) ); 11878 break; 11879 11880 case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161) 11881 DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 11882 vD_addr, vA_addr, vB_addr); 11883 assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) ); 11884 break; 11885 11886 case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162) 11887 DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 11888 vD_addr, vA_addr, vB_addr); 11889 assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) ); 11890 break; 11891 11892 case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168) 11893 DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 11894 vD_addr, vA_addr, vB_addr); 11895 assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) ); 11896 break; 11897 11898 case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169) 11899 DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 11900 vD_addr, vA_addr, vB_addr); 11901 assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) ); 11902 break; 11903 11904 case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170) 11905 DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 11906 vD_addr, vA_addr, vB_addr); 11907 assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) ); 11908 break; 11909 11910 case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165) 11911 DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 11912 vD_addr, vA_addr, vB_addr); 11913 assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) ); 11914 break; 11915 11916 case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166) 11917 DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 11918 vD_addr, vA_addr, vB_addr); 11919 assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) ); 11920 break; 11921 11922 case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167) 11923 DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 11924 vD_addr, vA_addr, vB_addr); 11925 assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) ); 11926 break; 11927 11928 default: 11929 vex_printf("dis_av_cmp(ppc)(opc2)\n"); 11930 return False; 11931 } 11932 11933 putVReg( vD_addr, mkexpr(vD) ); 11934 11935 if (flag_rC) { 11936 set_AV_CR6( mkexpr(vD), True ); 11937 } 11938 return True; 11939} 11940 11941/* 11942 AltiVec Multiply-Sum Instructions 11943*/ 11944static Bool dis_av_multarith ( UInt theInstr ) 11945{ 11946 /* VA-Form */ 11947 UChar opc1 = ifieldOPC(theInstr); 11948 UChar vD_addr = ifieldRegDS(theInstr); 11949 UChar vA_addr = ifieldRegA(theInstr); 11950 UChar vB_addr = ifieldRegB(theInstr); 11951 UChar vC_addr = ifieldRegC(theInstr); 11952 UChar opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 11953 11954 IRTemp vA = newTemp(Ity_V128); 11955 IRTemp vB = newTemp(Ity_V128); 11956 IRTemp vC = newTemp(Ity_V128); 11957 IRTemp zeros = newTemp(Ity_V128); 11958 IRTemp aLo = newTemp(Ity_V128); 11959 IRTemp bLo = newTemp(Ity_V128); 11960 IRTemp cLo = newTemp(Ity_V128); 11961 IRTemp zLo = newTemp(Ity_V128); 11962 IRTemp aHi = newTemp(Ity_V128); 11963 IRTemp bHi = newTemp(Ity_V128); 11964 IRTemp cHi = newTemp(Ity_V128); 11965 IRTemp zHi = newTemp(Ity_V128); 11966 IRTemp abEvn = newTemp(Ity_V128); 11967 IRTemp abOdd = newTemp(Ity_V128); 11968 IRTemp z3 = newTemp(Ity_I64); 11969 IRTemp z2 = newTemp(Ity_I64); 11970 IRTemp z1 = newTemp(Ity_I64); 11971 IRTemp z0 = newTemp(Ity_I64); 11972 IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0; 11973 IRTemp c3, c2, c1, c0; 11974 11975 ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID; 11976 c3 = c2 = c1 = c0 = IRTemp_INVALID; 11977 11978 assign( vA, getVReg(vA_addr)); 11979 assign( vB, getVReg(vB_addr)); 11980 assign( vC, getVReg(vC_addr)); 11981 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 11982 11983 if (opc1 != 0x4) { 11984 vex_printf("dis_av_multarith(ppc)(instr)\n"); 11985 return False; 11986 } 11987 11988 switch (opc2) { 11989 /* Multiply-Add */ 11990 case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185) 11991 IRTemp cSigns = newTemp(Ity_V128); 11992 DIP("vmhaddshs v%d,v%d,v%d,v%d\n", 11993 vD_addr, vA_addr, vB_addr, vC_addr); 11994 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC))); 11995 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 11996 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 11997 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 11998 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 11999 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 12000 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 12001 12002 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 12003 binop(Iop_SarN32x4, 12004 binop(Iop_MullEven16Sx8, 12005 mkexpr(aLo), mkexpr(bLo)), 12006 mkU8(15))) ); 12007 12008 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 12009 binop(Iop_SarN32x4, 12010 binop(Iop_MullEven16Sx8, 12011 mkexpr(aHi), mkexpr(bHi)), 12012 mkU8(15))) ); 12013 12014 putVReg( vD_addr, 12015 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 12016 break; 12017 } 12018 case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186) 12019 IRTemp zKonst = newTemp(Ity_V128); 12020 IRTemp cSigns = newTemp(Ity_V128); 12021 DIP("vmhraddshs v%d,v%d,v%d,v%d\n", 12022 vD_addr, vA_addr, vB_addr, vC_addr); 12023 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) ); 12024 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 12025 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 12026 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 12027 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 12028 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 12029 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 12030 12031 /* shifting our const avoids store/load version of Dup */ 12032 assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)), 12033 mkU8(14)) ); 12034 12035 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 12036 binop(Iop_SarN32x4, 12037 binop(Iop_Add32x4, mkexpr(zKonst), 12038 binop(Iop_MullEven16Sx8, 12039 mkexpr(aLo), mkexpr(bLo))), 12040 mkU8(15))) ); 12041 12042 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 12043 binop(Iop_SarN32x4, 12044 binop(Iop_Add32x4, mkexpr(zKonst), 12045 binop(Iop_MullEven16Sx8, 12046 mkexpr(aHi), mkexpr(bHi))), 12047 mkU8(15))) ); 12048 12049 putVReg( vD_addr, 12050 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 12051 break; 12052 } 12053 case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194) 12054 DIP("vmladduhm v%d,v%d,v%d,v%d\n", 12055 vD_addr, vA_addr, vB_addr, vC_addr); 12056 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 12057 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 12058 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC))); 12059 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 12060 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 12061 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC))); 12062 assign(zLo, binop(Iop_Add32x4, 12063 binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)), 12064 mkexpr(cLo)) ); 12065 assign(zHi, binop(Iop_Add32x4, 12066 binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)), 12067 mkexpr(cHi))); 12068 putVReg( vD_addr, 12069 binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) ); 12070 break; 12071 } 12072 12073 12074 /* Multiply-Sum */ 12075 case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204) 12076 IRTemp abEE, abEO, abOE, abOO; 12077 abEE = abEO = abOE = abOO = IRTemp_INVALID; 12078 DIP("vmsumubm v%d,v%d,v%d,v%d\n", 12079 vD_addr, vA_addr, vB_addr, vC_addr); 12080 12081 /* multiply vA,vB (unsigned, widening) */ 12082 assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 12083 assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) ); 12084 12085 /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */ 12086 expand16Ux8( mkexpr(abEvn), &abEE, &abEO ); 12087 expand16Ux8( mkexpr(abOdd), &abOE, &abOO ); 12088 12089 putVReg( vD_addr, 12090 binop(Iop_Add32x4, mkexpr(vC), 12091 binop(Iop_Add32x4, 12092 binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)), 12093 binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) ); 12094 break; 12095 } 12096 case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201) 12097 IRTemp aEvn, aOdd, bEvn, bOdd; 12098 IRTemp abEE = newTemp(Ity_V128); 12099 IRTemp abEO = newTemp(Ity_V128); 12100 IRTemp abOE = newTemp(Ity_V128); 12101 IRTemp abOO = newTemp(Ity_V128); 12102 aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID; 12103 DIP("vmsummbm v%d,v%d,v%d,v%d\n", 12104 vD_addr, vA_addr, vB_addr, vC_addr); 12105 12106 /* sign-extend vA, zero-extend vB, for mixed-sign multiply 12107 (separating out adjacent lanes to different vectors) */ 12108 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); 12109 expand8Ux16( mkexpr(vB), &bEvn, &bOdd ); 12110 12111 /* multiply vA, vB, again separating adjacent lanes */ 12112 assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) )); 12113 assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) ); 12114 assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) )); 12115 assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) ); 12116 12117 /* add results together, + vC */ 12118 putVReg( vD_addr, 12119 binop(Iop_QAdd32Sx4, mkexpr(vC), 12120 binop(Iop_QAdd32Sx4, 12121 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)), 12122 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) ); 12123 break; 12124 } 12125 case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205) 12126 DIP("vmsumuhm v%d,v%d,v%d,v%d\n", 12127 vD_addr, vA_addr, vB_addr, vC_addr); 12128 assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 12129 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 12130 putVReg( vD_addr, 12131 binop(Iop_Add32x4, mkexpr(vC), 12132 binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) ); 12133 break; 12134 } 12135 case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206) 12136 DIP("vmsumuhs v%d,v%d,v%d,v%d\n", 12137 vD_addr, vA_addr, vB_addr, vC_addr); 12138 /* widening multiply, separating lanes */ 12139 assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) )); 12140 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 12141 12142 /* break V128 to 4xI32's, zero-extending to I64's */ 12143 breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 12144 breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 12145 breakV128to4x64U( mkexpr(vC), &c3, &c2, &c1, &c0 ); 12146 12147 /* add lanes */ 12148 assign( z3, binop(Iop_Add64, mkexpr(c3), 12149 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 12150 assign( z2, binop(Iop_Add64, mkexpr(c2), 12151 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 12152 assign( z1, binop(Iop_Add64, mkexpr(c1), 12153 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 12154 assign( z0, binop(Iop_Add64, mkexpr(c0), 12155 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 12156 12157 /* saturate-narrow to 32bit, and combine to V128 */ 12158 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 12159 mkexpr(z1), mkexpr(z0)) ); 12160 12161 break; 12162 } 12163 case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202) 12164 DIP("vmsumshm v%d,v%d,v%d,v%d\n", 12165 vD_addr, vA_addr, vB_addr, vC_addr); 12166 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 12167 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 12168 putVReg( vD_addr, 12169 binop(Iop_Add32x4, mkexpr(vC), 12170 binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) ); 12171 break; 12172 } 12173 case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203) 12174 DIP("vmsumshs v%d,v%d,v%d,v%d\n", 12175 vD_addr, vA_addr, vB_addr, vC_addr); 12176 /* widening multiply, separating lanes */ 12177 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 12178 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 12179 12180 /* break V128 to 4xI32's, sign-extending to I64's */ 12181 breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 12182 breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 12183 breakV128to4x64S( mkexpr(vC), &c3, &c2, &c1, &c0 ); 12184 12185 /* add lanes */ 12186 assign( z3, binop(Iop_Add64, mkexpr(c3), 12187 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 12188 assign( z2, binop(Iop_Add64, mkexpr(c2), 12189 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 12190 assign( z1, binop(Iop_Add64, mkexpr(c1), 12191 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 12192 assign( z0, binop(Iop_Add64, mkexpr(c0), 12193 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 12194 12195 /* saturate-narrow to 32bit, and combine to V128 */ 12196 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 12197 mkexpr(z1), mkexpr(z0)) ); 12198 break; 12199 } 12200 default: 12201 vex_printf("dis_av_multarith(ppc)(opc2)\n"); 12202 return False; 12203 } 12204 return True; 12205} 12206 12207/* 12208 AltiVec Shift/Rotate Instructions 12209*/ 12210static Bool dis_av_shift ( UInt theInstr ) 12211{ 12212 /* VX-Form */ 12213 UChar opc1 = ifieldOPC(theInstr); 12214 UChar vD_addr = ifieldRegDS(theInstr); 12215 UChar vA_addr = ifieldRegA(theInstr); 12216 UChar vB_addr = ifieldRegB(theInstr); 12217 UInt opc2 = IFIELD( theInstr, 0, 11 ); 12218 12219 IRTemp vA = newTemp(Ity_V128); 12220 IRTemp vB = newTemp(Ity_V128); 12221 assign( vA, getVReg(vA_addr)); 12222 assign( vB, getVReg(vB_addr)); 12223 12224 if (opc1 != 0x4){ 12225 vex_printf("dis_av_shift(ppc)(instr)\n"); 12226 return False; 12227 } 12228 12229 switch (opc2) { 12230 /* Rotate */ 12231 case 0x004: // vrlb (Rotate Left Integer B, AV p234) 12232 DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12233 putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) ); 12234 break; 12235 12236 case 0x044: // vrlh (Rotate Left Integer HW, AV p235) 12237 DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12238 putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) ); 12239 break; 12240 12241 case 0x084: // vrlw (Rotate Left Integer W, AV p236) 12242 DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12243 putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) ); 12244 break; 12245 12246 12247 /* Shift Left */ 12248 case 0x104: // vslb (Shift Left Integer B, AV p240) 12249 DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12250 putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) ); 12251 break; 12252 12253 case 0x144: // vslh (Shift Left Integer HW, AV p242) 12254 DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12255 putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) ); 12256 break; 12257 12258 case 0x184: // vslw (Shift Left Integer W, AV p244) 12259 DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12260 putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) ); 12261 break; 12262 12263 case 0x1C4: { // vsl (Shift Left, AV p239) 12264 IRTemp sh = newTemp(Ity_I8); 12265 DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12266 assign( sh, binop(Iop_And8, mkU8(0x7), 12267 unop(Iop_32to8, 12268 unop(Iop_V128to32, mkexpr(vB)))) ); 12269 putVReg( vD_addr, 12270 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 12271 break; 12272 } 12273 case 0x40C: { // vslo (Shift Left by Octet, AV p243) 12274 IRTemp sh = newTemp(Ity_I8); 12275 DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12276 assign( sh, binop(Iop_And8, mkU8(0x78), 12277 unop(Iop_32to8, 12278 unop(Iop_V128to32, mkexpr(vB)))) ); 12279 putVReg( vD_addr, 12280 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 12281 break; 12282 } 12283 12284 12285 /* Shift Right */ 12286 case 0x204: // vsrb (Shift Right B, AV p256) 12287 DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12288 putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) ); 12289 break; 12290 12291 case 0x244: // vsrh (Shift Right HW, AV p257) 12292 DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12293 putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) ); 12294 break; 12295 12296 case 0x284: // vsrw (Shift Right W, AV p259) 12297 DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12298 putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) ); 12299 break; 12300 12301 case 0x2C4: { // vsr (Shift Right, AV p251) 12302 IRTemp sh = newTemp(Ity_I8); 12303 DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12304 assign( sh, binop(Iop_And8, mkU8(0x7), 12305 unop(Iop_32to8, 12306 unop(Iop_V128to32, mkexpr(vB)))) ); 12307 putVReg( vD_addr, 12308 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 12309 break; 12310 } 12311 case 0x304: // vsrab (Shift Right Alg B, AV p253) 12312 DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12313 putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) ); 12314 break; 12315 12316 case 0x344: // vsrah (Shift Right Alg HW, AV p254) 12317 DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12318 putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) ); 12319 break; 12320 12321 case 0x384: // vsraw (Shift Right Alg W, AV p255) 12322 DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12323 putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) ); 12324 break; 12325 12326 case 0x44C: { // vsro (Shift Right by Octet, AV p258) 12327 IRTemp sh = newTemp(Ity_I8); 12328 DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12329 assign( sh, binop(Iop_And8, mkU8(0x78), 12330 unop(Iop_32to8, 12331 unop(Iop_V128to32, mkexpr(vB)))) ); 12332 putVReg( vD_addr, 12333 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 12334 break; 12335 } 12336 12337 default: 12338 vex_printf("dis_av_shift(ppc)(opc2)\n"); 12339 return False; 12340 } 12341 return True; 12342} 12343 12344/* 12345 AltiVec Permute Instructions 12346*/ 12347static Bool dis_av_permute ( UInt theInstr ) 12348{ 12349 /* VA-Form, VX-Form */ 12350 UChar opc1 = ifieldOPC(theInstr); 12351 UChar vD_addr = ifieldRegDS(theInstr); 12352 UChar vA_addr = ifieldRegA(theInstr); 12353 UChar UIMM_5 = vA_addr; 12354 UChar vB_addr = ifieldRegB(theInstr); 12355 UChar vC_addr = ifieldRegC(theInstr); 12356 UChar b10 = ifieldBIT10(theInstr); 12357 UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) ); 12358 UInt opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 12359 12360 UChar SIMM_8 = extend_s_5to8(UIMM_5); 12361 12362 IRTemp vA = newTemp(Ity_V128); 12363 IRTemp vB = newTemp(Ity_V128); 12364 IRTemp vC = newTemp(Ity_V128); 12365 assign( vA, getVReg(vA_addr)); 12366 assign( vB, getVReg(vB_addr)); 12367 assign( vC, getVReg(vC_addr)); 12368 12369 if (opc1 != 0x4) { 12370 vex_printf("dis_av_permute(ppc)(instr)\n"); 12371 return False; 12372 } 12373 12374 switch (opc2) { 12375 case 0x2A: // vsel (Conditional Select, AV p238) 12376 DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr); 12377 /* vD = (vA & ~vC) | (vB & vC) */ 12378 putVReg( vD_addr, binop(Iop_OrV128, 12379 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 12380 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 12381 return True; 12382 12383 case 0x2B: { // vperm (Permute, AV p218) 12384 /* limited to two args for IR, so have to play games... */ 12385 IRTemp a_perm = newTemp(Ity_V128); 12386 IRTemp b_perm = newTemp(Ity_V128); 12387 IRTemp mask = newTemp(Ity_V128); 12388 IRTemp vC_andF = newTemp(Ity_V128); 12389 DIP("vperm v%d,v%d,v%d,v%d\n", 12390 vD_addr, vA_addr, vB_addr, vC_addr); 12391 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what 12392 IR specifies, and also to hide irrelevant bits from 12393 memcheck */ 12394 assign( vC_andF, 12395 binop(Iop_AndV128, mkexpr(vC), 12396 unop(Iop_Dup8x16, mkU8(0xF))) ); 12397 assign( a_perm, 12398 binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) ); 12399 assign( b_perm, 12400 binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) ); 12401 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0 12402 assign( mask, binop(Iop_SarN8x16, 12403 binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)), 12404 mkU8(7)) ); 12405 // dst = (a & ~mask) | (b & mask) 12406 putVReg( vD_addr, binop(Iop_OrV128, 12407 binop(Iop_AndV128, mkexpr(a_perm), 12408 unop(Iop_NotV128, mkexpr(mask))), 12409 binop(Iop_AndV128, mkexpr(b_perm), 12410 mkexpr(mask))) ); 12411 return True; 12412 } 12413 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241) 12414 if (b10 != 0) { 12415 vex_printf("dis_av_permute(ppc)(vsldoi)\n"); 12416 return False; 12417 } 12418 DIP("vsldoi v%d,v%d,v%d,%d\n", 12419 vD_addr, vA_addr, vB_addr, SHB_uimm4); 12420 if (SHB_uimm4 == 0) 12421 putVReg( vD_addr, mkexpr(vA) ); 12422 else 12423 putVReg( vD_addr, 12424 binop(Iop_OrV128, 12425 binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)), 12426 binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) ); 12427 return True; 12428 12429 default: 12430 break; // Fall through... 12431 } 12432 12433 opc2 = IFIELD( theInstr, 0, 11 ); 12434 switch (opc2) { 12435 12436 /* Merge */ 12437 case 0x00C: // vmrghb (Merge High B, AV p195) 12438 DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12439 putVReg( vD_addr, 12440 binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) ); 12441 break; 12442 12443 case 0x04C: // vmrghh (Merge High HW, AV p196) 12444 DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12445 putVReg( vD_addr, 12446 binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) ); 12447 break; 12448 12449 case 0x08C: // vmrghw (Merge High W, AV p197) 12450 DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12451 putVReg( vD_addr, 12452 binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) ); 12453 break; 12454 12455 case 0x10C: // vmrglb (Merge Low B, AV p198) 12456 DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12457 putVReg( vD_addr, 12458 binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) ); 12459 break; 12460 12461 case 0x14C: // vmrglh (Merge Low HW, AV p199) 12462 DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12463 putVReg( vD_addr, 12464 binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) ); 12465 break; 12466 12467 case 0x18C: // vmrglw (Merge Low W, AV p200) 12468 DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12469 putVReg( vD_addr, 12470 binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) ); 12471 break; 12472 12473 12474 /* Splat */ 12475 case 0x20C: { // vspltb (Splat Byte, AV p245) 12476 /* vD = Dup8x16( vB[UIMM_5] ) */ 12477 UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8; 12478 DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 12479 putVReg( vD_addr, unop(Iop_Dup8x16, 12480 unop(Iop_32to8, unop(Iop_V128to32, 12481 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 12482 break; 12483 } 12484 case 0x24C: { // vsplth (Splat Half Word, AV p246) 12485 UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16; 12486 DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 12487 putVReg( vD_addr, unop(Iop_Dup16x8, 12488 unop(Iop_32to16, unop(Iop_V128to32, 12489 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 12490 break; 12491 } 12492 case 0x28C: { // vspltw (Splat Word, AV p250) 12493 /* vD = Dup32x4( vB[UIMM_5] ) */ 12494 UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32; 12495 DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 12496 putVReg( vD_addr, unop(Iop_Dup32x4, 12497 unop(Iop_V128to32, 12498 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) ); 12499 break; 12500 } 12501 case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247) 12502 DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8); 12503 putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) ); 12504 break; 12505 12506 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248) 12507 DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8); 12508 putVReg( vD_addr, 12509 unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) ); 12510 break; 12511 12512 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249) 12513 DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8); 12514 putVReg( vD_addr, 12515 unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) ); 12516 break; 12517 12518 default: 12519 vex_printf("dis_av_permute(ppc)(opc2)\n"); 12520 return False; 12521 } 12522 return True; 12523} 12524 12525/* 12526 AltiVec Pack/Unpack Instructions 12527*/ 12528static Bool dis_av_pack ( UInt theInstr ) 12529{ 12530 /* VX-Form */ 12531 UChar opc1 = ifieldOPC(theInstr); 12532 UChar vD_addr = ifieldRegDS(theInstr); 12533 UChar vA_addr = ifieldRegA(theInstr); 12534 UChar vB_addr = ifieldRegB(theInstr); 12535 UInt opc2 = IFIELD( theInstr, 0, 11 ); 12536 12537 IRTemp signs = IRTemp_INVALID; 12538 IRTemp zeros = IRTemp_INVALID; 12539 IRTemp vA = newTemp(Ity_V128); 12540 IRTemp vB = newTemp(Ity_V128); 12541 assign( vA, getVReg(vA_addr)); 12542 assign( vB, getVReg(vB_addr)); 12543 12544 if (opc1 != 0x4) { 12545 vex_printf("dis_av_pack(ppc)(instr)\n"); 12546 return False; 12547 } 12548 12549 switch (opc2) { 12550 /* Packing */ 12551 case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224) 12552 DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12553 putVReg( vD_addr, 12554 binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) ); 12555 return True; 12556 12557 case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226) 12558 DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12559 putVReg( vD_addr, 12560 binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) ); 12561 return True; 12562 12563 case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225) 12564 DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12565 putVReg( vD_addr, 12566 binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) ); 12567 // TODO: set VSCR[SAT] 12568 return True; 12569 12570 case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227) 12571 DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12572 putVReg( vD_addr, 12573 binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) ); 12574 // TODO: set VSCR[SAT] 12575 return True; 12576 12577 case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221) 12578 // This insn does a signed->unsigned saturating conversion. 12579 // Conversion done here, then uses unsigned->unsigned vpk insn: 12580 // => UnsignedSaturatingNarrow( x & ~ (x >>s 15) ) 12581 IRTemp vA_tmp = newTemp(Ity_V128); 12582 IRTemp vB_tmp = newTemp(Ity_V128); 12583 DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12584 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 12585 unop(Iop_NotV128, 12586 binop(Iop_SarN16x8, 12587 mkexpr(vA), mkU8(15)))) ); 12588 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 12589 unop(Iop_NotV128, 12590 binop(Iop_SarN16x8, 12591 mkexpr(vB), mkU8(15)))) ); 12592 putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16, 12593 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 12594 // TODO: set VSCR[SAT] 12595 return True; 12596 } 12597 case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223) 12598 // This insn does a signed->unsigned saturating conversion. 12599 // Conversion done here, then uses unsigned->unsigned vpk insn: 12600 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) ) 12601 IRTemp vA_tmp = newTemp(Ity_V128); 12602 IRTemp vB_tmp = newTemp(Ity_V128); 12603 DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12604 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 12605 unop(Iop_NotV128, 12606 binop(Iop_SarN32x4, 12607 mkexpr(vA), mkU8(31)))) ); 12608 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 12609 unop(Iop_NotV128, 12610 binop(Iop_SarN32x4, 12611 mkexpr(vB), mkU8(31)))) ); 12612 putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8, 12613 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 12614 // TODO: set VSCR[SAT] 12615 return True; 12616 } 12617 case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220) 12618 DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12619 putVReg( vD_addr, 12620 binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) ); 12621 // TODO: set VSCR[SAT] 12622 return True; 12623 12624 case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222) 12625 DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12626 putVReg( vD_addr, 12627 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) ); 12628 // TODO: set VSCR[SAT] 12629 return True; 12630 12631 case 0x30E: { // vpkpx (Pack Pixel, AV p219) 12632 /* CAB: Worth a new primop? */ 12633 /* Using shifts to compact pixel elements, then packing them */ 12634 IRTemp a1 = newTemp(Ity_V128); 12635 IRTemp a2 = newTemp(Ity_V128); 12636 IRTemp a3 = newTemp(Ity_V128); 12637 IRTemp a_tmp = newTemp(Ity_V128); 12638 IRTemp b1 = newTemp(Ity_V128); 12639 IRTemp b2 = newTemp(Ity_V128); 12640 IRTemp b3 = newTemp(Ity_V128); 12641 IRTemp b_tmp = newTemp(Ity_V128); 12642 DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12643 assign( a1, binop(Iop_ShlN16x8, 12644 binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)), 12645 mkU8(10)) ); 12646 assign( a2, binop(Iop_ShlN16x8, 12647 binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)), 12648 mkU8(5)) ); 12649 assign( a3, binop(Iop_ShrN16x8, 12650 binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)), 12651 mkU8(11)) ); 12652 assign( a_tmp, binop(Iop_OrV128, mkexpr(a1), 12653 binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) ); 12654 12655 assign( b1, binop(Iop_ShlN16x8, 12656 binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)), 12657 mkU8(10)) ); 12658 assign( b2, binop(Iop_ShlN16x8, 12659 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)), 12660 mkU8(5)) ); 12661 assign( b3, binop(Iop_ShrN16x8, 12662 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)), 12663 mkU8(11)) ); 12664 assign( b_tmp, binop(Iop_OrV128, mkexpr(b1), 12665 binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) ); 12666 12667 putVReg( vD_addr, binop(Iop_NarrowBin32to16x8, 12668 mkexpr(a_tmp), mkexpr(b_tmp)) ); 12669 return True; 12670 } 12671 12672 default: 12673 break; // Fall through... 12674 } 12675 12676 12677 if (vA_addr != 0) { 12678 vex_printf("dis_av_pack(ppc)(vA_addr)\n"); 12679 return False; 12680 } 12681 12682 signs = newTemp(Ity_V128); 12683 zeros = newTemp(Ity_V128); 12684 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 12685 12686 switch (opc2) { 12687 /* Unpacking */ 12688 case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277) 12689 DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr); 12690 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 12691 putVReg( vD_addr, 12692 binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) ); 12693 break; 12694 } 12695 case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278) 12696 DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr); 12697 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 12698 putVReg( vD_addr, 12699 binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) ); 12700 break; 12701 } 12702 case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280) 12703 DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr); 12704 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 12705 putVReg( vD_addr, 12706 binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) ); 12707 break; 12708 } 12709 case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281) 12710 DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr); 12711 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 12712 putVReg( vD_addr, 12713 binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) ); 12714 break; 12715 } 12716 case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276) 12717 /* CAB: Worth a new primop? */ 12718 /* Using shifts to isolate pixel elements, then expanding them */ 12719 IRTemp z0 = newTemp(Ity_V128); 12720 IRTemp z1 = newTemp(Ity_V128); 12721 IRTemp z01 = newTemp(Ity_V128); 12722 IRTemp z2 = newTemp(Ity_V128); 12723 IRTemp z3 = newTemp(Ity_V128); 12724 IRTemp z23 = newTemp(Ity_V128); 12725 DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr); 12726 assign( z0, binop(Iop_ShlN16x8, 12727 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 12728 mkU8(8)) ); 12729 assign( z1, binop(Iop_ShrN16x8, 12730 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 12731 mkU8(11)) ); 12732 assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 12733 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 12734 assign( z2, binop(Iop_ShrN16x8, 12735 binop(Iop_ShlN16x8, 12736 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 12737 mkU8(11)), 12738 mkU8(3)) ); 12739 assign( z3, binop(Iop_ShrN16x8, 12740 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 12741 mkU8(11)) ); 12742 assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 12743 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 12744 putVReg( vD_addr, 12745 binop(Iop_OrV128, 12746 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 12747 mkexpr(z23)) ); 12748 break; 12749 } 12750 case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279) 12751 /* identical to vupkhpx, except interleaving LO */ 12752 IRTemp z0 = newTemp(Ity_V128); 12753 IRTemp z1 = newTemp(Ity_V128); 12754 IRTemp z01 = newTemp(Ity_V128); 12755 IRTemp z2 = newTemp(Ity_V128); 12756 IRTemp z3 = newTemp(Ity_V128); 12757 IRTemp z23 = newTemp(Ity_V128); 12758 DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr); 12759 assign( z0, binop(Iop_ShlN16x8, 12760 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 12761 mkU8(8)) ); 12762 assign( z1, binop(Iop_ShrN16x8, 12763 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 12764 mkU8(11)) ); 12765 assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 12766 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 12767 assign( z2, binop(Iop_ShrN16x8, 12768 binop(Iop_ShlN16x8, 12769 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 12770 mkU8(11)), 12771 mkU8(3)) ); 12772 assign( z3, binop(Iop_ShrN16x8, 12773 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 12774 mkU8(11)) ); 12775 assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 12776 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 12777 putVReg( vD_addr, 12778 binop(Iop_OrV128, 12779 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 12780 mkexpr(z23)) ); 12781 break; 12782 } 12783 default: 12784 vex_printf("dis_av_pack(ppc)(opc2)\n"); 12785 return False; 12786 } 12787 return True; 12788} 12789 12790 12791/* 12792 AltiVec Floating Point Arithmetic Instructions 12793*/ 12794static Bool dis_av_fp_arith ( UInt theInstr ) 12795{ 12796 /* VA-Form */ 12797 UChar opc1 = ifieldOPC(theInstr); 12798 UChar vD_addr = ifieldRegDS(theInstr); 12799 UChar vA_addr = ifieldRegA(theInstr); 12800 UChar vB_addr = ifieldRegB(theInstr); 12801 UChar vC_addr = ifieldRegC(theInstr); 12802 UInt opc2=0; 12803 12804 IRTemp vA = newTemp(Ity_V128); 12805 IRTemp vB = newTemp(Ity_V128); 12806 IRTemp vC = newTemp(Ity_V128); 12807 assign( vA, getVReg(vA_addr)); 12808 assign( vB, getVReg(vB_addr)); 12809 assign( vC, getVReg(vC_addr)); 12810 12811 if (opc1 != 0x4) { 12812 vex_printf("dis_av_fp_arith(ppc)(instr)\n"); 12813 return False; 12814 } 12815 12816 opc2 = IFIELD( theInstr, 0, 6 ); 12817 switch (opc2) { 12818 case 0x2E: // vmaddfp (Multiply Add FP, AV p177) 12819 DIP("vmaddfp v%d,v%d,v%d,v%d\n", 12820 vD_addr, vA_addr, vC_addr, vB_addr); 12821 putVReg( vD_addr, 12822 binop(Iop_Add32Fx4, mkexpr(vB), 12823 binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) ); 12824 return True; 12825 12826 case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215) 12827 DIP("vnmsubfp v%d,v%d,v%d,v%d\n", 12828 vD_addr, vA_addr, vC_addr, vB_addr); 12829 putVReg( vD_addr, 12830 binop(Iop_Sub32Fx4, 12831 mkexpr(vB), 12832 binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) ); 12833 return True; 12834 } 12835 12836 default: 12837 break; // Fall through... 12838 } 12839 12840 opc2 = IFIELD( theInstr, 0, 11 ); 12841 switch (opc2) { 12842 case 0x00A: // vaddfp (Add FP, AV p137) 12843 DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12844 putVReg( vD_addr, binop(Iop_Add32Fx4, mkexpr(vA), mkexpr(vB)) ); 12845 return True; 12846 12847 case 0x04A: // vsubfp (Subtract FP, AV p261) 12848 DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12849 putVReg( vD_addr, binop(Iop_Sub32Fx4, mkexpr(vA), mkexpr(vB)) ); 12850 return True; 12851 12852 case 0x40A: // vmaxfp (Maximum FP, AV p178) 12853 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12854 putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) ); 12855 return True; 12856 12857 case 0x44A: // vminfp (Minimum FP, AV p187) 12858 DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 12859 putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) ); 12860 return True; 12861 12862 default: 12863 break; // Fall through... 12864 } 12865 12866 12867 if (vA_addr != 0) { 12868 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n"); 12869 return False; 12870 } 12871 12872 switch (opc2) { 12873 case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228) 12874 DIP("vrefp v%d,v%d\n", vD_addr, vB_addr); 12875 putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) ); 12876 return True; 12877 12878 case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237) 12879 DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr); 12880 putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) ); 12881 return True; 12882 12883 case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173) 12884 DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr); 12885 DIP(" => not implemented\n"); 12886 return False; 12887 12888 case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175) 12889 DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr); 12890 DIP(" => not implemented\n"); 12891 return False; 12892 12893 default: 12894 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2); 12895 return False; 12896 } 12897 return True; 12898} 12899 12900/* 12901 AltiVec Floating Point Compare Instructions 12902*/ 12903static Bool dis_av_fp_cmp ( UInt theInstr ) 12904{ 12905 /* VXR-Form */ 12906 UChar opc1 = ifieldOPC(theInstr); 12907 UChar vD_addr = ifieldRegDS(theInstr); 12908 UChar vA_addr = ifieldRegA(theInstr); 12909 UChar vB_addr = ifieldRegB(theInstr); 12910 UChar flag_rC = ifieldBIT10(theInstr); 12911 UInt opc2 = IFIELD( theInstr, 0, 10 ); 12912 12913 Bool cmp_bounds = False; 12914 12915 IRTemp vA = newTemp(Ity_V128); 12916 IRTemp vB = newTemp(Ity_V128); 12917 IRTemp vD = newTemp(Ity_V128); 12918 assign( vA, getVReg(vA_addr)); 12919 assign( vB, getVReg(vB_addr)); 12920 12921 if (opc1 != 0x4) { 12922 vex_printf("dis_av_fp_cmp(ppc)(instr)\n"); 12923 return False; 12924 } 12925 12926 switch (opc2) { 12927 case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159) 12928 DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 12929 vD_addr, vA_addr, vB_addr); 12930 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 12931 break; 12932 12933 case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163) 12934 DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 12935 vD_addr, vA_addr, vB_addr); 12936 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 12937 break; 12938 12939 case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164) 12940 DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 12941 vD_addr, vA_addr, vB_addr); 12942 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 12943 break; 12944 12945 case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157) 12946 IRTemp gt = newTemp(Ity_V128); 12947 IRTemp lt = newTemp(Ity_V128); 12948 IRTemp zeros = newTemp(Ity_V128); 12949 DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 12950 vD_addr, vA_addr, vB_addr); 12951 cmp_bounds = True; 12952 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 12953 12954 /* Note: making use of fact that the ppc backend for compare insns 12955 return zero'd lanes if either of the corresponding arg lanes is 12956 a nan. 12957 12958 Perhaps better to have an irop Iop_isNan32Fx4, but then we'd 12959 need this for the other compares too (vcmpeqfp etc)... 12960 Better still, tighten down the spec for compare irops. 12961 */ 12962 assign( gt, unop(Iop_NotV128, 12963 binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) ); 12964 assign( lt, unop(Iop_NotV128, 12965 binop(Iop_CmpGE32Fx4, mkexpr(vA), 12966 binop(Iop_Sub32Fx4, mkexpr(zeros), 12967 mkexpr(vB)))) ); 12968 12969 // finally, just shift gt,lt to correct position 12970 assign( vD, binop(Iop_ShlN32x4, 12971 binop(Iop_OrV128, 12972 binop(Iop_AndV128, mkexpr(gt), 12973 unop(Iop_Dup32x4, mkU32(0x2))), 12974 binop(Iop_AndV128, mkexpr(lt), 12975 unop(Iop_Dup32x4, mkU32(0x1)))), 12976 mkU8(30)) ); 12977 break; 12978 } 12979 12980 default: 12981 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n"); 12982 return False; 12983 } 12984 12985 putVReg( vD_addr, mkexpr(vD) ); 12986 12987 if (flag_rC) { 12988 set_AV_CR6( mkexpr(vD), !cmp_bounds ); 12989 } 12990 return True; 12991} 12992 12993/* 12994 AltiVec Floating Point Convert/Round Instructions 12995*/ 12996static Bool dis_av_fp_convert ( UInt theInstr ) 12997{ 12998 /* VX-Form */ 12999 UChar opc1 = ifieldOPC(theInstr); 13000 UChar vD_addr = ifieldRegDS(theInstr); 13001 UChar UIMM_5 = ifieldRegA(theInstr); 13002 UChar vB_addr = ifieldRegB(theInstr); 13003 UInt opc2 = IFIELD( theInstr, 0, 11 ); 13004 13005 IRTemp vB = newTemp(Ity_V128); 13006 IRTemp vScale = newTemp(Ity_V128); 13007 IRTemp vInvScale = newTemp(Ity_V128); 13008 13009 float scale, inv_scale; 13010 13011 assign( vB, getVReg(vB_addr)); 13012 13013 /* scale = 2^UIMM, cast to float, reinterpreted as uint */ 13014 scale = (float)( (unsigned int) 1<<UIMM_5 ); 13015 assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) ); 13016 inv_scale = 1/scale; 13017 assign( vInvScale, 13018 unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) ); 13019 13020 if (opc1 != 0x4) { 13021 vex_printf("dis_av_fp_convert(ppc)(instr)\n"); 13022 return False; 13023 } 13024 13025 switch (opc2) { 13026 case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156) 13027 DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 13028 putVReg( vD_addr, binop(Iop_Mul32Fx4, 13029 unop(Iop_I32UtoFx4, mkexpr(vB)), 13030 mkexpr(vInvScale)) ); 13031 return True; 13032 13033 case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155) 13034 DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 13035 13036 putVReg( vD_addr, binop(Iop_Mul32Fx4, 13037 unop(Iop_I32StoFx4, mkexpr(vB)), 13038 mkexpr(vInvScale)) ); 13039 return True; 13040 13041 case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172) 13042 DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 13043 putVReg( vD_addr, 13044 unop(Iop_QFtoI32Ux4_RZ, 13045 binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) ); 13046 return True; 13047 13048 case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171) 13049 DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 13050 putVReg( vD_addr, 13051 unop(Iop_QFtoI32Sx4_RZ, 13052 binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) ); 13053 return True; 13054 13055 default: 13056 break; // Fall through... 13057 } 13058 13059 if (UIMM_5 != 0) { 13060 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n"); 13061 return False; 13062 } 13063 13064 switch (opc2) { 13065 case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231) 13066 DIP("vrfin v%d,v%d\n", vD_addr, vB_addr); 13067 putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) ); 13068 break; 13069 13070 case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233) 13071 DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr); 13072 putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) ); 13073 break; 13074 13075 case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232) 13076 DIP("vrfip v%d,v%d\n", vD_addr, vB_addr); 13077 putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) ); 13078 break; 13079 13080 case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230) 13081 DIP("vrfim v%d,v%d\n", vD_addr, vB_addr); 13082 putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) ); 13083 break; 13084 13085 default: 13086 vex_printf("dis_av_fp_convert(ppc)(opc2)\n"); 13087 return False; 13088 } 13089 return True; 13090} 13091 13092 13093/* The 0x3C primary opcode (VSX category) uses several different forms of 13094 * extended opcodes: 13095 * o XX2-form: 13096 * - [10:2] (IBM notation [21:29]) 13097 * o XX3-form variants: 13098 * - variant 1: [10:3] (IBM notation [21:28]) 13099 * - variant 2: [9:3] (IBM notation [22:28]) 13100 * - variant 3: [7:3] (IBM notation [24:28]) 13101 * o XX-4 form: 13102 * - [10:6] (IBM notation [21:25]) 13103 * 13104 * The XX2-form needs bit 0 masked from the standard extended opcode 13105 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked; 13106 * and the XX4-form needs bits 0, 1, and 2 masked. Additionally, the 13107 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the 13108 * front end since their encoding does not begin at bit 21 like the standard 13109 * format. 13110 * 13111 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the 13112 * secondary opcode for such VSX instructions. 13113 * 13114*/ 13115 13116 13117struct vsx_insn { 13118 UInt opcode; 13119 Char * name; 13120}; 13121 13122// ATTENTION: Keep this array sorted on the opcocde!!! 13123static struct vsx_insn vsx_all[] = { 13124 { 0x8, "xxsldwi" }, 13125 { 0x18, "xxsel" }, 13126 { 0x28, "xxpermdi" }, 13127 { 0x48, "xxmrghw" }, 13128 { 0x80, "xsadddp" }, 13129 { 0x84, "xsmaddadp" }, 13130 { 0x8c, "xscmpudp" }, 13131 { 0x90, "xscvdpuxws" }, 13132 { 0x92, "xsrdpi" }, 13133 { 0x94, "xsrsqrtedp" }, 13134 { 0x96, "xssqrtdp" }, 13135 { 0xa0, "xssubdp" }, 13136 { 0xa4, "xsmaddmdp" }, 13137 { 0xac, "xscmpodp" }, 13138 { 0xb0, "xscvdpsxws" }, 13139 { 0xb2, "xsrdpiz" }, 13140 { 0xb4, "xsredp" }, 13141 { 0xc0, "xsmuldp" }, 13142 { 0xc4, "xsmsubadp" }, 13143 { 0xc8, "xxmrglw" }, 13144 { 0xd2, "xsrdpip" }, 13145 { 0xd4, "xstsqrtdp" }, 13146 { 0xd6, "xsrdpic" }, 13147 { 0xe0, "xsdivdp" }, 13148 { 0xe4, "xsmsubmdp" }, 13149 { 0xf2, "xsrdpim" }, 13150 { 0xf4, "xstdivdp" }, 13151 { 0x100, "xvaddsp" }, 13152 { 0x104, "xvmaddasp" }, 13153 { 0x10c, "xvcmpeqsp" }, 13154 { 0x110, "xvcvspuxws" }, 13155 { 0x112, "xvrspi" }, 13156 { 0x114, "xvrsqrtesp" }, 13157 { 0x116, "xvsqrtsp" }, 13158 { 0x120, "xvsubsp" }, 13159 { 0x124, "xvmaddmsp" }, 13160 { 0x12c, "xvcmpgtsp" }, 13161 { 0x130, "xvcvspsxws" }, 13162 { 0x132, "xvrspiz" }, 13163 { 0x134, "xvresp" }, 13164 { 0x140, "xvmulsp" }, 13165 { 0x144, "xvmsubasp" }, 13166 { 0x148, "xxspltw" }, 13167 { 0x14c, "xvcmpgesp" }, 13168 { 0x150, "xvcvuxwsp" }, 13169 { 0x152, "xvrspip" }, 13170 { 0x154, "xvtsqrtsp" }, 13171 { 0x156, "xvrspic" }, 13172 { 0x160, "xvdivsp" }, 13173 { 0x164, "xvmsubmsp" }, 13174 { 0x170, "xvcvsxwsp" }, 13175 { 0x172, "xvrspim" }, 13176 { 0x174, "xvtdivsp" }, 13177 { 0x180, "xvadddp" }, 13178 { 0x184, "xvmaddadp" }, 13179 { 0x18c, "xvcmpeqdp" }, 13180 { 0x190, "xvcvdpuxws" }, 13181 { 0x192, "xvrdpi" }, 13182 { 0x194, "xvrsqrtedp" }, 13183 { 0x196, "xvsqrtdp" }, 13184 { 0x1a0, "xvsubdp" }, 13185 { 0x1a4, "xvmaddmdp" }, 13186 { 0x1ac, "xvcmpgtdp" }, 13187 { 0x1b0, "xvcvdpsxws" }, 13188 { 0x1b2, "xvrdpiz" }, 13189 { 0x1b4, "xvredp" }, 13190 { 0x1c0, "xvmuldp" }, 13191 { 0x1c4, "xvmsubadp" }, 13192 { 0x1cc, "xvcmpgedp" }, 13193 { 0x1d0, "xvcvuxwdp" }, 13194 { 0x1d2, "xvrdpip" }, 13195 { 0x1d4, "xvtsqrtdp" }, 13196 { 0x1d6, "xvrdpic" }, 13197 { 0x1e0, "xvdivdp" }, 13198 { 0x1e4, "xvmsubmdp" }, 13199 { 0x1f0, "xvcvsxwdp" }, 13200 { 0x1f2, "xvrdpim" }, 13201 { 0x1f4, "xvtdivdp" }, 13202 { 0x208, "xxland" }, 13203 { 0x212, "xscvdpsp" }, 13204 { 0x228, "xxlandc" }, 13205 { 0x248 , "xxlor" }, 13206 { 0x268, "xxlxor" }, 13207 { 0x280, "xsmaxdp" }, 13208 { 0x284, "xsnmaddadp" }, 13209 { 0x288, "xxlnor" }, 13210 { 0x290, "xscvdpuxds" }, 13211 { 0x292, "xscvspdp" }, 13212 { 0x2a0, "xsmindp" }, 13213 { 0x2a4, "xsnmaddmdp" }, 13214 { 0x2b0, "xscvdpsxds" }, 13215 { 0x2b2, "xsabsdp" }, 13216 { 0x2c0, "xscpsgndp" }, 13217 { 0x2c4, "xsnmsubadp" }, 13218 { 0x2d0, "xscvuxddp" }, 13219 { 0x2d2, "xsnabsdp" }, 13220 { 0x2e4, "xsnmsubmdp" }, 13221 { 0x2f0, "xscvsxddp" }, 13222 { 0x2f2, "xsnegdp" }, 13223 { 0x300, "xvmaxsp" }, 13224 { 0x304, "xvnmaddasp" }, 13225 { 0x30c, "xvcmpeqsp." }, 13226 { 0x310, "xvcvspuxds" }, 13227 { 0x312, "xvcvdpsp" }, 13228 { 0x320, "xvminsp" }, 13229 { 0x324, "xvnmaddmsp" }, 13230 { 0x32c, "xvcmpgtsp." }, 13231 { 0x330, "xvcvspsxds" }, 13232 { 0x332, "xvabssp" }, 13233 { 0x340, "xvcpsgnsp" }, 13234 { 0x344, "xvnmsubasp" }, 13235 { 0x34c, "xvcmpgesp." }, 13236 { 0x350, "xvcvuxdsp" }, 13237 { 0x352, "xvnabssp" }, 13238 { 0x364, "xvnmsubmsp" }, 13239 { 0x370, "xvcvsxdsp" }, 13240 { 0x372, "xvnegsp" }, 13241 { 0x380, "xvmaxdp" }, 13242 { 0x384, "xvnmaddadp" }, 13243 { 0x38c, "xvcmpeqdp." }, 13244 { 0x390, "xvcvdpuxds" }, 13245 { 0x392, "xvcvspdp" }, 13246 { 0x3a0, "xvmindp" }, 13247 { 0x3a4, "xvnmaddmdp" }, 13248 { 0x3ac, "xvcmpgtdp." }, 13249 { 0x3b0, "xvcvdpsxds" }, 13250 { 0x3b2, "xvabsdp" }, 13251 { 0x3c0, "xvcpsgndp" }, 13252 { 0x3c4, "xvnmsubadp" }, 13253 { 0x3cc, "xvcmpgedp." }, 13254 { 0x3d0, "xvcvuxddp" }, 13255 { 0x3d2, "xvnabsdp" }, 13256 { 0x3e4, "xvnmsubmdp" }, 13257 { 0x3f0, "xvcvsxddp" }, 13258 { 0x3f2, "xvnegdp" } 13259}; 13260#define VSX_ALL_LEN 135 13261 13262// ATTENTION: This search function assumes vsx_all array is sorted. 13263static Int findVSXextOpCode(UInt opcode) 13264{ 13265 Int low, mid, high; 13266 low = 0; 13267 high = VSX_ALL_LEN - 1; 13268 while (low <= high) { 13269 mid = (low + high)/2; 13270 if (opcode < vsx_all[mid].opcode) 13271 high = mid - 1; 13272 else if (opcode > vsx_all[mid].opcode) 13273 low = mid + 1; 13274 else 13275 return mid; 13276 } 13277 return -1; 13278} 13279 13280 13281/* The full 10-bit extended opcode retrieved via ifieldOPClo10 is 13282 * passed, and we then try to match it up with one of the VSX forms 13283 * below. 13284 */ 13285static UInt get_VSX60_opc2(UInt opc2_full) 13286{ 13287#define XX2_MASK 0x000003FE 13288#define XX3_1_MASK 0x000003FC 13289#define XX3_2_MASK 0x000001FC 13290#define XX3_3_MASK 0x0000007C 13291#define XX4_MASK 0x00000018 13292 Int ret; 13293 UInt vsxExtOpcode = 0; 13294 13295 if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0) 13296 vsxExtOpcode = vsx_all[ret].opcode; 13297 else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0) 13298 vsxExtOpcode = vsx_all[ret].opcode; 13299 else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0) 13300 vsxExtOpcode = vsx_all[ret].opcode; 13301 else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0) 13302 vsxExtOpcode = vsx_all[ret].opcode; 13303 else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0) 13304 vsxExtOpcode = vsx_all[ret].opcode; 13305 13306 return vsxExtOpcode; 13307} 13308 13309/*------------------------------------------------------------*/ 13310/*--- Disassemble a single instruction ---*/ 13311/*------------------------------------------------------------*/ 13312 13313/* Disassemble a single instruction into IR. The instruction 13314 is located in host memory at &guest_code[delta]. */ 13315 13316static 13317DisResult disInstr_PPC_WRK ( 13318 Bool put_IP, 13319 Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ), 13320 Bool resteerCisOk, 13321 void* callback_opaque, 13322 Long delta64, 13323 VexArchInfo* archinfo, 13324 VexAbiInfo* abiinfo 13325 ) 13326{ 13327 UChar opc1; 13328 UInt opc2; 13329 DisResult dres; 13330 UInt theInstr; 13331 IRType ty = mode64 ? Ity_I64 : Ity_I32; 13332 Bool allow_F = False; 13333 Bool allow_V = False; 13334 Bool allow_FX = False; 13335 Bool allow_GX = False; 13336 Bool allow_VX = False; // Equates to "supports Power ISA 2.06 13337 UInt hwcaps = archinfo->hwcaps; 13338 Long delta; 13339 13340 /* What insn variants are we supporting today? */ 13341 if (mode64) { 13342 allow_F = True; 13343 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC64_V)); 13344 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX)); 13345 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX)); 13346 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX)); 13347 } else { 13348 allow_F = (0 != (hwcaps & VEX_HWCAPS_PPC32_F)); 13349 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC32_V)); 13350 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX)); 13351 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX)); 13352 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX)); 13353 } 13354 13355 /* The running delta */ 13356 delta = (Long)mkSzAddr(ty, (ULong)delta64); 13357 13358 /* Set result defaults. */ 13359 dres.whatNext = Dis_Continue; 13360 dres.len = 0; 13361 dres.continueAt = 0; 13362 13363 /* At least this is simple on PPC32: insns are all 4 bytes long, and 13364 4-aligned. So just fish the whole thing out of memory right now 13365 and have done. */ 13366 theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) ); 13367 13368 if (0) vex_printf("insn: 0x%x\n", theInstr); 13369 13370 DIP("\t0x%llx: ", (ULong)guest_CIA_curr_instr); 13371 13372 /* We may be asked to update the guest CIA before going further. */ 13373 if (put_IP) 13374 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) ); 13375 13376 /* Spot "Special" instructions (see comment at top of file). */ 13377 { 13378 UChar* code = (UChar*)(guest_code + delta); 13379 /* Spot the 16-byte preamble: 13380 32-bit mode: 13381 54001800 rlwinm 0,0,3,0,0 13382 54006800 rlwinm 0,0,13,0,0 13383 5400E800 rlwinm 0,0,29,0,0 13384 54009800 rlwinm 0,0,19,0,0 13385 64-bit mode: 13386 78001800 rotldi 0,0,3 13387 78006800 rotldi 0,0,13 13388 7800E802 rotldi 0,0,61 13389 78009802 rotldi 0,0,51 13390 */ 13391 UInt word1 = mode64 ? 0x78001800 : 0x54001800; 13392 UInt word2 = mode64 ? 0x78006800 : 0x54006800; 13393 UInt word3 = mode64 ? 0x7800E802 : 0x5400E800; 13394 UInt word4 = mode64 ? 0x78009802 : 0x54009800; 13395 if (getUIntBigendianly(code+ 0) == word1 && 13396 getUIntBigendianly(code+ 4) == word2 && 13397 getUIntBigendianly(code+ 8) == word3 && 13398 getUIntBigendianly(code+12) == word4) { 13399 /* Got a "Special" instruction preamble. Which one is it? */ 13400 if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) { 13401 /* %R3 = client_request ( %R4 ) */ 13402 DIP("r3 = client_request ( %%r4 )\n"); 13403 delta += 20; 13404 irsb->next = mkSzImm( ty, guest_CIA_bbstart + delta ); 13405 irsb->jumpkind = Ijk_ClientReq; 13406 dres.whatNext = Dis_StopHere; 13407 goto decode_success; 13408 } 13409 else 13410 if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) { 13411 /* %R3 = guest_NRADDR */ 13412 DIP("r3 = guest_NRADDR\n"); 13413 delta += 20; 13414 dres.len = 20; 13415 putIReg(3, IRExpr_Get( OFFB_NRADDR, ty )); 13416 goto decode_success; 13417 } 13418 else 13419 if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) { 13420 /* branch-and-link-to-noredir %R11 */ 13421 DIP("branch-and-link-to-noredir r11\n"); 13422 delta += 20; 13423 putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) ); 13424 irsb->next = getIReg(11); 13425 irsb->jumpkind = Ijk_NoRedir; 13426 dres.whatNext = Dis_StopHere; 13427 goto decode_success; 13428 } 13429 else 13430 if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { 13431 /* %R3 = guest_NRADDR_GPR2 */ 13432 DIP("r3 = guest_NRADDR_GPR2\n"); 13433 delta += 20; 13434 dres.len = 20; 13435 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty )); 13436 goto decode_success; 13437 } 13438 /* We don't know what it is. Set opc1/opc2 so decode_failure 13439 can print the insn following the Special-insn preamble. */ 13440 theInstr = getUIntBigendianly(code+16); 13441 opc1 = ifieldOPC(theInstr); 13442 opc2 = ifieldOPClo10(theInstr); 13443 goto decode_failure; 13444 /*NOTREACHED*/ 13445 } 13446 } 13447 13448 opc1 = ifieldOPC(theInstr); 13449 opc2 = ifieldOPClo10(theInstr); 13450 13451 // Note: all 'reserved' bits must be cleared, else invalid 13452 switch (opc1) { 13453 13454 /* Integer Arithmetic Instructions */ 13455 case 0x0C: case 0x0D: case 0x0E: // addic, addic., addi 13456 case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic 13457 if (dis_int_arith( theInstr )) goto decode_success; 13458 goto decode_failure; 13459 13460 /* Integer Compare Instructions */ 13461 case 0x0B: case 0x0A: // cmpi, cmpli 13462 if (dis_int_cmp( theInstr )) goto decode_success; 13463 goto decode_failure; 13464 13465 /* Integer Logical Instructions */ 13466 case 0x1C: case 0x1D: case 0x18: // andi., andis., ori 13467 case 0x19: case 0x1A: case 0x1B: // oris, xori, xoris 13468 if (dis_int_logic( theInstr )) goto decode_success; 13469 goto decode_failure; 13470 13471 /* Integer Rotate Instructions */ 13472 case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm 13473 if (dis_int_rot( theInstr )) goto decode_success; 13474 goto decode_failure; 13475 13476 /* 64bit Integer Rotate Instructions */ 13477 case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi 13478 if (dis_int_rot( theInstr )) goto decode_success; 13479 goto decode_failure; 13480 13481 /* Integer Load Instructions */ 13482 case 0x22: case 0x23: case 0x2A: // lbz, lbzu, lha 13483 case 0x2B: case 0x28: case 0x29: // lhau, lhz, lhzu 13484 case 0x20: case 0x21: // lwz, lwzu 13485 if (dis_int_load( theInstr )) goto decode_success; 13486 goto decode_failure; 13487 13488 /* Integer Store Instructions */ 13489 case 0x26: case 0x27: case 0x2C: // stb, stbu, sth 13490 case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu 13491 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 13492 goto decode_failure; 13493 13494 /* Integer Load and Store Multiple Instructions */ 13495 case 0x2E: case 0x2F: // lmw, stmw 13496 if (dis_int_ldst_mult( theInstr )) goto decode_success; 13497 goto decode_failure; 13498 13499 /* Branch Instructions */ 13500 case 0x12: case 0x10: // b, bc 13501 if (dis_branch(theInstr, abiinfo, &dres, 13502 resteerOkFn, callback_opaque)) 13503 goto decode_success; 13504 goto decode_failure; 13505 13506 /* System Linkage Instructions */ 13507 case 0x11: // sc 13508 if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success; 13509 goto decode_failure; 13510 13511 /* Trap Instructions */ 13512 case 0x02: case 0x03: // tdi, twi 13513 if (dis_trapi(theInstr, &dres)) goto decode_success; 13514 goto decode_failure; 13515 13516 /* Floating Point Load Instructions */ 13517 case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd 13518 case 0x33: // lfdu 13519 if (!allow_F) goto decode_noF; 13520 if (dis_fp_load( theInstr )) goto decode_success; 13521 goto decode_failure; 13522 13523 /* Floating Point Store Instructions */ 13524 case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx 13525 case 0x37: // stfdux 13526 if (!allow_F) goto decode_noF; 13527 if (dis_fp_store( theInstr )) goto decode_success; 13528 goto decode_failure; 13529 13530 /* Floating Point Load Double Pair Instructions */ 13531 case 0x39: case 0x3D: 13532 if (!allow_F) goto decode_noF; 13533 if (dis_fp_pair( theInstr )) goto decode_success; 13534 goto decode_failure; 13535 13536 /* 64bit Integer Loads */ 13537 case 0x3A: // ld, ldu, lwa 13538 if (!mode64) goto decode_failure; 13539 if (dis_int_load( theInstr )) goto decode_success; 13540 goto decode_failure; 13541 13542 case 0x3B: 13543 if (!allow_F) goto decode_noF; 13544 opc2 = ifieldOPClo10(theInstr); 13545 switch (opc2) { 13546 case 0x3CE: // fcfidus (implemented as native insn) 13547 if (!allow_VX) 13548 goto decode_noVX; 13549 if (dis_fp_round( theInstr )) 13550 goto decode_success; 13551 goto decode_failure; 13552 case 0x34E: // fcfids 13553 if (dis_fp_round( theInstr )) 13554 goto decode_success; 13555 goto decode_failure; 13556 } 13557 13558 opc2 = IFIELD(theInstr, 1, 5); 13559 switch (opc2) { 13560 /* Floating Point Arith Instructions */ 13561 case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds 13562 case 0x19: // fmuls 13563 if (dis_fp_arith(theInstr)) goto decode_success; 13564 goto decode_failure; 13565 case 0x16: // fsqrts 13566 if (!allow_FX) goto decode_noFX; 13567 if (dis_fp_arith(theInstr)) goto decode_success; 13568 goto decode_failure; 13569 case 0x18: // fres 13570 if (!allow_GX) goto decode_noGX; 13571 if (dis_fp_arith(theInstr)) goto decode_success; 13572 goto decode_failure; 13573 13574 /* Floating Point Mult-Add Instructions */ 13575 case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs 13576 case 0x1F: // fnmadds 13577 if (dis_fp_multadd(theInstr)) goto decode_success; 13578 goto decode_failure; 13579 13580 case 0x1A: // frsqrtes 13581 if (!allow_GX) goto decode_noGX; 13582 if (dis_fp_arith(theInstr)) goto decode_success; 13583 goto decode_failure; 13584 13585 default: 13586 goto decode_failure; 13587 } 13588 break; 13589 13590 case 0x3C: // VSX instructions (except load/store) 13591 { 13592 UInt vsxOpc2 = get_VSX60_opc2(opc2); 13593 /* The vsxOpc2 returned is the "normalized" value, representing the 13594 * instructions secondary opcode as taken from the standard secondary 13595 * opcode field [21:30] (IBM notatition), even if the actual field 13596 * is non-standard. These normalized values are given in the opcode 13597 * appendices of the ISA 2.06 document. 13598 */ 13599 if (vsxOpc2 == 0) 13600 goto decode_failure; 13601 13602 switch (vsxOpc2) { 13603 case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw 13604 case 0x018: case 0x148: // xxsel, xxspltw 13605 if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success; 13606 goto decode_failure; 13607 case 0x268: case 0x248: case 0x288: case 0x208: case 0x228: // xxlxor, xxlor, xxlnor, xxland, xxlandc 13608 if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success; 13609 goto decode_failure; 13610 case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp 13611 case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp 13612 case 0x280: case 0x2A0: // xsmaxdp, xsmindp 13613 case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip 13614 case 0x0B4: case 0x094: // xsredp, xsrsqrtedp 13615 case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz 13616 case 0x092: // xsrdpi 13617 if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success; 13618 goto decode_failure; 13619 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 13620 if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success; 13621 goto decode_failure; 13622 case 0x080: case 0x0E0: // xsadddp, xsdivdp 13623 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp 13624 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp 13625 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp 13626 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp 13627 case 0x0C0: case 0x0A0: // xsmuldp, xssubdp 13628 case 0x096: case 0x0F4: // xssqrtdp, xstdivdp 13629 case 0x0D4: // xstsqrtdp 13630 if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success; 13631 goto decode_failure; 13632 case 0x180: // xvadddp 13633 case 0x1E0: // xvdivdp 13634 case 0x1C0: // xvmuldp 13635 case 0x1A0: // xvsubdp 13636 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp 13637 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp 13638 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp 13639 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp 13640 case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp 13641 case 0x196: // xvsqrtdp 13642 if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success; 13643 goto decode_failure; 13644 case 0x100: // xvaddsp 13645 case 0x160: // xvdivsp 13646 case 0x140: // xvmulsp 13647 case 0x120: // xvsubsp 13648 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp 13649 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp 13650 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp 13651 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp 13652 case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp 13653 case 0x116: // xvsqrtsp 13654 if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success; 13655 goto decode_failure; 13656 13657 case 0x2B0: case 0x2F0: case 0x2D0: // xscvdpsxds, xscvsxddp, xscvuxddp 13658 case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws 13659 case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds 13660 case 0x212: case 0x090: // xscvdpsp, xscvdpuxws 13661 case 0x292: case 0x312: // xscvspdp, xvcvdpsp 13662 case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws 13663 case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds 13664 case 0x392: case 0x330: // xvcvspdp, xvcvspsxds 13665 case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp 13666 case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp 13667 case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp 13668 case 0x3d0: case 0x350: // xvcvuxddp, xvcvuxdsp 13669 case 0x1d0: // xvcvuxwdp 13670 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success; 13671 goto decode_failure; 13672 13673 case 0x18C: case 0x38C: // xvcmpeqdp[.] 13674 case 0x10C: case 0x30C: // xvcmpeqsp[.] 13675 case 0x14C: case 0x34C: // xvcmpgesp[.] 13676 case 0x12C: case 0x32C: // xvcmpgtsp[.] 13677 case 0x1CC: case 0x3CC: // xvcmpgedp[.] 13678 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] 13679 if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success; 13680 goto decode_failure; 13681 13682 case 0x134: // xvresp 13683 case 0x1B4: // xvredp 13684 case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp 13685 case 0x380: case 0x3A0: // xvmaxdp, xvmindp 13686 case 0x300: case 0x320: // xvmaxsp, xvminsp 13687 case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp 13688 case 0x3B2: case 0x332: // xvabsdp, xvabssp 13689 case 0x3D2: case 0x352: // xvnabsdp, xvnabssp 13690 case 0x192: case 0x1D6: // xvrdpi, xvrdpic 13691 case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip 13692 case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp 13693 case 0x112: case 0x156: // xvrspi, xvrspic 13694 case 0x172: case 0x152: // xvrspim, xvrspip 13695 case 0x132: // xvrspiz 13696 if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success; 13697 goto decode_failure; 13698 13699 default: 13700 goto decode_failure; 13701 } 13702 break; 13703 } 13704 13705 /* 64bit Integer Stores */ 13706 case 0x3E: // std, stdu 13707 if (!mode64) goto decode_failure; 13708 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 13709 goto decode_failure; 13710 13711 case 0x3F: 13712 if (!allow_F) goto decode_noF; 13713 /* Instrs using opc[1:5] never overlap instrs using opc[1:10], 13714 so we can simply fall through the first switch statement */ 13715 13716 opc2 = IFIELD(theInstr, 1, 5); 13717 switch (opc2) { 13718 /* Floating Point Arith Instructions */ 13719 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd 13720 case 0x19: // fmul 13721 if (dis_fp_arith(theInstr)) goto decode_success; 13722 goto decode_failure; 13723 case 0x16: // fsqrt 13724 if (!allow_FX) goto decode_noFX; 13725 if (dis_fp_arith(theInstr)) goto decode_success; 13726 goto decode_failure; 13727 case 0x17: case 0x1A: // fsel, frsqrte 13728 if (!allow_GX) goto decode_noGX; 13729 if (dis_fp_arith(theInstr)) goto decode_success; 13730 goto decode_failure; 13731 13732 /* Floating Point Mult-Add Instructions */ 13733 case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub 13734 case 0x1F: // fnmadd 13735 if (dis_fp_multadd(theInstr)) goto decode_success; 13736 goto decode_failure; 13737 13738 case 0x18: // fre 13739 if (!allow_GX) goto decode_noGX; 13740 if (dis_fp_arith(theInstr)) goto decode_success; 13741 goto decode_failure; 13742 13743 default: 13744 break; // Fall through 13745 } 13746 13747 opc2 = IFIELD(theInstr, 1, 10); 13748 switch (opc2) { 13749 /* Floating Point Compare Instructions */ 13750 case 0x000: // fcmpu 13751 case 0x020: // fcmpo 13752 if (dis_fp_cmp(theInstr)) goto decode_success; 13753 goto decode_failure; 13754 13755 case 0x080: // ftdiv 13756 case 0x0A0: // ftsqrt 13757 if (dis_fp_tests(theInstr)) goto decode_success; 13758 goto decode_failure; 13759 13760 /* Floating Point Rounding/Conversion Instructions */ 13761 case 0x00C: // frsp 13762 case 0x00E: // fctiw 13763 case 0x00F: // fctiwz 13764 case 0x32E: // fctid 13765 case 0x32F: // fctidz 13766 case 0x34E: // fcfid 13767 if (dis_fp_round(theInstr)) goto decode_success; 13768 goto decode_failure; 13769 case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns) 13770 case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns) 13771 if (!allow_VX) goto decode_noVX; 13772 if (dis_fp_round(theInstr)) goto decode_success; 13773 goto decode_failure; 13774 13775 /* Power6 rounding stuff */ 13776 case 0x1E8: // frim 13777 case 0x1C8: // frip 13778 case 0x188: // frin 13779 case 0x1A8: // friz 13780 /* A hack to check for P6 capability . . . */ 13781 if ((allow_F && allow_V && allow_FX && allow_GX) && 13782 (dis_fp_round(theInstr))) 13783 goto decode_success; 13784 goto decode_failure; 13785 13786 /* Floating Point Move Instructions */ 13787 case 0x008: // fcpsgn 13788 case 0x028: // fneg 13789 case 0x048: // fmr 13790 case 0x088: // fnabs 13791 case 0x108: // fabs 13792 if (dis_fp_move( theInstr )) goto decode_success; 13793 goto decode_failure; 13794 13795 /* Floating Point Status/Control Register Instructions */ 13796 case 0x026: // mtfsb1 13797 case 0x040: // mcrfs 13798 case 0x046: // mtfsb0 13799 case 0x086: // mtfsfi 13800 case 0x247: // mffs 13801 case 0x2C7: // mtfsf 13802 if (dis_fp_scr( theInstr )) goto decode_success; 13803 goto decode_failure; 13804 13805 default: 13806 goto decode_failure; 13807 } 13808 break; 13809 13810 case 0x13: 13811 switch (opc2) { 13812 13813 /* Condition Register Logical Instructions */ 13814 case 0x101: case 0x081: case 0x121: // crand, crandc, creqv 13815 case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror 13816 case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf 13817 if (dis_cond_logic( theInstr )) goto decode_success; 13818 goto decode_failure; 13819 13820 /* Branch Instructions */ 13821 case 0x210: case 0x010: // bcctr, bclr 13822 if (dis_branch(theInstr, abiinfo, &dres, 13823 resteerOkFn, callback_opaque)) 13824 goto decode_success; 13825 goto decode_failure; 13826 13827 /* Memory Synchronization Instructions */ 13828 case 0x096: // isync 13829 if (dis_memsync( theInstr )) goto decode_success; 13830 goto decode_failure; 13831 13832 default: 13833 goto decode_failure; 13834 } 13835 break; 13836 13837 13838 case 0x1F: 13839 13840 /* For arith instns, bit10 is the OE flag (overflow enable) */ 13841 13842 opc2 = IFIELD(theInstr, 1, 9); 13843 switch (opc2) { 13844 /* Integer Arithmetic Instructions */ 13845 case 0x10A: case 0x00A: case 0x08A: // add, addc, adde 13846 case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw 13847 case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu 13848 case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf 13849 case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme 13850 case 0x0C8: // subfze 13851 if (dis_int_arith( theInstr )) goto decode_success; 13852 goto decode_failure; 13853 13854 case 0x18B: // divweu (implemented as native insn) 13855 case 0x1AB: // divwe (implemented as native insn) 13856 if (!allow_VX) goto decode_noVX; 13857 if (dis_int_arith( theInstr )) goto decode_success; 13858 goto decode_failure; 13859 13860 /* 64bit Integer Arithmetic */ 13861 case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld 13862 case 0x1C9: case 0x1E9: // divdu, divd 13863 if (!mode64) goto decode_failure; 13864 if (dis_int_arith( theInstr )) goto decode_success; 13865 goto decode_failure; 13866 13867 case 0x1A9: // divde (implemented as native insn) 13868 case 0x189: // divdeuo (implemented as native insn) 13869 if (!allow_VX) goto decode_noVX; 13870 if (!mode64) goto decode_failure; 13871 if (dis_int_arith( theInstr )) goto decode_success; 13872 goto decode_failure; 13873 13874 case 0x1FC: // cmpb 13875 if (dis_int_logic( theInstr )) goto decode_success; 13876 goto decode_failure; 13877 13878 default: 13879 break; // Fall through... 13880 } 13881 13882 /* All remaining opcodes use full 10 bits. */ 13883 13884 opc2 = IFIELD(theInstr, 1, 10); 13885 switch (opc2) { 13886 /* Integer Compare Instructions */ 13887 case 0x000: case 0x020: // cmp, cmpl 13888 if (dis_int_cmp( theInstr )) goto decode_success; 13889 goto decode_failure; 13890 13891 /* Integer Logical Instructions */ 13892 case 0x01C: case 0x03C: case 0x01A: // and, andc, cntlzw 13893 case 0x11C: case 0x3BA: case 0x39A: // eqv, extsb, extsh 13894 case 0x1DC: case 0x07C: case 0x1BC: // nand, nor, or 13895 case 0x19C: case 0x13C: // orc, xor 13896 case 0x2DF: case 0x25F: // mftgpr, mffgpr 13897 if (dis_int_logic( theInstr )) goto decode_success; 13898 goto decode_failure; 13899 13900 /* 64bit Integer Logical Instructions */ 13901 case 0x3DA: case 0x03A: // extsw, cntlzd 13902 if (!mode64) goto decode_failure; 13903 if (dis_int_logic( theInstr )) goto decode_success; 13904 goto decode_failure; 13905 13906 /* 64bit Integer Parity Instructions */ 13907 case 0xba: case 0x9a: // prtyd, prtyw 13908 if (dis_int_parity( theInstr )) goto decode_success; 13909 goto decode_failure; 13910 13911 /* Integer Shift Instructions */ 13912 case 0x018: case 0x318: case 0x338: // slw, sraw, srawi 13913 case 0x218: // srw 13914 if (dis_int_shift( theInstr )) goto decode_success; 13915 goto decode_failure; 13916 13917 /* 64bit Integer Shift Instructions */ 13918 case 0x01B: case 0x31A: // sld, srad 13919 case 0x33A: case 0x33B: // sradi 13920 case 0x21B: // srd 13921 if (!mode64) goto decode_failure; 13922 if (dis_int_shift( theInstr )) goto decode_success; 13923 goto decode_failure; 13924 13925 /* Integer Load Instructions */ 13926 case 0x057: case 0x077: case 0x157: // lbzx, lbzux, lhax 13927 case 0x177: case 0x117: case 0x137: // lhaux, lhzx, lhzux 13928 case 0x017: case 0x037: // lwzx, lwzux 13929 if (dis_int_load( theInstr )) goto decode_success; 13930 goto decode_failure; 13931 13932 /* 64bit Integer Load Instructions */ 13933 case 0x035: case 0x015: // ldux, ldx 13934 case 0x175: case 0x155: // lwaux, lwax 13935 if (!mode64) goto decode_failure; 13936 if (dis_int_load( theInstr )) goto decode_success; 13937 goto decode_failure; 13938 13939 /* Integer Store Instructions */ 13940 case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux 13941 case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx 13942 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 13943 goto decode_failure; 13944 13945 /* 64bit Integer Store Instructions */ 13946 case 0x0B5: case 0x095: // stdux, stdx 13947 if (!mode64) goto decode_failure; 13948 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 13949 goto decode_failure; 13950 13951 /* Integer Load and Store with Byte Reverse Instructions */ 13952 case 0x316: case 0x216: case 0x396: // lhbrx, lwbrx, sthbrx 13953 case 0x296: case 0x214: // stwbrx, ldbrx 13954 case 0x294: // stdbrx 13955 if (dis_int_ldst_rev( theInstr )) goto decode_success; 13956 goto decode_failure; 13957 13958 /* Integer Load and Store String Instructions */ 13959 case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi 13960 case 0x295: { // stswx 13961 Bool stopHere = False; 13962 Bool ok = dis_int_ldst_str( theInstr, &stopHere ); 13963 if (!ok) goto decode_failure; 13964 if (stopHere) { 13965 irsb->next = mkSzImm(ty, nextInsnAddr()); 13966 irsb->jumpkind = Ijk_Boring; 13967 dres.whatNext = Dis_StopHere; 13968 } 13969 goto decode_success; 13970 } 13971 13972 /* Memory Synchronization Instructions */ 13973 case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx. 13974 case 0x256: // sync 13975 if (dis_memsync( theInstr )) goto decode_success; 13976 goto decode_failure; 13977 13978 /* 64bit Memory Synchronization Instructions */ 13979 case 0x054: case 0x0D6: // ldarx, stdcx. 13980 if (!mode64) goto decode_failure; 13981 if (dis_memsync( theInstr )) goto decode_success; 13982 goto decode_failure; 13983 13984 /* Processor Control Instructions */ 13985 case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr 13986 case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr 13987 if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success; 13988 goto decode_failure; 13989 13990 /* Cache Management Instructions */ 13991 case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst 13992 case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz 13993 case 0x3D6: // icbi 13994 if (dis_cache_manage( theInstr, &dres, archinfo )) 13995 goto decode_success; 13996 goto decode_failure; 13997 13998//zz /* External Control Instructions */ 13999//zz case 0x136: case 0x1B6: // eciwx, ecowx 14000//zz DIP("external control op => not implemented\n"); 14001//zz goto decode_failure; 14002 14003 /* Trap Instructions */ 14004 case 0x004: case 0x044: // tw, td 14005 if (dis_trap(theInstr, &dres)) goto decode_success; 14006 goto decode_failure; 14007 14008 /* Floating Point Load Instructions */ 14009 case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx 14010 case 0x277: // lfdux 14011 if (!allow_F) goto decode_noF; 14012 if (dis_fp_load( theInstr )) goto decode_success; 14013 goto decode_failure; 14014 14015 /* Floating Point Store Instructions */ 14016 case 0x297: case 0x2B7: case 0x2D7: // stfs, stfsu, stfd 14017 case 0x2F7: // stfdu, stfiwx 14018 if (!allow_F) goto decode_noF; 14019 if (dis_fp_store( theInstr )) goto decode_success; 14020 goto decode_failure; 14021 case 0x3D7: // stfiwx 14022 if (!allow_F) goto decode_noF; 14023 if (!allow_GX) goto decode_noGX; 14024 if (dis_fp_store( theInstr )) goto decode_success; 14025 goto decode_failure; 14026 14027 /* Floating Point Double Pair Indexed Instructions */ 14028 case 0x317: // lfdpx (Power6) 14029 case 0x397: // stfdpx (Power6) 14030 if (!allow_F) goto decode_noF; 14031 if (dis_fp_pair(theInstr)) goto decode_success; 14032 goto decode_failure; 14033 14034 case 0x357: // lfiwax 14035 if (!allow_F) goto decode_noF; 14036 if (dis_fp_load( theInstr )) goto decode_success; 14037 goto decode_failure; 14038 14039 case 0x377: // lfiwzx 14040 if (!allow_F) goto decode_noF; 14041 if (dis_fp_load( theInstr )) goto decode_success; 14042 goto decode_failure; 14043 14044 /* AltiVec instructions */ 14045 14046 /* AV Cache Control - Data streams */ 14047 case 0x156: case 0x176: case 0x336: // dst, dstst, dss 14048 if (!allow_V) goto decode_noV; 14049 if (dis_av_datastream( theInstr )) goto decode_success; 14050 goto decode_failure; 14051 14052 /* AV Load */ 14053 case 0x006: case 0x026: // lvsl, lvsr 14054 case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx 14055 case 0x067: case 0x167: // lvx, lvxl 14056 if (!allow_V) goto decode_noV; 14057 if (dis_av_load( abiinfo, theInstr )) goto decode_success; 14058 goto decode_failure; 14059 14060 /* AV Store */ 14061 case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx 14062 case 0x0E7: case 0x1E7: // stvx, stvxl 14063 if (!allow_V) goto decode_noV; 14064 if (dis_av_store( theInstr )) goto decode_success; 14065 goto decode_failure; 14066 14067 /* VSX Load */ 14068 case 0x24C: // lxsdx 14069 case 0x34C: // lxvd2x 14070 case 0x14C: // lxvdsx 14071 case 0x30C: // lxvw4x 14072 if (dis_vx_load( theInstr )) goto decode_success; 14073 goto decode_failure; 14074 14075 /* VSX Store */ 14076 case 0x2CC: // stxsdx 14077 case 0x3CC: // stxvd2x 14078 case 0x38C: // stxvw4x 14079 if (dis_vx_store( theInstr )) goto decode_success; 14080 goto decode_failure; 14081 14082 /* Miscellaneous ISA 2.06 instructions */ 14083 case 0x1FA: // popcntd 14084 case 0x17A: // popcntw 14085 if (dis_int_logic( theInstr )) goto decode_success; 14086 goto decode_failure; 14087 14088 case 0x0FC: // bpermd 14089 if (dis_int_logic( theInstr )) goto decode_success; 14090 goto decode_failure; 14091 14092 default: 14093 /* Deal with some other cases that we would otherwise have 14094 punted on. */ 14095 /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */ 14096 /* only decode this insn when reserved bit 0 (31 in IBM's 14097 notation) is zero */ 14098 if (IFIELD(theInstr, 0, 6) == (15<<1)) { 14099 UInt rT = ifieldRegDS( theInstr ); 14100 UInt rA = ifieldRegA( theInstr ); 14101 UInt rB = ifieldRegB( theInstr ); 14102 UInt bi = ifieldRegC( theInstr ); 14103 putIReg( 14104 rT, 14105 IRExpr_Mux0X( unop(Iop_32to8,getCRbit( bi )), 14106 getIReg(rB), 14107 rA == 0 ? (mode64 ? mkU64(0) : mkU32(0)) 14108 : getIReg(rA) ) 14109 ); 14110 DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi); 14111 goto decode_success; 14112 } 14113 goto decode_failure; 14114 } 14115 break; 14116 14117 14118 case 0x04: 14119 /* AltiVec instructions */ 14120 14121 opc2 = IFIELD(theInstr, 0, 6); 14122 switch (opc2) { 14123 /* AV Mult-Add, Mult-Sum */ 14124 case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm 14125 case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm 14126 case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs 14127 if (!allow_V) goto decode_noV; 14128 if (dis_av_multarith( theInstr )) goto decode_success; 14129 goto decode_failure; 14130 14131 /* AV Permutations */ 14132 case 0x2A: // vsel 14133 case 0x2B: // vperm 14134 case 0x2C: // vsldoi 14135 if (!allow_V) goto decode_noV; 14136 if (dis_av_permute( theInstr )) goto decode_success; 14137 goto decode_failure; 14138 14139 /* AV Floating Point Mult-Add/Sub */ 14140 case 0x2E: case 0x2F: // vmaddfp, vnmsubfp 14141 if (!allow_V) goto decode_noV; 14142 if (dis_av_fp_arith( theInstr )) goto decode_success; 14143 goto decode_failure; 14144 14145 default: 14146 break; // Fall through... 14147 } 14148 14149 opc2 = IFIELD(theInstr, 0, 11); 14150 switch (opc2) { 14151 /* AV Arithmetic */ 14152 case 0x180: // vaddcuw 14153 case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm 14154 case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws 14155 case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws 14156 case 0x580: // vsubcuw 14157 case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm 14158 case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws 14159 case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws 14160 case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw 14161 case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw 14162 case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw 14163 case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw 14164 case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw 14165 case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw 14166 case 0x008: case 0x048: // vmuloub, vmulouh 14167 case 0x108: case 0x148: // vmulosb, vmulosh 14168 case 0x208: case 0x248: // vmuleub, vmuleuh 14169 case 0x308: case 0x348: // vmulesb, vmulesh 14170 case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs 14171 case 0x688: case 0x788: // vsum2sws, vsumsws 14172 if (!allow_V) goto decode_noV; 14173 if (dis_av_arith( theInstr )) goto decode_success; 14174 goto decode_failure; 14175 14176 /* AV Rotate, Shift */ 14177 case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw 14178 case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw 14179 case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw 14180 case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw 14181 case 0x1C4: case 0x2C4: // vsl, vsr 14182 case 0x40C: case 0x44C: // vslo, vsro 14183 if (!allow_V) goto decode_noV; 14184 if (dis_av_shift( theInstr )) goto decode_success; 14185 goto decode_failure; 14186 14187 /* AV Logic */ 14188 case 0x404: case 0x444: case 0x484: // vand, vandc, vor 14189 case 0x4C4: case 0x504: // vxor, vnor 14190 if (!allow_V) goto decode_noV; 14191 if (dis_av_logic( theInstr )) goto decode_success; 14192 goto decode_failure; 14193 14194 /* AV Processor Control */ 14195 case 0x604: case 0x644: // mfvscr, mtvscr 14196 if (!allow_V) goto decode_noV; 14197 if (dis_av_procctl( theInstr )) goto decode_success; 14198 goto decode_failure; 14199 14200 /* AV Floating Point Arithmetic */ 14201 case 0x00A: case 0x04A: // vaddfp, vsubfp 14202 case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp 14203 case 0x1CA: // vlogefp 14204 case 0x40A: case 0x44A: // vmaxfp, vminfp 14205 if (!allow_V) goto decode_noV; 14206 if (dis_av_fp_arith( theInstr )) goto decode_success; 14207 goto decode_failure; 14208 14209 /* AV Floating Point Round/Convert */ 14210 case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip 14211 case 0x2CA: // vrfim 14212 case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs 14213 case 0x3CA: // vctsxs 14214 if (!allow_V) goto decode_noV; 14215 if (dis_av_fp_convert( theInstr )) goto decode_success; 14216 goto decode_failure; 14217 14218 /* AV Merge, Splat */ 14219 case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw 14220 case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw 14221 case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw 14222 case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw 14223 if (!allow_V) goto decode_noV; 14224 if (dis_av_permute( theInstr )) goto decode_success; 14225 goto decode_failure; 14226 14227 /* AV Pack, Unpack */ 14228 case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus 14229 case 0x0CE: // vpkuwus 14230 case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss 14231 case 0x1CE: // vpkswss 14232 case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb 14233 case 0x2CE: // vupklsh 14234 case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx 14235 if (!allow_V) goto decode_noV; 14236 if (dis_av_pack( theInstr )) goto decode_success; 14237 goto decode_failure; 14238 14239 default: 14240 break; // Fall through... 14241 } 14242 14243 opc2 = IFIELD(theInstr, 0, 10); 14244 switch (opc2) { 14245 14246 /* AV Compare */ 14247 case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw 14248 case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw 14249 case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw 14250 if (!allow_V) goto decode_noV; 14251 if (dis_av_cmp( theInstr )) goto decode_success; 14252 goto decode_failure; 14253 14254 /* AV Floating Point Compare */ 14255 case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp 14256 case 0x3C6: // vcmpbfp 14257 if (!allow_V) goto decode_noV; 14258 if (dis_av_fp_cmp( theInstr )) goto decode_success; 14259 goto decode_failure; 14260 14261 default: 14262 goto decode_failure; 14263 } 14264 break; 14265 14266 default: 14267 goto decode_failure; 14268 14269 decode_noF: 14270 vassert(!allow_F); 14271 vex_printf("disInstr(ppc): declined to decode an FP insn.\n"); 14272 goto decode_failure; 14273 decode_noV: 14274 vassert(!allow_V); 14275 vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n"); 14276 goto decode_failure; 14277 decode_noVX: 14278 vassert(!allow_VX); 14279 vex_printf("disInstr(ppc): declined to decode a Power ISA 2.06 insn.\n"); 14280 goto decode_failure; 14281 decode_noFX: 14282 vassert(!allow_FX); 14283 vex_printf("disInstr(ppc): " 14284 "declined to decode a GeneralPurpose-Optional insn.\n"); 14285 goto decode_failure; 14286 decode_noGX: 14287 vassert(!allow_GX); 14288 vex_printf("disInstr(ppc): " 14289 "declined to decode a Graphics-Optional insn.\n"); 14290 goto decode_failure; 14291 14292 decode_failure: 14293 /* All decode failures end up here. */ 14294 opc2 = (theInstr) & 0x7FF; 14295 vex_printf("disInstr(ppc): unhandled instruction: " 14296 "0x%x\n", theInstr); 14297 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n", 14298 opc1, opc1, opc2, opc2); 14299 14300 /* Tell the dispatcher that this insn cannot be decoded, and so has 14301 not been executed, and (is currently) the next to be executed. 14302 CIA should be up-to-date since it made so at the start of each 14303 insn, but nevertheless be paranoid and update it again right 14304 now. */ 14305 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) ); 14306 irsb->next = mkSzImm(ty, guest_CIA_curr_instr); 14307 irsb->jumpkind = Ijk_NoDecode; 14308 dres.whatNext = Dis_StopHere; 14309 dres.len = 0; 14310 return dres; 14311 14312 } /* switch (opc) for the main (primary) opcode switch. */ 14313 14314 decode_success: 14315 /* All decode successes end up here. */ 14316 DIP("\n"); 14317 14318 if (dres.len == 0) { 14319 dres.len = 4; 14320 } else { 14321 vassert(dres.len == 20); 14322 } 14323 return dres; 14324} 14325 14326#undef DIP 14327#undef DIS 14328 14329 14330/*------------------------------------------------------------*/ 14331/*--- Top-level fn ---*/ 14332/*------------------------------------------------------------*/ 14333 14334/* Disassemble a single instruction into IR. The instruction 14335 is located in host memory at &guest_code[delta]. */ 14336 14337DisResult disInstr_PPC ( IRSB* irsb_IN, 14338 Bool put_IP, 14339 Bool (*resteerOkFn) ( void*, Addr64 ), 14340 Bool resteerCisOk, 14341 void* callback_opaque, 14342 UChar* guest_code_IN, 14343 Long delta, 14344 Addr64 guest_IP, 14345 VexArch guest_arch, 14346 VexArchInfo* archinfo, 14347 VexAbiInfo* abiinfo, 14348 Bool host_bigendian_IN ) 14349{ 14350 IRType ty; 14351 DisResult dres; 14352 UInt mask32, mask64; 14353 UInt hwcaps_guest = archinfo->hwcaps; 14354 14355 vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64); 14356 14357 /* global -- ick */ 14358 mode64 = guest_arch == VexArchPPC64; 14359 ty = mode64 ? Ity_I64 : Ity_I32; 14360 14361 /* do some sanity checks */ 14362 mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V 14363 | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX; 14364 14365 mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX 14366 | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX; 14367 14368 if (mode64) { 14369 vassert((hwcaps_guest & mask32) == 0); 14370 } else { 14371 vassert((hwcaps_guest & mask64) == 0); 14372 } 14373 14374 /* Set globals (see top of this file) */ 14375 guest_code = guest_code_IN; 14376 irsb = irsb_IN; 14377 host_is_bigendian = host_bigendian_IN; 14378 14379 guest_CIA_curr_instr = mkSzAddr(ty, guest_IP); 14380 guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta); 14381 14382 dres = disInstr_PPC_WRK ( put_IP, 14383 resteerOkFn, resteerCisOk, callback_opaque, 14384 delta, archinfo, abiinfo ); 14385 14386 return dres; 14387} 14388 14389 14390/*------------------------------------------------------------*/ 14391/*--- Unused stuff ---*/ 14392/*------------------------------------------------------------*/ 14393 14394///* A potentially more memcheck-friendly implementation of Clz32, with 14395// the boundary case Clz32(0) = 32, which is what ppc requires. */ 14396// 14397//static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg ) 14398//{ 14399// /* Welcome ... to SSA R Us. */ 14400// IRTemp n1 = newTemp(Ity_I32); 14401// IRTemp n2 = newTemp(Ity_I32); 14402// IRTemp n3 = newTemp(Ity_I32); 14403// IRTemp n4 = newTemp(Ity_I32); 14404// IRTemp n5 = newTemp(Ity_I32); 14405// IRTemp n6 = newTemp(Ity_I32); 14406// IRTemp n7 = newTemp(Ity_I32); 14407// IRTemp n8 = newTemp(Ity_I32); 14408// IRTemp n9 = newTemp(Ity_I32); 14409// IRTemp n10 = newTemp(Ity_I32); 14410// IRTemp n11 = newTemp(Ity_I32); 14411// IRTemp n12 = newTemp(Ity_I32); 14412// 14413// /* First, propagate the most significant 1-bit into all lower 14414// positions in the word. */ 14415// /* unsigned int clz ( unsigned int n ) 14416// { 14417// n |= (n >> 1); 14418// n |= (n >> 2); 14419// n |= (n >> 4); 14420// n |= (n >> 8); 14421// n |= (n >> 16); 14422// return bitcount(~n); 14423// } 14424// */ 14425// assign(n1, mkexpr(arg)); 14426// assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1)))); 14427// assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2)))); 14428// assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4)))); 14429// assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8)))); 14430// assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16)))); 14431// /* This gives a word of the form 0---01---1. Now invert it, giving 14432// a word of the form 1---10---0, then do a population-count idiom 14433// (to count the 1s, which is the number of leading zeroes, or 32 14434// if the original word was 0. */ 14435// assign(n7, unop(Iop_Not32, mkexpr(n6))); 14436// 14437// /* unsigned int bitcount ( unsigned int n ) 14438// { 14439// n = n - ((n >> 1) & 0x55555555); 14440// n = (n & 0x33333333) + ((n >> 2) & 0x33333333); 14441// n = (n + (n >> 4)) & 0x0F0F0F0F; 14442// n = n + (n >> 8); 14443// n = (n + (n >> 16)) & 0x3F; 14444// return n; 14445// } 14446// */ 14447// assign(n8, 14448// binop(Iop_Sub32, 14449// mkexpr(n7), 14450// binop(Iop_And32, 14451// binop(Iop_Shr32, mkexpr(n7), mkU8(1)), 14452// mkU32(0x55555555)))); 14453// assign(n9, 14454// binop(Iop_Add32, 14455// binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)), 14456// binop(Iop_And32, 14457// binop(Iop_Shr32, mkexpr(n8), mkU8(2)), 14458// mkU32(0x33333333)))); 14459// assign(n10, 14460// binop(Iop_And32, 14461// binop(Iop_Add32, 14462// mkexpr(n9), 14463// binop(Iop_Shr32, mkexpr(n9), mkU8(4))), 14464// mkU32(0x0F0F0F0F))); 14465// assign(n11, 14466// binop(Iop_Add32, 14467// mkexpr(n10), 14468// binop(Iop_Shr32, mkexpr(n10), mkU8(8)))); 14469// assign(n12, 14470// binop(Iop_Add32, 14471// mkexpr(n11), 14472// binop(Iop_Shr32, mkexpr(n11), mkU8(16)))); 14473// return 14474// binop(Iop_And32, mkexpr(n12), mkU32(0x3F)); 14475//} 14476 14477/*--------------------------------------------------------------------*/ 14478/*--- end guest_ppc_toIR.c ---*/ 14479/*--------------------------------------------------------------------*/ 14480