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-2012 OpenWorks LLP 12 info (at) 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. */ 149 static Bool host_is_bigendian; 150 151 /* Pointer to the guest code area. */ 152 static UChar* guest_code; 153 154 /* The guest address corresponding to guest_code[0]. */ 155 static Addr64 guest_CIA_bbstart; 156 157 /* The guest address for the instruction currently being 158 translated. */ 159 static Addr64 guest_CIA_curr_instr; 160 161 /* The IRSB* into which we're generating code. */ 162 static IRSB* irsb; 163 164 /* Is our guest binary 32 or 64bit? Set at each call to 165 disInstr_PPC below. */ 166 static 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. 173 static 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_DFPROUND offsetofPPCGuestState(guest_DFPROUND) 226 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE) 227 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR) 228 #define OFFB_EMWARN offsetofPPCGuestState(guest_EMWARN) 229 #define OFFB_TISTART offsetofPPCGuestState(guest_TISTART) 230 #define OFFB_TILEN offsetofPPCGuestState(guest_TILEN) 231 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) 232 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2) 233 234 235 /*------------------------------------------------------------*/ 236 /*--- Extract instruction fields --- */ 237 /*------------------------------------------------------------*/ 238 239 /* Extract field from insn, given idx (zero = lsb) and field length */ 240 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1)) 241 242 /* Extract primary opcode, instr[31:26] */ 243 static UChar ifieldOPC( UInt instr ) { 244 return toUChar( IFIELD( instr, 26, 6 ) ); 245 } 246 247 /* Extract 10-bit secondary opcode, instr[10:1] */ 248 static UInt ifieldOPClo10 ( UInt instr) { 249 return IFIELD( instr, 1, 10 ); 250 } 251 252 /* Extract 9-bit secondary opcode, instr[9:1] */ 253 static UInt ifieldOPClo9 ( UInt instr) { 254 return IFIELD( instr, 1, 9 ); 255 } 256 257 /* Extract 8-bit secondary opcode, instr[8:1] */ 258 static UInt ifieldOPClo8 ( UInt instr) { 259 return IFIELD( instr, 1, 8 ); 260 } 261 262 /* Extract 5-bit secondary opcode, instr[5:1] */ 263 static UInt ifieldOPClo5 ( UInt instr) { 264 return IFIELD( instr, 1, 5 ); 265 } 266 267 /* Extract RD (destination register) field, instr[25:21] */ 268 static UChar ifieldRegDS( UInt instr ) { 269 return toUChar( IFIELD( instr, 21, 5 ) ); 270 } 271 272 /* Extract XT (destination register) field, instr[0,25:21] */ 273 static UChar ifieldRegXT ( UInt instr ) 274 { 275 UChar upper_bit = toUChar (IFIELD (instr, 0, 1)); 276 UChar lower_bits = toUChar (IFIELD (instr, 21, 5)); 277 return (upper_bit << 5) | lower_bits; 278 } 279 280 /* Extract XS (store source register) field, instr[0,25:21] */ 281 static inline UChar ifieldRegXS ( UInt instr ) 282 { 283 return ifieldRegXT ( instr ); 284 } 285 286 /* Extract RA (1st source register) field, instr[20:16] */ 287 static UChar ifieldRegA ( UInt instr ) { 288 return toUChar( IFIELD( instr, 16, 5 ) ); 289 } 290 291 /* Extract XA (1st source register) field, instr[2,20:16] */ 292 static UChar ifieldRegXA ( UInt instr ) 293 { 294 UChar upper_bit = toUChar (IFIELD (instr, 2, 1)); 295 UChar lower_bits = toUChar (IFIELD (instr, 16, 5)); 296 return (upper_bit << 5) | lower_bits; 297 } 298 299 /* Extract RB (2nd source register) field, instr[15:11] */ 300 static UChar ifieldRegB ( UInt instr ) { 301 return toUChar( IFIELD( instr, 11, 5 ) ); 302 } 303 304 /* Extract XB (2nd source register) field, instr[1,15:11] */ 305 static UChar ifieldRegXB ( UInt instr ) 306 { 307 UChar upper_bit = toUChar (IFIELD (instr, 1, 1)); 308 UChar lower_bits = toUChar (IFIELD (instr, 11, 5)); 309 return (upper_bit << 5) | lower_bits; 310 } 311 312 /* Extract RC (3rd source register) field, instr[10:6] */ 313 static UChar ifieldRegC ( UInt instr ) { 314 return toUChar( IFIELD( instr, 6, 5 ) ); 315 } 316 317 /* Extract XC (3rd source register) field, instr[3,10:6] */ 318 static UChar ifieldRegXC ( UInt instr ) 319 { 320 UChar upper_bit = toUChar (IFIELD (instr, 3, 1)); 321 UChar lower_bits = toUChar (IFIELD (instr, 6, 5)); 322 return (upper_bit << 5) | lower_bits; 323 } 324 325 /* Extract bit 10, instr[10] */ 326 static UChar ifieldBIT10 ( UInt instr ) { 327 return toUChar( IFIELD( instr, 10, 1 ) ); 328 } 329 330 /* Extract 2nd lowest bit, instr[1] */ 331 static UChar ifieldBIT1 ( UInt instr ) { 332 return toUChar( IFIELD( instr, 1, 1 ) ); 333 } 334 335 /* Extract lowest bit, instr[0] */ 336 static UChar ifieldBIT0 ( UInt instr ) { 337 return toUChar( instr & 0x1 ); 338 } 339 340 /* Extract unsigned bottom half, instr[15:0] */ 341 static UInt ifieldUIMM16 ( UInt instr ) { 342 return instr & 0xFFFF; 343 } 344 345 /* Extract unsigned bottom 26 bits, instr[25:0] */ 346 static UInt ifieldUIMM26 ( UInt instr ) { 347 return instr & 0x3FFFFFF; 348 } 349 350 /* Extract DM field, instr[9:8] */ 351 static UChar ifieldDM ( UInt instr ) { 352 return toUChar( IFIELD( instr, 8, 2 ) ); 353 } 354 355 /* Extract SHW field, instr[9:8] */ 356 static inline UChar ifieldSHW ( UInt instr ) 357 { 358 return ifieldDM ( instr ); 359 } 360 361 /*------------------------------------------------------------*/ 362 /*--- Guest-state identifiers ---*/ 363 /*------------------------------------------------------------*/ 364 365 typedef enum { 366 PPC_GST_CIA, // Current Instruction Address 367 PPC_GST_LR, // Link Register 368 PPC_GST_CTR, // Count Register 369 PPC_GST_XER, // Overflow, carry flags, byte count 370 PPC_GST_CR, // Condition Register 371 PPC_GST_FPSCR, // Floating Point Status/Control Register 372 PPC_GST_VRSAVE, // Vector Save/Restore Register 373 PPC_GST_VSCR, // Vector Status and Control Register 374 PPC_GST_EMWARN, // Emulation warnings 375 PPC_GST_TISTART,// For icbi: start of area to invalidate 376 PPC_GST_TILEN, // For icbi: length of area to invalidate 377 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn 378 PPC_GST_SPRG3_RO, // SPRG3 379 PPC_GST_MAX 380 } PPC_GST; 381 382 #define MASK_FPSCR_RN 0x3ULL // Binary floating point rounding mode 383 #define MASK_FPSCR_DRN 0x700000000ULL // Decimal floating point rounding mode 384 #define MASK_VSCR_VALID 0x00010001 385 386 387 /*------------------------------------------------------------*/ 388 /*--- FP Helpers ---*/ 389 /*------------------------------------------------------------*/ 390 391 /* Produce the 32-bit pattern corresponding to the supplied 392 float. */ 393 static UInt float_to_bits ( Float f ) 394 { 395 union { UInt i; Float f; } u; 396 vassert(4 == sizeof(UInt)); 397 vassert(4 == sizeof(Float)); 398 vassert(4 == sizeof(u)); 399 u.f = f; 400 return u.i; 401 } 402 403 404 /*------------------------------------------------------------*/ 405 /*--- Misc Helpers ---*/ 406 /*------------------------------------------------------------*/ 407 408 /* Generate mask with 1's from 'begin' through 'end', 409 wrapping if begin > end. 410 begin->end works from right to left, 0=lsb 411 */ 412 static UInt MASK32( UInt begin, UInt end ) 413 { 414 UInt m1, m2, mask; 415 vassert(begin < 32); 416 vassert(end < 32); 417 m1 = ((UInt)(-1)) << begin; 418 m2 = ((UInt)(-1)) << end << 1; 419 mask = m1 ^ m2; 420 if (begin > end) mask = ~mask; // wrap mask 421 return mask; 422 } 423 424 static ULong MASK64( UInt begin, UInt end ) 425 { 426 ULong m1, m2, mask; 427 vassert(begin < 64); 428 vassert(end < 64); 429 m1 = ((ULong)(-1)) << begin; 430 m2 = ((ULong)(-1)) << end << 1; 431 mask = m1 ^ m2; 432 if (begin > end) mask = ~mask; // wrap mask 433 return mask; 434 } 435 436 static Addr64 nextInsnAddr( void ) 437 { 438 return guest_CIA_curr_instr + 4; 439 } 440 441 442 /*------------------------------------------------------------*/ 443 /*--- Helper bits and pieces for deconstructing the ---*/ 444 /*--- ppc32/64 insn stream. ---*/ 445 /*------------------------------------------------------------*/ 446 447 /* Add a statement to the list held by "irsb". */ 448 static void stmt ( IRStmt* st ) 449 { 450 addStmtToIRSB( irsb, st ); 451 } 452 453 /* Generate a new temporary of the given type. */ 454 static IRTemp newTemp ( IRType ty ) 455 { 456 vassert(isPlausibleIRType(ty)); 457 return newIRTemp( irsb->tyenv, ty ); 458 } 459 460 /* Various simple conversions */ 461 462 static UChar extend_s_5to8 ( UChar x ) 463 { 464 return toUChar((((Int)x) << 27) >> 27); 465 } 466 467 static UInt extend_s_8to32( UChar x ) 468 { 469 return (UInt)((((Int)x) << 24) >> 24); 470 } 471 472 static UInt extend_s_16to32 ( UInt x ) 473 { 474 return (UInt)((((Int)x) << 16) >> 16); 475 } 476 477 static ULong extend_s_16to64 ( UInt x ) 478 { 479 return (ULong)((((Long)x) << 48) >> 48); 480 } 481 482 static ULong extend_s_26to64 ( UInt x ) 483 { 484 return (ULong)((((Long)x) << 38) >> 38); 485 } 486 487 static ULong extend_s_32to64 ( UInt x ) 488 { 489 return (ULong)((((Long)x) << 32) >> 32); 490 } 491 492 /* Do a big-endian load of a 32-bit word, regardless of the endianness 493 of the underlying host. */ 494 static UInt getUIntBigendianly ( UChar* p ) 495 { 496 UInt w = 0; 497 w = (w << 8) | p[0]; 498 w = (w << 8) | p[1]; 499 w = (w << 8) | p[2]; 500 w = (w << 8) | p[3]; 501 return w; 502 } 503 504 505 /*------------------------------------------------------------*/ 506 /*--- Helpers for constructing IR. ---*/ 507 /*------------------------------------------------------------*/ 508 509 static void assign ( IRTemp dst, IRExpr* e ) 510 { 511 stmt( IRStmt_WrTmp(dst, e) ); 512 } 513 514 /* This generates a normal (non store-conditional) store. */ 515 static void storeBE ( IRExpr* addr, IRExpr* data ) 516 { 517 IRType tyA = typeOfIRExpr(irsb->tyenv, addr); 518 vassert(tyA == Ity_I32 || tyA == Ity_I64); 519 stmt( IRStmt_Store(Iend_BE, addr, data) ); 520 } 521 522 static IRExpr* unop ( IROp op, IRExpr* a ) 523 { 524 return IRExpr_Unop(op, a); 525 } 526 527 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 528 { 529 return IRExpr_Binop(op, a1, a2); 530 } 531 532 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 533 { 534 return IRExpr_Triop(op, a1, a2, a3); 535 } 536 537 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2, 538 IRExpr* a3, IRExpr* a4 ) 539 { 540 return IRExpr_Qop(op, a1, a2, a3, a4); 541 } 542 543 static IRExpr* mkexpr ( IRTemp tmp ) 544 { 545 return IRExpr_RdTmp(tmp); 546 } 547 548 static IRExpr* mkU8 ( UChar i ) 549 { 550 return IRExpr_Const(IRConst_U8(i)); 551 } 552 553 static IRExpr* mkU16 ( UInt i ) 554 { 555 return IRExpr_Const(IRConst_U16(i)); 556 } 557 558 static IRExpr* mkU32 ( UInt i ) 559 { 560 return IRExpr_Const(IRConst_U32(i)); 561 } 562 563 static IRExpr* mkU64 ( ULong i ) 564 { 565 return IRExpr_Const(IRConst_U64(i)); 566 } 567 568 static IRExpr* mkV128 ( UShort i ) 569 { 570 vassert(i == 0 || i == 0xffff); 571 return IRExpr_Const(IRConst_V128(i)); 572 } 573 574 /* This generates a normal (non load-linked) load. */ 575 static IRExpr* loadBE ( IRType ty, IRExpr* addr ) 576 { 577 return IRExpr_Load(Iend_BE, ty, addr); 578 } 579 580 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 ) 581 { 582 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 583 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 584 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1), 585 unop(Iop_1Uto32, arg2))); 586 } 587 588 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 ) 589 { 590 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 591 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 592 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1), 593 unop(Iop_1Uto32, arg2))); 594 } 595 596 /* expand V128_8Ux16 to 2x V128_16Ux8's */ 597 static void expand8Ux16( IRExpr* vIn, 598 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 599 { 600 IRTemp ones8x16 = newTemp(Ity_V128); 601 602 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 603 vassert(vEvn && *vEvn == IRTemp_INVALID); 604 vassert(vOdd && *vOdd == IRTemp_INVALID); 605 *vEvn = newTemp(Ity_V128); 606 *vOdd = newTemp(Ity_V128); 607 608 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 609 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) ); 610 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 611 binop(Iop_ShrV128, vIn, mkU8(8))) ); 612 } 613 614 /* expand V128_8Sx16 to 2x V128_16Sx8's */ 615 static void expand8Sx16( IRExpr* vIn, 616 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 617 { 618 IRTemp ones8x16 = newTemp(Ity_V128); 619 620 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 621 vassert(vEvn && *vEvn == IRTemp_INVALID); 622 vassert(vOdd && *vOdd == IRTemp_INVALID); 623 *vEvn = newTemp(Ity_V128); 624 *vOdd = newTemp(Ity_V128); 625 626 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 627 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) ); 628 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 629 binop(Iop_ShrV128, vIn, mkU8(8))) ); 630 } 631 632 /* expand V128_16Uto8 to 2x V128_32Ux4's */ 633 static void expand16Ux8( IRExpr* vIn, 634 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 635 { 636 IRTemp ones16x8 = newTemp(Ity_V128); 637 638 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 639 vassert(vEvn && *vEvn == IRTemp_INVALID); 640 vassert(vOdd && *vOdd == IRTemp_INVALID); 641 *vEvn = newTemp(Ity_V128); 642 *vOdd = newTemp(Ity_V128); 643 644 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 645 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) ); 646 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 647 binop(Iop_ShrV128, vIn, mkU8(16))) ); 648 } 649 650 /* expand V128_16Sto8 to 2x V128_32Sx4's */ 651 static void expand16Sx8( IRExpr* vIn, 652 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 653 { 654 IRTemp ones16x8 = newTemp(Ity_V128); 655 656 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 657 vassert(vEvn && *vEvn == IRTemp_INVALID); 658 vassert(vOdd && *vOdd == IRTemp_INVALID); 659 *vEvn = newTemp(Ity_V128); 660 *vOdd = newTemp(Ity_V128); 661 662 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 663 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) ); 664 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 665 binop(Iop_ShrV128, vIn, mkU8(16))) ); 666 } 667 668 /* break V128 to 4xF64's*/ 669 static void breakV128to4xF64( IRExpr* t128, 670 /*OUTs*/ 671 IRTemp* t3, IRTemp* t2, 672 IRTemp* t1, IRTemp* t0 ) 673 { 674 IRTemp hi64 = newTemp(Ity_I64); 675 IRTemp lo64 = newTemp(Ity_I64); 676 677 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 678 vassert(t0 && *t0 == IRTemp_INVALID); 679 vassert(t1 && *t1 == IRTemp_INVALID); 680 vassert(t2 && *t2 == IRTemp_INVALID); 681 vassert(t3 && *t3 == IRTemp_INVALID); 682 *t0 = newTemp(Ity_F64); 683 *t1 = newTemp(Ity_F64); 684 *t2 = newTemp(Ity_F64); 685 *t3 = newTemp(Ity_F64); 686 687 assign( hi64, unop(Iop_V128HIto64, t128) ); 688 assign( lo64, unop(Iop_V128to64, t128) ); 689 assign( *t3, 690 unop( Iop_F32toF64, 691 unop( Iop_ReinterpI32asF32, 692 unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) ); 693 assign( *t2, 694 unop( Iop_F32toF64, 695 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) ); 696 assign( *t1, 697 unop( Iop_F32toF64, 698 unop( Iop_ReinterpI32asF32, 699 unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) ); 700 assign( *t0, 701 unop( Iop_F32toF64, 702 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) ); 703 } 704 705 706 /* break V128 to 4xI32's, then sign-extend to I64's */ 707 static void breakV128to4x64S( IRExpr* t128, 708 /*OUTs*/ 709 IRTemp* t3, IRTemp* t2, 710 IRTemp* t1, IRTemp* t0 ) 711 { 712 IRTemp hi64 = newTemp(Ity_I64); 713 IRTemp lo64 = newTemp(Ity_I64); 714 715 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 716 vassert(t0 && *t0 == IRTemp_INVALID); 717 vassert(t1 && *t1 == IRTemp_INVALID); 718 vassert(t2 && *t2 == IRTemp_INVALID); 719 vassert(t3 && *t3 == IRTemp_INVALID); 720 *t0 = newTemp(Ity_I64); 721 *t1 = newTemp(Ity_I64); 722 *t2 = newTemp(Ity_I64); 723 *t3 = newTemp(Ity_I64); 724 725 assign( hi64, unop(Iop_V128HIto64, t128) ); 726 assign( lo64, unop(Iop_V128to64, t128) ); 727 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 728 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) ); 729 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 730 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) ); 731 } 732 733 /* break V128 to 4xI32's, then zero-extend to I64's */ 734 static void breakV128to4x64U ( IRExpr* t128, 735 /*OUTs*/ 736 IRTemp* t3, IRTemp* t2, 737 IRTemp* t1, IRTemp* t0 ) 738 { 739 IRTemp hi64 = newTemp(Ity_I64); 740 IRTemp lo64 = newTemp(Ity_I64); 741 742 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 743 vassert(t0 && *t0 == IRTemp_INVALID); 744 vassert(t1 && *t1 == IRTemp_INVALID); 745 vassert(t2 && *t2 == IRTemp_INVALID); 746 vassert(t3 && *t3 == IRTemp_INVALID); 747 *t0 = newTemp(Ity_I64); 748 *t1 = newTemp(Ity_I64); 749 *t2 = newTemp(Ity_I64); 750 *t3 = newTemp(Ity_I64); 751 752 assign( hi64, unop(Iop_V128HIto64, t128) ); 753 assign( lo64, unop(Iop_V128to64, t128) ); 754 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 755 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) ); 756 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 757 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) ); 758 } 759 760 static void breakV128to4x32( IRExpr* t128, 761 /*OUTs*/ 762 IRTemp* t3, IRTemp* t2, 763 IRTemp* t1, IRTemp* t0 ) 764 { 765 IRTemp hi64 = newTemp(Ity_I64); 766 IRTemp lo64 = newTemp(Ity_I64); 767 768 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 769 vassert(t0 && *t0 == IRTemp_INVALID); 770 vassert(t1 && *t1 == IRTemp_INVALID); 771 vassert(t2 && *t2 == IRTemp_INVALID); 772 vassert(t3 && *t3 == IRTemp_INVALID); 773 *t0 = newTemp(Ity_I32); 774 *t1 = newTemp(Ity_I32); 775 *t2 = newTemp(Ity_I32); 776 *t3 = newTemp(Ity_I32); 777 778 assign( hi64, unop(Iop_V128HIto64, t128) ); 779 assign( lo64, unop(Iop_V128to64, t128) ); 780 assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) ); 781 assign( *t2, unop(Iop_64to32, mkexpr(hi64)) ); 782 assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) ); 783 assign( *t0, unop(Iop_64to32, mkexpr(lo64)) ); 784 } 785 786 787 /* Signed saturating narrow 64S to 32 */ 788 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 ) 789 { 790 IRTemp hi32 = newTemp(Ity_I32); 791 IRTemp lo32 = newTemp(Ity_I32); 792 793 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 794 795 assign( hi32, unop(Iop_64HIto32, t64)); 796 assign( lo32, unop(Iop_64to32, t64)); 797 798 return IRExpr_Mux0X( 799 /* if (hi32 == (lo32 >>s 31)) */ 800 unop(Iop_1Uto8, 801 binop(Iop_CmpEQ32, mkexpr(hi32), 802 binop( Iop_Sar32, mkexpr(lo32), mkU8(31)))), 803 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */ 804 binop(Iop_Add32, mkU32(0x7FFFFFFF), 805 binop(Iop_Shr32, mkexpr(hi32), mkU8(31))), 806 /* then: within signed-32 range: lo half good enough */ 807 mkexpr(lo32) ); 808 } 809 810 /* Unsigned saturating narrow 64S to 32 */ 811 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 ) 812 { 813 IRTemp hi32 = newTemp(Ity_I32); 814 IRTemp lo32 = newTemp(Ity_I32); 815 816 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 817 818 assign( hi32, unop(Iop_64HIto32, t64)); 819 assign( lo32, unop(Iop_64to32, t64)); 820 821 return IRExpr_Mux0X( 822 /* if (top 32 bits of t64 are 0) */ 823 unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0))), 824 /* else: positive saturate -> 0xFFFFFFFF */ 825 mkU32(0xFFFFFFFF), 826 /* then: within unsigned-32 range: lo half good enough */ 827 mkexpr(lo32) ); 828 } 829 830 /* Signed saturate narrow 64->32, combining to V128 */ 831 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2, 832 IRExpr* t1, IRExpr* t0 ) 833 { 834 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 835 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 836 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 837 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 838 return binop(Iop_64HLtoV128, 839 binop(Iop_32HLto64, 840 mkQNarrow64Sto32( t3 ), 841 mkQNarrow64Sto32( t2 )), 842 binop(Iop_32HLto64, 843 mkQNarrow64Sto32( t1 ), 844 mkQNarrow64Sto32( t0 ))); 845 } 846 847 /* Unsigned saturate narrow 64->32, combining to V128 */ 848 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2, 849 IRExpr* t1, IRExpr* t0 ) 850 { 851 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 852 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 853 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 854 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 855 return binop(Iop_64HLtoV128, 856 binop(Iop_32HLto64, 857 mkQNarrow64Uto32( t3 ), 858 mkQNarrow64Uto32( t2 )), 859 binop(Iop_32HLto64, 860 mkQNarrow64Uto32( t1 ), 861 mkQNarrow64Uto32( t0 ))); 862 } 863 864 /* Simulate irops Iop_MullOdd*, since we don't have them */ 865 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \ 866 binop(Iop_MullEven8Ux16, \ 867 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 868 binop(Iop_ShrV128, expr_vB, mkU8(8))) 869 870 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \ 871 binop(Iop_MullEven8Sx16, \ 872 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 873 binop(Iop_ShrV128, expr_vB, mkU8(8))) 874 875 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \ 876 binop(Iop_MullEven16Ux8, \ 877 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 878 binop(Iop_ShrV128, expr_vB, mkU8(16))) 879 880 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \ 881 binop(Iop_MullEven16Sx8, \ 882 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 883 binop(Iop_ShrV128, expr_vB, mkU8(16))) 884 885 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src ) 886 { 887 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 888 return unop(Iop_32Sto64, unop(Iop_64to32, src)); 889 } 890 891 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src ) 892 { 893 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 894 return unop(Iop_32Uto64, unop(Iop_64to32, src)); 895 } 896 897 static IROp mkSzOp ( IRType ty, IROp op8 ) 898 { 899 Int adj; 900 vassert(ty == Ity_I8 || ty == Ity_I16 || 901 ty == Ity_I32 || ty == Ity_I64); 902 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || 903 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 || 904 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 || 905 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || 906 op8 == Iop_Not8 ); 907 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3)); 908 return adj + op8; 909 } 910 911 /* Make sure we get valid 32 and 64bit addresses */ 912 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 913 { 914 vassert(ty == Ity_I32 || ty == Ity_I64); 915 return ( ty == Ity_I64 ? 916 (Addr64)addr : 917 (Addr64)extend_s_32to64( toUInt(addr) ) ); 918 } 919 920 /* sz, ULong -> IRExpr */ 921 static IRExpr* mkSzImm ( IRType ty, ULong imm64 ) 922 { 923 vassert(ty == Ity_I32 || ty == Ity_I64); 924 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64); 925 } 926 927 /* sz, ULong -> IRConst */ 928 static IRConst* mkSzConst ( IRType ty, ULong imm64 ) 929 { 930 vassert(ty == Ity_I32 || ty == Ity_I64); 931 return ( ty == Ity_I64 ? 932 IRConst_U64(imm64) : 933 IRConst_U32((UInt)imm64) ); 934 } 935 936 /* Sign extend imm16 -> IRExpr* */ 937 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 ) 938 { 939 vassert(ty == Ity_I32 || ty == Ity_I64); 940 return ( ty == Ity_I64 ? 941 mkU64(extend_s_16to64(imm16)) : 942 mkU32(extend_s_16to32(imm16)) ); 943 } 944 945 /* Sign extend imm32 -> IRExpr* */ 946 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 ) 947 { 948 vassert(ty == Ity_I32 || ty == Ity_I64); 949 return ( ty == Ity_I64 ? 950 mkU64(extend_s_32to64(imm32)) : 951 mkU32(imm32) ); 952 } 953 954 /* IR narrows I32/I64 -> I8/I16/I32 */ 955 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src ) 956 { 957 vassert(ty == Ity_I32 || ty == Ity_I64); 958 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 959 } 960 961 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src ) 962 { 963 vassert(ty == Ity_I32 || ty == Ity_I64); 964 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src); 965 } 966 967 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src ) 968 { 969 vassert(ty == Ity_I32 || ty == Ity_I64); 970 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 971 } 972 973 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */ 974 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined ) 975 { 976 IROp op; 977 vassert(ty == Ity_I32 || ty == Ity_I64); 978 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64; 979 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64; 980 return unop(op, src); 981 } 982 983 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined ) 984 { 985 IROp op; 986 vassert(ty == Ity_I32 || ty == Ity_I64); 987 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64; 988 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64; 989 return unop(op, src); 990 } 991 992 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined ) 993 { 994 vassert(ty == Ity_I32 || ty == Ity_I64); 995 if (ty == Ity_I32) 996 return src; 997 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 998 } 999 1000 1001 static Int integerGuestRegOffset ( UInt archreg ) 1002 { 1003 vassert(archreg < 32); 1004 1005 // jrs: probably not necessary; only matters if we reference sub-parts 1006 // of the ppc registers, but that isn't the case 1007 // later: this might affect Altivec though? 1008 vassert(host_is_bigendian); 1009 1010 switch (archreg) { 1011 case 0: return offsetofPPCGuestState(guest_GPR0); 1012 case 1: return offsetofPPCGuestState(guest_GPR1); 1013 case 2: return offsetofPPCGuestState(guest_GPR2); 1014 case 3: return offsetofPPCGuestState(guest_GPR3); 1015 case 4: return offsetofPPCGuestState(guest_GPR4); 1016 case 5: return offsetofPPCGuestState(guest_GPR5); 1017 case 6: return offsetofPPCGuestState(guest_GPR6); 1018 case 7: return offsetofPPCGuestState(guest_GPR7); 1019 case 8: return offsetofPPCGuestState(guest_GPR8); 1020 case 9: return offsetofPPCGuestState(guest_GPR9); 1021 case 10: return offsetofPPCGuestState(guest_GPR10); 1022 case 11: return offsetofPPCGuestState(guest_GPR11); 1023 case 12: return offsetofPPCGuestState(guest_GPR12); 1024 case 13: return offsetofPPCGuestState(guest_GPR13); 1025 case 14: return offsetofPPCGuestState(guest_GPR14); 1026 case 15: return offsetofPPCGuestState(guest_GPR15); 1027 case 16: return offsetofPPCGuestState(guest_GPR16); 1028 case 17: return offsetofPPCGuestState(guest_GPR17); 1029 case 18: return offsetofPPCGuestState(guest_GPR18); 1030 case 19: return offsetofPPCGuestState(guest_GPR19); 1031 case 20: return offsetofPPCGuestState(guest_GPR20); 1032 case 21: return offsetofPPCGuestState(guest_GPR21); 1033 case 22: return offsetofPPCGuestState(guest_GPR22); 1034 case 23: return offsetofPPCGuestState(guest_GPR23); 1035 case 24: return offsetofPPCGuestState(guest_GPR24); 1036 case 25: return offsetofPPCGuestState(guest_GPR25); 1037 case 26: return offsetofPPCGuestState(guest_GPR26); 1038 case 27: return offsetofPPCGuestState(guest_GPR27); 1039 case 28: return offsetofPPCGuestState(guest_GPR28); 1040 case 29: return offsetofPPCGuestState(guest_GPR29); 1041 case 30: return offsetofPPCGuestState(guest_GPR30); 1042 case 31: return offsetofPPCGuestState(guest_GPR31); 1043 default: break; 1044 } 1045 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/ 1046 } 1047 1048 static IRExpr* getIReg ( UInt archreg ) 1049 { 1050 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1051 vassert(archreg < 32); 1052 return IRExpr_Get( integerGuestRegOffset(archreg), ty ); 1053 } 1054 1055 /* Ditto, but write to a reg instead. */ 1056 static void putIReg ( UInt archreg, IRExpr* e ) 1057 { 1058 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1059 vassert(archreg < 32); 1060 vassert(typeOfIRExpr(irsb->tyenv, e) == ty ); 1061 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) ); 1062 } 1063 1064 1065 /* Floating point egisters are mapped to VSX registers[0..31]. */ 1066 static Int floatGuestRegOffset ( UInt archreg ) 1067 { 1068 vassert(archreg < 32); 1069 1070 switch (archreg) { 1071 case 0: return offsetofPPCGuestState(guest_VSR0); 1072 case 1: return offsetofPPCGuestState(guest_VSR1); 1073 case 2: return offsetofPPCGuestState(guest_VSR2); 1074 case 3: return offsetofPPCGuestState(guest_VSR3); 1075 case 4: return offsetofPPCGuestState(guest_VSR4); 1076 case 5: return offsetofPPCGuestState(guest_VSR5); 1077 case 6: return offsetofPPCGuestState(guest_VSR6); 1078 case 7: return offsetofPPCGuestState(guest_VSR7); 1079 case 8: return offsetofPPCGuestState(guest_VSR8); 1080 case 9: return offsetofPPCGuestState(guest_VSR9); 1081 case 10: return offsetofPPCGuestState(guest_VSR10); 1082 case 11: return offsetofPPCGuestState(guest_VSR11); 1083 case 12: return offsetofPPCGuestState(guest_VSR12); 1084 case 13: return offsetofPPCGuestState(guest_VSR13); 1085 case 14: return offsetofPPCGuestState(guest_VSR14); 1086 case 15: return offsetofPPCGuestState(guest_VSR15); 1087 case 16: return offsetofPPCGuestState(guest_VSR16); 1088 case 17: return offsetofPPCGuestState(guest_VSR17); 1089 case 18: return offsetofPPCGuestState(guest_VSR18); 1090 case 19: return offsetofPPCGuestState(guest_VSR19); 1091 case 20: return offsetofPPCGuestState(guest_VSR20); 1092 case 21: return offsetofPPCGuestState(guest_VSR21); 1093 case 22: return offsetofPPCGuestState(guest_VSR22); 1094 case 23: return offsetofPPCGuestState(guest_VSR23); 1095 case 24: return offsetofPPCGuestState(guest_VSR24); 1096 case 25: return offsetofPPCGuestState(guest_VSR25); 1097 case 26: return offsetofPPCGuestState(guest_VSR26); 1098 case 27: return offsetofPPCGuestState(guest_VSR27); 1099 case 28: return offsetofPPCGuestState(guest_VSR28); 1100 case 29: return offsetofPPCGuestState(guest_VSR29); 1101 case 30: return offsetofPPCGuestState(guest_VSR30); 1102 case 31: return offsetofPPCGuestState(guest_VSR31); 1103 default: break; 1104 } 1105 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/ 1106 } 1107 1108 static IRExpr* getFReg ( UInt archreg ) 1109 { 1110 vassert(archreg < 32); 1111 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 ); 1112 } 1113 1114 /* Ditto, but write to a reg instead. */ 1115 static void putFReg ( UInt archreg, IRExpr* e ) 1116 { 1117 vassert(archreg < 32); 1118 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1119 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) ); 1120 } 1121 1122 /* get Decimal float value. Note, they share floating point register file. */ 1123 static IRExpr* getDReg(UInt archreg) { 1124 IRExpr *e; 1125 vassert( archreg < 32 ); 1126 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 ); 1127 return e; 1128 } 1129 1130 /* Read a floating point register pair and combine their contents into a 1131 128-bit value */ 1132 static IRExpr *getDReg_pair(UInt archreg) { 1133 IRExpr *high = getDReg( archreg ); 1134 IRExpr *low = getDReg( archreg + 1 ); 1135 1136 return binop( Iop_D64HLtoD128, high, low ); 1137 } 1138 1139 /* Ditto, but write to a reg instead. */ 1140 static void putDReg(UInt archreg, IRExpr* e) { 1141 vassert( archreg < 32 ); 1142 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 ); 1143 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1144 } 1145 1146 /* Write a 128-bit floating point value into a register pair. */ 1147 static void putDReg_pair(UInt archreg, IRExpr *e) { 1148 IRTemp low = newTemp( Ity_D64 ); 1149 IRTemp high = newTemp( Ity_D64 ); 1150 1151 vassert( archreg < 32 ); 1152 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 ); 1153 1154 assign( low, unop( Iop_D128LOtoD64, e ) ); 1155 assign( high, unop( Iop_D128HItoD64, e ) ); 1156 1157 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) ); 1158 stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) ); 1159 } 1160 1161 static Int vsxGuestRegOffset ( UInt archreg ) 1162 { 1163 vassert(archreg < 64); 1164 switch (archreg) { 1165 case 0: return offsetofPPCGuestState(guest_VSR0); 1166 case 1: return offsetofPPCGuestState(guest_VSR1); 1167 case 2: return offsetofPPCGuestState(guest_VSR2); 1168 case 3: return offsetofPPCGuestState(guest_VSR3); 1169 case 4: return offsetofPPCGuestState(guest_VSR4); 1170 case 5: return offsetofPPCGuestState(guest_VSR5); 1171 case 6: return offsetofPPCGuestState(guest_VSR6); 1172 case 7: return offsetofPPCGuestState(guest_VSR7); 1173 case 8: return offsetofPPCGuestState(guest_VSR8); 1174 case 9: return offsetofPPCGuestState(guest_VSR9); 1175 case 10: return offsetofPPCGuestState(guest_VSR10); 1176 case 11: return offsetofPPCGuestState(guest_VSR11); 1177 case 12: return offsetofPPCGuestState(guest_VSR12); 1178 case 13: return offsetofPPCGuestState(guest_VSR13); 1179 case 14: return offsetofPPCGuestState(guest_VSR14); 1180 case 15: return offsetofPPCGuestState(guest_VSR15); 1181 case 16: return offsetofPPCGuestState(guest_VSR16); 1182 case 17: return offsetofPPCGuestState(guest_VSR17); 1183 case 18: return offsetofPPCGuestState(guest_VSR18); 1184 case 19: return offsetofPPCGuestState(guest_VSR19); 1185 case 20: return offsetofPPCGuestState(guest_VSR20); 1186 case 21: return offsetofPPCGuestState(guest_VSR21); 1187 case 22: return offsetofPPCGuestState(guest_VSR22); 1188 case 23: return offsetofPPCGuestState(guest_VSR23); 1189 case 24: return offsetofPPCGuestState(guest_VSR24); 1190 case 25: return offsetofPPCGuestState(guest_VSR25); 1191 case 26: return offsetofPPCGuestState(guest_VSR26); 1192 case 27: return offsetofPPCGuestState(guest_VSR27); 1193 case 28: return offsetofPPCGuestState(guest_VSR28); 1194 case 29: return offsetofPPCGuestState(guest_VSR29); 1195 case 30: return offsetofPPCGuestState(guest_VSR30); 1196 case 31: return offsetofPPCGuestState(guest_VSR31); 1197 case 32: return offsetofPPCGuestState(guest_VSR32); 1198 case 33: return offsetofPPCGuestState(guest_VSR33); 1199 case 34: return offsetofPPCGuestState(guest_VSR34); 1200 case 35: return offsetofPPCGuestState(guest_VSR35); 1201 case 36: return offsetofPPCGuestState(guest_VSR36); 1202 case 37: return offsetofPPCGuestState(guest_VSR37); 1203 case 38: return offsetofPPCGuestState(guest_VSR38); 1204 case 39: return offsetofPPCGuestState(guest_VSR39); 1205 case 40: return offsetofPPCGuestState(guest_VSR40); 1206 case 41: return offsetofPPCGuestState(guest_VSR41); 1207 case 42: return offsetofPPCGuestState(guest_VSR42); 1208 case 43: return offsetofPPCGuestState(guest_VSR43); 1209 case 44: return offsetofPPCGuestState(guest_VSR44); 1210 case 45: return offsetofPPCGuestState(guest_VSR45); 1211 case 46: return offsetofPPCGuestState(guest_VSR46); 1212 case 47: return offsetofPPCGuestState(guest_VSR47); 1213 case 48: return offsetofPPCGuestState(guest_VSR48); 1214 case 49: return offsetofPPCGuestState(guest_VSR49); 1215 case 50: return offsetofPPCGuestState(guest_VSR50); 1216 case 51: return offsetofPPCGuestState(guest_VSR51); 1217 case 52: return offsetofPPCGuestState(guest_VSR52); 1218 case 53: return offsetofPPCGuestState(guest_VSR53); 1219 case 54: return offsetofPPCGuestState(guest_VSR54); 1220 case 55: return offsetofPPCGuestState(guest_VSR55); 1221 case 56: return offsetofPPCGuestState(guest_VSR56); 1222 case 57: return offsetofPPCGuestState(guest_VSR57); 1223 case 58: return offsetofPPCGuestState(guest_VSR58); 1224 case 59: return offsetofPPCGuestState(guest_VSR59); 1225 case 60: return offsetofPPCGuestState(guest_VSR60); 1226 case 61: return offsetofPPCGuestState(guest_VSR61); 1227 case 62: return offsetofPPCGuestState(guest_VSR62); 1228 case 63: return offsetofPPCGuestState(guest_VSR63); 1229 default: break; 1230 } 1231 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/ 1232 } 1233 1234 /* Vector registers are mapped to VSX registers[32..63]. */ 1235 static Int vectorGuestRegOffset ( UInt archreg ) 1236 { 1237 vassert(archreg < 32); 1238 1239 switch (archreg) { 1240 case 0: return offsetofPPCGuestState(guest_VSR32); 1241 case 1: return offsetofPPCGuestState(guest_VSR33); 1242 case 2: return offsetofPPCGuestState(guest_VSR34); 1243 case 3: return offsetofPPCGuestState(guest_VSR35); 1244 case 4: return offsetofPPCGuestState(guest_VSR36); 1245 case 5: return offsetofPPCGuestState(guest_VSR37); 1246 case 6: return offsetofPPCGuestState(guest_VSR38); 1247 case 7: return offsetofPPCGuestState(guest_VSR39); 1248 case 8: return offsetofPPCGuestState(guest_VSR40); 1249 case 9: return offsetofPPCGuestState(guest_VSR41); 1250 case 10: return offsetofPPCGuestState(guest_VSR42); 1251 case 11: return offsetofPPCGuestState(guest_VSR43); 1252 case 12: return offsetofPPCGuestState(guest_VSR44); 1253 case 13: return offsetofPPCGuestState(guest_VSR45); 1254 case 14: return offsetofPPCGuestState(guest_VSR46); 1255 case 15: return offsetofPPCGuestState(guest_VSR47); 1256 case 16: return offsetofPPCGuestState(guest_VSR48); 1257 case 17: return offsetofPPCGuestState(guest_VSR49); 1258 case 18: return offsetofPPCGuestState(guest_VSR50); 1259 case 19: return offsetofPPCGuestState(guest_VSR51); 1260 case 20: return offsetofPPCGuestState(guest_VSR52); 1261 case 21: return offsetofPPCGuestState(guest_VSR53); 1262 case 22: return offsetofPPCGuestState(guest_VSR54); 1263 case 23: return offsetofPPCGuestState(guest_VSR55); 1264 case 24: return offsetofPPCGuestState(guest_VSR56); 1265 case 25: return offsetofPPCGuestState(guest_VSR57); 1266 case 26: return offsetofPPCGuestState(guest_VSR58); 1267 case 27: return offsetofPPCGuestState(guest_VSR59); 1268 case 28: return offsetofPPCGuestState(guest_VSR60); 1269 case 29: return offsetofPPCGuestState(guest_VSR61); 1270 case 30: return offsetofPPCGuestState(guest_VSR62); 1271 case 31: return offsetofPPCGuestState(guest_VSR63); 1272 default: break; 1273 } 1274 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/ 1275 } 1276 1277 static IRExpr* getVReg ( UInt archreg ) 1278 { 1279 vassert(archreg < 32); 1280 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 ); 1281 } 1282 1283 /* Ditto, but write to a reg instead. */ 1284 static void putVReg ( UInt archreg, IRExpr* e ) 1285 { 1286 vassert(archreg < 32); 1287 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1288 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1289 } 1290 1291 /* Get contents of VSX guest register */ 1292 static IRExpr* getVSReg ( UInt archreg ) 1293 { 1294 vassert(archreg < 64); 1295 return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 ); 1296 } 1297 1298 /* Ditto, but write to a VSX reg instead. */ 1299 static void putVSReg ( UInt archreg, IRExpr* e ) 1300 { 1301 vassert(archreg < 64); 1302 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1303 stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) ); 1304 } 1305 1306 1307 static Int guestCR321offset ( UInt cr ) 1308 { 1309 switch (cr) { 1310 case 0: return offsetofPPCGuestState(guest_CR0_321 ); 1311 case 1: return offsetofPPCGuestState(guest_CR1_321 ); 1312 case 2: return offsetofPPCGuestState(guest_CR2_321 ); 1313 case 3: return offsetofPPCGuestState(guest_CR3_321 ); 1314 case 4: return offsetofPPCGuestState(guest_CR4_321 ); 1315 case 5: return offsetofPPCGuestState(guest_CR5_321 ); 1316 case 6: return offsetofPPCGuestState(guest_CR6_321 ); 1317 case 7: return offsetofPPCGuestState(guest_CR7_321 ); 1318 default: vpanic("guestCR321offset(ppc)"); 1319 } 1320 } 1321 1322 static Int guestCR0offset ( UInt cr ) 1323 { 1324 switch (cr) { 1325 case 0: return offsetofPPCGuestState(guest_CR0_0 ); 1326 case 1: return offsetofPPCGuestState(guest_CR1_0 ); 1327 case 2: return offsetofPPCGuestState(guest_CR2_0 ); 1328 case 3: return offsetofPPCGuestState(guest_CR3_0 ); 1329 case 4: return offsetofPPCGuestState(guest_CR4_0 ); 1330 case 5: return offsetofPPCGuestState(guest_CR5_0 ); 1331 case 6: return offsetofPPCGuestState(guest_CR6_0 ); 1332 case 7: return offsetofPPCGuestState(guest_CR7_0 ); 1333 default: vpanic("guestCR3offset(ppc)"); 1334 } 1335 } 1336 1337 /* Generate an IR sequence to do a popcount operation on the supplied 1338 IRTemp, and return a new IRTemp holding the result. 'ty' may be 1339 Ity_I32 or Ity_I64 only. */ 1340 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, Bool byte_count ) 1341 { 1342 Int i, shift[6], max; 1343 IRTemp mask[6]; 1344 IRTemp old = IRTemp_INVALID; 1345 IRTemp nyu = IRTemp_INVALID; 1346 1347 vassert(ty == Ity_I64 || ty == Ity_I32); 1348 1349 if (ty == Ity_I32) { 1350 if (byte_count) 1351 /* Return the population count across each byte not across the entire 1352 * 32-bit value. Stop after third iteration. 1353 */ 1354 max = 3; 1355 else 1356 max = 5; 1357 1358 for (i = 0; i < 5; i++) { 1359 mask[i] = newTemp(ty); 1360 shift[i] = 1 << i; 1361 } 1362 assign(mask[0], mkU32(0x55555555)); 1363 assign(mask[1], mkU32(0x33333333)); 1364 assign(mask[2], mkU32(0x0F0F0F0F)); 1365 assign(mask[3], mkU32(0x00FF00FF)); 1366 assign(mask[4], mkU32(0x0000FFFF)); 1367 old = src; 1368 for (i = 0; i < max; i++) { 1369 nyu = newTemp(ty); 1370 assign(nyu, 1371 binop(Iop_Add32, 1372 binop(Iop_And32, 1373 mkexpr(old), 1374 mkexpr(mask[i])), 1375 binop(Iop_And32, 1376 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1377 mkexpr(mask[i])))); 1378 old = nyu; 1379 } 1380 return nyu; 1381 } 1382 // else, ty == Ity_I64 1383 if (byte_count) 1384 /* Return the population count across each byte not across the entire 1385 * 64-bit value. Stop after third iteration. 1386 */ 1387 max = 3; 1388 else 1389 max = 6; 1390 1391 for (i = 0; i < 6; i++) { 1392 mask[i] = newTemp( Ity_I64 ); 1393 shift[i] = 1 << i; 1394 } 1395 assign( mask[0], mkU64( 0x5555555555555555ULL ) ); 1396 assign( mask[1], mkU64( 0x3333333333333333ULL ) ); 1397 assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) ); 1398 assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) ); 1399 assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) ); 1400 assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) ); 1401 old = src; 1402 for (i = 0; i < max; i++) { 1403 nyu = newTemp( Ity_I64 ); 1404 assign( nyu, 1405 binop( Iop_Add64, 1406 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ), 1407 binop( Iop_And64, 1408 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ), 1409 mkexpr( mask[i] ) ) ) ); 1410 old = nyu; 1411 } 1412 return nyu; 1413 } 1414 1415 1416 // ROTL(src32/64, rot_amt5/6) 1417 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src, 1418 IRExpr* rot_amt ) 1419 { 1420 IRExpr *mask, *rot; 1421 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8); 1422 1423 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) { 1424 // rot = (src << rot_amt) | (src >> (64-rot_amt)) 1425 mask = binop(Iop_And8, rot_amt, mkU8(63)); 1426 rot = binop(Iop_Or64, 1427 binop(Iop_Shl64, src, mask), 1428 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask))); 1429 } else { 1430 // rot = (src << rot_amt) | (src >> (32-rot_amt)) 1431 mask = binop(Iop_And8, rot_amt, mkU8(31)); 1432 rot = binop(Iop_Or32, 1433 binop(Iop_Shl32, src, mask), 1434 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask))); 1435 } 1436 /* Note: the MuxOX is not merely an optimisation; it's needed 1437 because otherwise the Shr is a shift by the word size when 1438 mask denotes zero. For rotates by immediates, a lot of 1439 this junk gets folded out. */ 1440 return IRExpr_Mux0X( mask, /* zero rotate */ src, 1441 /* non-zero rotate */ rot ); 1442 } 1443 1444 /* Standard effective address calc: (rA + rB) */ 1445 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB ) 1446 { 1447 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1448 vassert(rA < 32); 1449 vassert(rB < 32); 1450 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB)); 1451 } 1452 1453 /* Standard effective address calc: (rA + simm) */ 1454 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 ) 1455 { 1456 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1457 vassert(rA < 32); 1458 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), 1459 mkSzExtendS16(ty, simm16)); 1460 } 1461 1462 /* Standard effective address calc: (rA|0) */ 1463 static IRExpr* ea_rAor0 ( UInt rA ) 1464 { 1465 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1466 vassert(rA < 32); 1467 if (rA == 0) { 1468 return mkSzImm(ty, 0); 1469 } else { 1470 return getIReg(rA); 1471 } 1472 } 1473 1474 /* Standard effective address calc: (rA|0) + rB */ 1475 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB ) 1476 { 1477 vassert(rA < 32); 1478 vassert(rB < 32); 1479 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB ); 1480 } 1481 1482 /* Standard effective address calc: (rA|0) + simm16 */ 1483 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 ) 1484 { 1485 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1486 vassert(rA < 32); 1487 if (rA == 0) { 1488 return mkSzExtendS16(ty, simm16); 1489 } else { 1490 return ea_rA_simm( rA, simm16 ); 1491 } 1492 } 1493 1494 1495 /* Align effective address */ 1496 static IRExpr* addr_align( IRExpr* addr, UChar align ) 1497 { 1498 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1499 Long mask; 1500 switch (align) { 1501 case 1: return addr; // byte aligned 1502 case 2: mask = ((Long)-1) << 1; break; // half-word aligned 1503 case 4: mask = ((Long)-1) << 2; break; // word aligned 1504 case 16: mask = ((Long)-1) << 4; break; // quad-word aligned 1505 default: 1506 vex_printf("addr_align: align = %u\n", align); 1507 vpanic("addr_align(ppc)"); 1508 } 1509 1510 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty); 1511 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) ); 1512 } 1513 1514 1515 /* Exit the trace if ADDR (intended to be a guest memory address) is 1516 not ALIGN-aligned, generating a request for a SIGBUS followed by a 1517 restart of the current insn. */ 1518 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align ) 1519 { 1520 vassert(align == 4 || align == 8); 1521 if (mode64) { 1522 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64); 1523 stmt( 1524 IRStmt_Exit( 1525 binop(Iop_CmpNE64, 1526 binop(Iop_And64, mkexpr(addr), mkU64(align-1)), 1527 mkU64(0)), 1528 Ijk_SigBUS, 1529 IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA 1530 ) 1531 ); 1532 } else { 1533 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32); 1534 stmt( 1535 IRStmt_Exit( 1536 binop(Iop_CmpNE32, 1537 binop(Iop_And32, mkexpr(addr), mkU32(align-1)), 1538 mkU32(0)), 1539 Ijk_SigBUS, 1540 IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA 1541 ) 1542 ); 1543 } 1544 } 1545 1546 1547 /* Generate AbiHints which mark points at which the ELF or PowerOpen 1548 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some 1549 N) becomes undefined. That is at function calls and returns. ELF 1550 ppc32 doesn't have this "feature" (how fortunate for it). nia is 1551 the address of the next instruction to be executed. 1552 */ 1553 static void make_redzone_AbiHint ( VexAbiInfo* vbi, 1554 IRTemp nia, HChar* who ) 1555 { 1556 Int szB = vbi->guest_stack_redzone_size; 1557 if (0) vex_printf("AbiHint: %s\n", who); 1558 vassert(szB >= 0); 1559 if (szB > 0) { 1560 if (mode64) { 1561 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64); 1562 stmt( IRStmt_AbiHint( 1563 binop(Iop_Sub64, getIReg(1), mkU64(szB)), 1564 szB, 1565 mkexpr(nia) 1566 )); 1567 } else { 1568 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32); 1569 stmt( IRStmt_AbiHint( 1570 binop(Iop_Sub32, getIReg(1), mkU32(szB)), 1571 szB, 1572 mkexpr(nia) 1573 )); 1574 } 1575 } 1576 } 1577 1578 1579 /*------------------------------------------------------------*/ 1580 /*--- Helpers for condition codes. ---*/ 1581 /*------------------------------------------------------------*/ 1582 1583 /* Condition register layout. 1584 1585 In the hardware, CR is laid out like this. The leftmost end is the 1586 most significant bit in the register; however the IBM documentation 1587 numbers the bits backwards for some reason. 1588 1589 CR0 CR1 .......... CR6 CR7 1590 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 1591 31 28 3 0 (normal bit numbering) 1592 1593 Each CR field is 4 bits: [<,>,==,SO] 1594 1595 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. 1596 1597 Indexing from BI to guest state: 1598 1599 let n = BI / 4 1600 off = BI % 4 1601 this references CR n: 1602 1603 off==0 -> guest_CRn_321 >> 3 1604 off==1 -> guest_CRn_321 >> 2 1605 off==2 -> guest_CRn_321 >> 1 1606 off==3 -> guest_CRn_SO 1607 1608 Bear in mind the only significant bit in guest_CRn_SO is bit 0 1609 (normal notation) and in guest_CRn_321 the significant bits are 1610 3, 2 and 1 (normal notation). 1611 */ 1612 1613 static void putCR321 ( UInt cr, IRExpr* e ) 1614 { 1615 vassert(cr < 8); 1616 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1617 stmt( IRStmt_Put(guestCR321offset(cr), e) ); 1618 } 1619 1620 static void putCR0 ( UInt cr, IRExpr* e ) 1621 { 1622 vassert(cr < 8); 1623 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1624 stmt( IRStmt_Put(guestCR0offset(cr), e) ); 1625 } 1626 1627 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) 1628 { 1629 vassert(cr < 8); 1630 return IRExpr_Get(guestCR0offset(cr), Ity_I8); 1631 } 1632 1633 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) 1634 { 1635 vassert(cr < 8); 1636 return IRExpr_Get(guestCR321offset(cr), Ity_I8); 1637 } 1638 1639 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1640 return it at the bottom of an I32; the top 31 bits are guaranteed 1641 to be zero. */ 1642 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi ) 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 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1652 } else { 1653 /* Fetch the <, > or == bit for this CR field */ 1654 return binop( Iop_And32, 1655 binop( Iop_Shr32, 1656 unop(Iop_8Uto32, getCR321(n)), 1657 mkU8(toUChar(3-off)) ), 1658 mkU32(1) ); 1659 } 1660 } 1661 1662 /* Dually, write the least significant bit of BIT to the specified CR 1663 bit. Indexing as per getCRbit. */ 1664 static void putCRbit ( UInt bi, IRExpr* bit ) 1665 { 1666 UInt n, off; 1667 IRExpr* safe; 1668 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32); 1669 safe = binop(Iop_And32, bit, mkU32(1)); 1670 n = bi / 4; 1671 off = bi % 4; 1672 vassert(bi < 32); 1673 if (off == 3) { 1674 /* This is the SO bit for this CR field */ 1675 putCR0(n, unop(Iop_32to8, safe)); 1676 } else { 1677 off = 3 - off; 1678 vassert(off == 1 || off == 2 || off == 3); 1679 putCR321( 1680 n, 1681 unop( Iop_32to8, 1682 binop( Iop_Or32, 1683 /* old value with field masked out */ 1684 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)), 1685 mkU32(~(1 << off))), 1686 /* new value in the right place */ 1687 binop(Iop_Shl32, safe, mkU8(toUChar(off))) 1688 ) 1689 ) 1690 ); 1691 } 1692 } 1693 1694 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1695 return it somewhere in an I32; it does not matter where, but 1696 whichever bit it is, all other bits are guaranteed to be zero. In 1697 other words, the I32-typed expression will be zero if the bit is 1698 zero and nonzero if the bit is 1. Write into *where the index 1699 of where the bit will be. */ 1700 1701 static 1702 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ) 1703 { 1704 UInt n = bi / 4; 1705 UInt off = bi % 4; 1706 vassert(bi < 32); 1707 if (off == 3) { 1708 /* Fetch the SO bit for this CR field */ 1709 /* Note: And32 is redundant paranoia iff guest state only has 0 1710 or 1 in that slot. */ 1711 *where = 0; 1712 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1713 } else { 1714 /* Fetch the <, > or == bit for this CR field */ 1715 *where = 3-off; 1716 return binop( Iop_And32, 1717 unop(Iop_8Uto32, getCR321(n)), 1718 mkU32(1 << (3-off)) ); 1719 } 1720 } 1721 1722 /* Set the CR0 flags following an arithmetic operation. 1723 (Condition Register CR0 Field Definition, PPC32 p60) 1724 */ 1725 static IRExpr* getXER_SO ( void ); 1726 static void set_CR0 ( IRExpr* result ) 1727 { 1728 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 || 1729 typeOfIRExpr(irsb->tyenv,result) == Ity_I64); 1730 if (mode64) { 1731 putCR321( 0, unop(Iop_64to8, 1732 binop(Iop_CmpORD64S, result, mkU64(0))) ); 1733 } else { 1734 putCR321( 0, unop(Iop_32to8, 1735 binop(Iop_CmpORD32S, result, mkU32(0))) ); 1736 } 1737 putCR0( 0, getXER_SO() ); 1738 } 1739 1740 1741 /* Set the CR6 flags following an AltiVec compare operation. 1742 * NOTE: This also works for VSX single-precision compares. 1743 * */ 1744 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) 1745 { 1746 /* CR6[0:3] = {all_ones, 0, all_zeros, 0} 1747 all_ones = (v[0] && v[1] && v[2] && v[3]) 1748 all_zeros = ~(v[0] || v[1] || v[2] || v[3]) 1749 */ 1750 IRTemp v0 = newTemp(Ity_V128); 1751 IRTemp v1 = newTemp(Ity_V128); 1752 IRTemp v2 = newTemp(Ity_V128); 1753 IRTemp v3 = newTemp(Ity_V128); 1754 IRTemp rOnes = newTemp(Ity_I8); 1755 IRTemp rZeros = newTemp(Ity_I8); 1756 1757 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128); 1758 1759 assign( v0, result ); 1760 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); 1761 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); 1762 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); 1763 1764 assign( rZeros, unop(Iop_1Uto8, 1765 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1766 unop(Iop_Not32, 1767 unop(Iop_V128to32, 1768 binop(Iop_OrV128, 1769 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), 1770 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) 1771 ))) ); 1772 1773 if (test_all_ones) { 1774 assign( rOnes, unop(Iop_1Uto8, 1775 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1776 unop(Iop_V128to32, 1777 binop(Iop_AndV128, 1778 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), 1779 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))) 1780 ))) ); 1781 putCR321( 6, binop(Iop_Or8, 1782 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), 1783 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); 1784 } else { 1785 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); 1786 } 1787 putCR0( 6, mkU8(0) ); 1788 } 1789 1790 1791 1792 /*------------------------------------------------------------*/ 1793 /*--- Helpers for XER flags. ---*/ 1794 /*------------------------------------------------------------*/ 1795 1796 static void putXER_SO ( IRExpr* e ) 1797 { 1798 IRExpr* so; 1799 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1800 so = binop(Iop_And8, e, mkU8(1)); 1801 stmt( IRStmt_Put( OFFB_XER_SO, so ) ); 1802 } 1803 1804 static void putXER_OV ( IRExpr* e ) 1805 { 1806 IRExpr* ov; 1807 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1808 ov = binop(Iop_And8, e, mkU8(1)); 1809 stmt( IRStmt_Put( OFFB_XER_OV, ov ) ); 1810 } 1811 1812 static void putXER_CA ( IRExpr* e ) 1813 { 1814 IRExpr* ca; 1815 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1816 ca = binop(Iop_And8, e, mkU8(1)); 1817 stmt( IRStmt_Put( OFFB_XER_CA, ca ) ); 1818 } 1819 1820 static void putXER_BC ( IRExpr* e ) 1821 { 1822 IRExpr* bc; 1823 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1824 bc = binop(Iop_And8, e, mkU8(0x7F)); 1825 stmt( IRStmt_Put( OFFB_XER_BC, bc ) ); 1826 } 1827 1828 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) 1829 { 1830 return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); 1831 } 1832 1833 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void ) 1834 { 1835 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) ); 1836 } 1837 1838 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ) 1839 { 1840 return IRExpr_Get( OFFB_XER_OV, Ity_I8 ); 1841 } 1842 1843 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void ) 1844 { 1845 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) ); 1846 } 1847 1848 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void ) 1849 { 1850 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 ); 1851 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 1852 } 1853 1854 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ) 1855 { 1856 return IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 1857 } 1858 1859 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void ) 1860 { 1861 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 1862 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) ); 1863 } 1864 1865 1866 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and 1867 %XER.SO accordingly. */ 1868 1869 static void set_XER_OV_32( UInt op, IRExpr* res, 1870 IRExpr* argL, IRExpr* argR ) 1871 { 1872 IRTemp t64; 1873 IRExpr* xer_ov; 1874 vassert(op < PPCG_FLAG_OP_NUMBER); 1875 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 1876 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 1877 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 1878 1879 # define INT32_MIN 0x80000000 1880 1881 # define XOR2(_aa,_bb) \ 1882 binop(Iop_Xor32,(_aa),(_bb)) 1883 1884 # define XOR3(_cc,_dd,_ee) \ 1885 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee)) 1886 1887 # define AND3(_ff,_gg,_hh) \ 1888 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh)) 1889 1890 #define NOT(_jj) \ 1891 unop(Iop_Not32, (_jj)) 1892 1893 switch (op) { 1894 case /* 0 */ PPCG_FLAG_OP_ADD: 1895 case /* 1 */ PPCG_FLAG_OP_ADDE: 1896 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */ 1897 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 1898 xer_ov 1899 = AND3( XOR3(argL,argR,mkU32(-1)), 1900 XOR2(argL,res), 1901 mkU32(INT32_MIN) ); 1902 /* xer_ov can only be 0 or 1<<31 */ 1903 xer_ov 1904 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 1905 break; 1906 1907 case /* 2 */ PPCG_FLAG_OP_DIVW: 1908 /* (argL == INT32_MIN && argR == -1) || argR == 0 */ 1909 xer_ov 1910 = mkOR1( 1911 mkAND1( 1912 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)), 1913 binop(Iop_CmpEQ32, argR, mkU32(-1)) 1914 ), 1915 binop(Iop_CmpEQ32, argR, mkU32(0) ) 1916 ); 1917 xer_ov 1918 = unop(Iop_1Uto32, xer_ov); 1919 break; 1920 1921 case /* 3 */ PPCG_FLAG_OP_DIVWU: 1922 /* argR == 0 */ 1923 xer_ov 1924 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); 1925 break; 1926 1927 case /* 4 */ PPCG_FLAG_OP_MULLW: 1928 /* OV true if result can't be represented in 32 bits 1929 i.e sHi != sign extension of sLo */ 1930 t64 = newTemp(Ity_I64); 1931 assign( t64, binop(Iop_MullS32, argL, argR) ); 1932 xer_ov 1933 = binop( Iop_CmpNE32, 1934 unop(Iop_64HIto32, mkexpr(t64)), 1935 binop( Iop_Sar32, 1936 unop(Iop_64to32, mkexpr(t64)), 1937 mkU8(31)) 1938 ); 1939 xer_ov 1940 = unop(Iop_1Uto32, xer_ov); 1941 break; 1942 1943 case /* 5 */ PPCG_FLAG_OP_NEG: 1944 /* argL == INT32_MIN */ 1945 xer_ov 1946 = unop( Iop_1Uto32, 1947 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); 1948 break; 1949 1950 case /* 6 */ PPCG_FLAG_OP_SUBF: 1951 case /* 7 */ PPCG_FLAG_OP_SUBFC: 1952 case /* 8 */ PPCG_FLAG_OP_SUBFE: 1953 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */ 1954 xer_ov 1955 = AND3( XOR3(NOT(argL),argR,mkU32(-1)), 1956 XOR2(NOT(argL),res), 1957 mkU32(INT32_MIN) ); 1958 /* xer_ov can only be 0 or 1<<31 */ 1959 xer_ov 1960 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 1961 break; 1962 1963 case PPCG_FLAG_OP_DIVWEU: 1964 xer_ov 1965 = binop( Iop_Or32, 1966 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 1967 unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) ); 1968 break; 1969 1970 case PPCG_FLAG_OP_DIVWE: 1971 1972 /* If argR == 0 of if the result cannot fit in the 32-bit destination register, 1973 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero, 1974 * an overflow is implied. 1975 */ 1976 xer_ov = binop( Iop_Or32, 1977 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 1978 unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ), 1979 mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ), 1980 binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) ); 1981 break; 1982 1983 1984 1985 default: 1986 vex_printf("set_XER_OV: op = %u\n", op); 1987 vpanic("set_XER_OV(ppc)"); 1988 } 1989 1990 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 1991 putXER_OV( unop(Iop_32to8, xer_ov) ); 1992 1993 /* Update the summary overflow */ 1994 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 1995 1996 # undef INT32_MIN 1997 # undef AND3 1998 # undef XOR3 1999 # undef XOR2 2000 # undef NOT 2001 } 2002 2003 static void set_XER_OV_64( UInt op, IRExpr* res, 2004 IRExpr* argL, IRExpr* argR ) 2005 { 2006 IRExpr* xer_ov; 2007 vassert(op < PPCG_FLAG_OP_NUMBER); 2008 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2009 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2010 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2011 2012 # define INT64_MIN 0x8000000000000000ULL 2013 2014 # define XOR2(_aa,_bb) \ 2015 binop(Iop_Xor64,(_aa),(_bb)) 2016 2017 # define XOR3(_cc,_dd,_ee) \ 2018 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee)) 2019 2020 # define AND3(_ff,_gg,_hh) \ 2021 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh)) 2022 2023 #define NOT(_jj) \ 2024 unop(Iop_Not64, (_jj)) 2025 2026 switch (op) { 2027 case /* 0 */ PPCG_FLAG_OP_ADD: 2028 case /* 1 */ PPCG_FLAG_OP_ADDE: 2029 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */ 2030 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2031 xer_ov 2032 = AND3( XOR3(argL,argR,mkU64(-1)), 2033 XOR2(argL,res), 2034 mkU64(INT64_MIN) ); 2035 /* xer_ov can only be 0 or 1<<63 */ 2036 xer_ov 2037 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2038 break; 2039 2040 case /* 2 */ PPCG_FLAG_OP_DIVW: 2041 /* (argL == INT64_MIN && argR == -1) || argR == 0 */ 2042 xer_ov 2043 = mkOR1( 2044 mkAND1( 2045 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)), 2046 binop(Iop_CmpEQ64, argR, mkU64(-1)) 2047 ), 2048 binop(Iop_CmpEQ64, argR, mkU64(0) ) 2049 ); 2050 break; 2051 2052 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2053 /* argR == 0 */ 2054 xer_ov 2055 = binop(Iop_CmpEQ64, argR, mkU64(0)); 2056 break; 2057 2058 case /* 4 */ PPCG_FLAG_OP_MULLW: { 2059 /* OV true if result can't be represented in 64 bits 2060 i.e sHi != sign extension of sLo */ 2061 xer_ov 2062 = binop( Iop_CmpNE32, 2063 unop(Iop_64HIto32, res), 2064 binop( Iop_Sar32, 2065 unop(Iop_64to32, res), 2066 mkU8(31)) 2067 ); 2068 break; 2069 } 2070 2071 case /* 5 */ PPCG_FLAG_OP_NEG: 2072 /* argL == INT64_MIN */ 2073 xer_ov 2074 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)); 2075 break; 2076 2077 case /* 6 */ PPCG_FLAG_OP_SUBF: 2078 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2079 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2080 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */ 2081 xer_ov 2082 = AND3( XOR3(NOT(argL),argR,mkU64(-1)), 2083 XOR2(NOT(argL),res), 2084 mkU64(INT64_MIN) ); 2085 /* xer_ov can only be 0 or 1<<63 */ 2086 xer_ov 2087 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2088 break; 2089 2090 case PPCG_FLAG_OP_DIVDE: 2091 2092 /* If argR == 0, we must set the OV bit. But there's another condition 2093 * where we can get overflow set for divde . . . when the 2094 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND 2095 * both dividend and divisor are non-zero, it implies an overflow. 2096 */ 2097 xer_ov 2098 = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2099 mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ), 2100 mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ), 2101 binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) ); 2102 break; 2103 2104 case PPCG_FLAG_OP_DIVDEU: 2105 /* If argR == 0 or if argL >= argR, set OV. */ 2106 xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2107 binop( Iop_CmpLE64U, argR, argL ) ); 2108 break; 2109 2110 default: 2111 vex_printf("set_XER_OV: op = %u\n", op); 2112 vpanic("set_XER_OV(ppc64)"); 2113 } 2114 2115 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2116 putXER_OV( unop(Iop_1Uto8, xer_ov) ); 2117 2118 /* Update the summary overflow */ 2119 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2120 2121 # undef INT64_MIN 2122 # undef AND3 2123 # undef XOR3 2124 # undef XOR2 2125 # undef NOT 2126 } 2127 2128 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res, 2129 IRExpr* argL, IRExpr* argR ) 2130 { 2131 if (ty == Ity_I32) 2132 set_XER_OV_32( op, res, argL, argR ); 2133 else 2134 set_XER_OV_64( op, res, argL, argR ); 2135 } 2136 2137 2138 2139 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA 2140 value being OLDCA. Set %XER.CA accordingly. */ 2141 2142 static void set_XER_CA_32 ( UInt op, IRExpr* res, 2143 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2144 { 2145 IRExpr* xer_ca; 2146 vassert(op < PPCG_FLAG_OP_NUMBER); 2147 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2148 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2149 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2150 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32); 2151 2152 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2153 seems reasonable given that it's always generated by 2154 getXER_CA32(), which masks it accordingly. In any case it being 2155 0 or 1 is an invariant of the ppc guest state representation; 2156 if it has any other value, that invariant has been violated. */ 2157 2158 switch (op) { 2159 case /* 0 */ PPCG_FLAG_OP_ADD: 2160 /* res <u argL */ 2161 xer_ca 2162 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); 2163 break; 2164 2165 case /* 1 */ PPCG_FLAG_OP_ADDE: 2166 /* res <u argL || (old_ca==1 && res==argL) */ 2167 xer_ca 2168 = mkOR1( 2169 binop(Iop_CmpLT32U, res, argL), 2170 mkAND1( 2171 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2172 binop(Iop_CmpEQ32, res, argL) 2173 ) 2174 ); 2175 xer_ca 2176 = unop(Iop_1Uto32, xer_ca); 2177 break; 2178 2179 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2180 /* res <u argR || (old_ca==1 && res==argR) */ 2181 xer_ca 2182 = mkOR1( 2183 binop(Iop_CmpLT32U, res, argR), 2184 mkAND1( 2185 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2186 binop(Iop_CmpEQ32, res, argR) 2187 ) 2188 ); 2189 xer_ca 2190 = unop(Iop_1Uto32, xer_ca); 2191 break; 2192 2193 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2194 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2195 /* res <=u argR */ 2196 xer_ca 2197 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); 2198 break; 2199 2200 case /* 10 */ PPCG_FLAG_OP_SRAW: 2201 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2202 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2203 bit of argL. */ 2204 /* This term valid for shift amount < 32 only */ 2205 xer_ca 2206 = binop( 2207 Iop_And32, 2208 binop(Iop_Sar32, argL, mkU8(31)), 2209 binop( Iop_And32, 2210 argL, 2211 binop( Iop_Sub32, 2212 binop(Iop_Shl32, mkU32(1), 2213 unop(Iop_32to8,argR)), 2214 mkU32(1) ) 2215 ) 2216 ); 2217 xer_ca 2218 = IRExpr_Mux0X( 2219 /* shift amt > 31 ? */ 2220 unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)), 2221 /* no -- be like srawi */ 2222 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))), 2223 /* yes -- get sign bit of argL */ 2224 binop(Iop_Shr32, argL, mkU8(31)) 2225 ); 2226 break; 2227 2228 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2229 /* xer_ca is 1 iff src was negative and bits_shifted_out != 2230 0. Since the shift amount is known to be in the range 2231 0 .. 31 inclusive the following seems viable: 2232 xer.ca == 1 iff the following is nonzero: 2233 (argL >>s 31) -- either all 0s or all 1s 2234 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2235 xer_ca 2236 = binop( 2237 Iop_And32, 2238 binop(Iop_Sar32, argL, mkU8(31)), 2239 binop( Iop_And32, 2240 argL, 2241 binop( Iop_Sub32, 2242 binop(Iop_Shl32, mkU32(1), 2243 unop(Iop_32to8,argR)), 2244 mkU32(1) ) 2245 ) 2246 ); 2247 xer_ca 2248 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); 2249 break; 2250 2251 default: 2252 vex_printf("set_XER_CA: op = %u\n", op); 2253 vpanic("set_XER_CA(ppc)"); 2254 } 2255 2256 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2257 putXER_CA( unop(Iop_32to8, xer_ca) ); 2258 } 2259 2260 static void set_XER_CA_64 ( UInt op, IRExpr* res, 2261 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2262 { 2263 IRExpr* xer_ca; 2264 vassert(op < PPCG_FLAG_OP_NUMBER); 2265 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2266 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2267 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2268 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64); 2269 2270 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2271 seems reasonable given that it's always generated by 2272 getXER_CA32(), which masks it accordingly. In any case it being 2273 0 or 1 is an invariant of the ppc guest state representation; 2274 if it has any other value, that invariant has been violated. */ 2275 2276 switch (op) { 2277 case /* 0 */ PPCG_FLAG_OP_ADD: 2278 /* res <u argL */ 2279 xer_ca 2280 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL)); 2281 break; 2282 2283 case /* 1 */ PPCG_FLAG_OP_ADDE: 2284 /* res <u argL || (old_ca==1 && res==argL) */ 2285 xer_ca 2286 = mkOR1( 2287 binop(Iop_CmpLT64U, res, argL), 2288 mkAND1( 2289 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2290 binop(Iop_CmpEQ64, res, argL) 2291 ) 2292 ); 2293 xer_ca 2294 = unop(Iop_1Uto32, xer_ca); 2295 break; 2296 2297 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2298 /* res <u argR || (old_ca==1 && res==argR) */ 2299 xer_ca 2300 = mkOR1( 2301 binop(Iop_CmpLT64U, res, argR), 2302 mkAND1( 2303 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2304 binop(Iop_CmpEQ64, res, argR) 2305 ) 2306 ); 2307 xer_ca 2308 = unop(Iop_1Uto32, xer_ca); 2309 break; 2310 2311 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2312 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2313 /* res <=u argR */ 2314 xer_ca 2315 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR)); 2316 break; 2317 2318 2319 case /* 10 */ PPCG_FLAG_OP_SRAW: 2320 /* The shift amount is guaranteed to be in 0 .. 31 inclusive. 2321 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2322 bit of argL. */ 2323 /* This term valid for shift amount < 31 only */ 2324 2325 xer_ca 2326 = binop( 2327 Iop_And64, 2328 binop(Iop_Sar64, argL, mkU8(31)), 2329 binop( Iop_And64, 2330 argL, 2331 binop( Iop_Sub64, 2332 binop(Iop_Shl64, mkU64(1), 2333 unop(Iop_64to8,argR)), 2334 mkU64(1) ) 2335 ) 2336 ); 2337 xer_ca 2338 = IRExpr_Mux0X( 2339 /* shift amt > 31 ? */ 2340 unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(31), argR)), 2341 /* no -- be like srawi */ 2342 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))), 2343 /* yes -- get sign bit of argL */ 2344 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))) 2345 ); 2346 break; 2347 2348 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2349 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2350 Since the shift amount is known to be in the range 0 .. 31 2351 inclusive the following seems viable: 2352 xer.ca == 1 iff the following is nonzero: 2353 (argL >>s 31) -- either all 0s or all 1s 2354 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2355 2356 xer_ca 2357 = binop( 2358 Iop_And64, 2359 binop(Iop_Sar64, argL, mkU8(31)), 2360 binop( Iop_And64, 2361 argL, 2362 binop( Iop_Sub64, 2363 binop(Iop_Shl64, mkU64(1), 2364 unop(Iop_64to8,argR)), 2365 mkU64(1) ) 2366 ) 2367 ); 2368 xer_ca 2369 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2370 break; 2371 2372 2373 case /* 12 */ PPCG_FLAG_OP_SRAD: 2374 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2375 If it is <= 63, behave like SRADI; else XER.CA is the sign 2376 bit of argL. */ 2377 /* This term valid for shift amount < 63 only */ 2378 2379 xer_ca 2380 = binop( 2381 Iop_And64, 2382 binop(Iop_Sar64, argL, mkU8(63)), 2383 binop( Iop_And64, 2384 argL, 2385 binop( Iop_Sub64, 2386 binop(Iop_Shl64, mkU64(1), 2387 unop(Iop_64to8,argR)), 2388 mkU64(1) ) 2389 ) 2390 ); 2391 xer_ca 2392 = IRExpr_Mux0X( 2393 /* shift amt > 63 ? */ 2394 unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)), 2395 /* no -- be like sradi */ 2396 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))), 2397 /* yes -- get sign bit of argL */ 2398 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))) 2399 ); 2400 break; 2401 2402 2403 case /* 13 */ PPCG_FLAG_OP_SRADI: 2404 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2405 Since the shift amount is known to be in the range 0 .. 63 2406 inclusive, the following seems viable: 2407 xer.ca == 1 iff the following is nonzero: 2408 (argL >>s 63) -- either all 0s or all 1s 2409 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2410 2411 xer_ca 2412 = binop( 2413 Iop_And64, 2414 binop(Iop_Sar64, argL, mkU8(63)), 2415 binop( Iop_And64, 2416 argL, 2417 binop( Iop_Sub64, 2418 binop(Iop_Shl64, mkU64(1), 2419 unop(Iop_64to8,argR)), 2420 mkU64(1) ) 2421 ) 2422 ); 2423 xer_ca 2424 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2425 break; 2426 2427 default: 2428 vex_printf("set_XER_CA: op = %u\n", op); 2429 vpanic("set_XER_CA(ppc64)"); 2430 } 2431 2432 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2433 putXER_CA( unop(Iop_32to8, xer_ca) ); 2434 } 2435 2436 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res, 2437 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2438 { 2439 if (ty == Ity_I32) 2440 set_XER_CA_32( op, res, argL, argR, oldca ); 2441 else 2442 set_XER_CA_64( op, res, argL, argR, oldca ); 2443 } 2444 2445 2446 2447 /*------------------------------------------------------------*/ 2448 /*--- Read/write to guest-state --- */ 2449 /*------------------------------------------------------------*/ 2450 2451 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg ) 2452 { 2453 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2454 switch (reg) { 2455 case PPC_GST_SPRG3_RO: 2456 return IRExpr_Get( OFFB_SPRG3_RO, ty ); 2457 2458 case PPC_GST_CIA: 2459 return IRExpr_Get( OFFB_CIA, ty ); 2460 2461 case PPC_GST_LR: 2462 return IRExpr_Get( OFFB_LR, ty ); 2463 2464 case PPC_GST_CTR: 2465 return IRExpr_Get( OFFB_CTR, ty ); 2466 2467 case PPC_GST_VRSAVE: 2468 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); 2469 2470 case PPC_GST_VSCR: 2471 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ), 2472 mkU32(MASK_VSCR_VALID)); 2473 2474 case PPC_GST_CR: { 2475 /* Synthesise the entire CR into a single word. Expensive. */ 2476 # define FIELD(_n) \ 2477 binop(Iop_Shl32, \ 2478 unop(Iop_8Uto32, \ 2479 binop(Iop_Or8, \ 2480 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ 2481 binop(Iop_And8, getCR0(_n), mkU8(1)) \ 2482 ) \ 2483 ), \ 2484 mkU8(4 * (7-(_n))) \ 2485 ) 2486 return binop(Iop_Or32, 2487 binop(Iop_Or32, 2488 binop(Iop_Or32, FIELD(0), FIELD(1)), 2489 binop(Iop_Or32, FIELD(2), FIELD(3)) 2490 ), 2491 binop(Iop_Or32, 2492 binop(Iop_Or32, FIELD(4), FIELD(5)), 2493 binop(Iop_Or32, FIELD(6), FIELD(7)) 2494 ) 2495 ); 2496 # undef FIELD 2497 } 2498 2499 case PPC_GST_XER: 2500 return binop(Iop_Or32, 2501 binop(Iop_Or32, 2502 binop( Iop_Shl32, getXER_SO32(), mkU8(31)), 2503 binop( Iop_Shl32, getXER_OV32(), mkU8(30))), 2504 binop(Iop_Or32, 2505 binop( Iop_Shl32, getXER_CA32(), mkU8(29)), 2506 getXER_BC32())); 2507 2508 default: 2509 vex_printf("getGST(ppc): reg = %u", reg); 2510 vpanic("getGST(ppc)"); 2511 } 2512 } 2513 2514 /* Get a masked word from the given reg */ 2515 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask ) 2516 { 2517 IRTemp val = newTemp(Ity_I32); 2518 vassert( reg < PPC_GST_MAX ); 2519 2520 switch (reg) { 2521 2522 case PPC_GST_FPSCR: { 2523 /* Vex-generated code expects the FPSCR to be set as follows: 2524 all exceptions masked, round-to-nearest. 2525 This corresponds to a FPSCR value of 0x0. */ 2526 2527 /* In the lower 32 bits of FPSCR, we're only keeping track of 2528 * the binary floating point rounding mode, so if the mask isn't 2529 * asking for this, just return 0x0. 2530 */ 2531 if (mask & MASK_FPSCR_RN) { 2532 assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) ); 2533 } else { 2534 assign( val, mkU32(0x0) ); 2535 } 2536 break; 2537 } 2538 2539 default: 2540 vex_printf("getGST_masked(ppc): reg = %u", reg); 2541 vpanic("getGST_masked(ppc)"); 2542 } 2543 2544 if (mask != 0xFFFFFFFF) { 2545 return binop(Iop_And32, mkexpr(val), mkU32(mask)); 2546 } else { 2547 return mkexpr(val); 2548 } 2549 } 2550 2551 /* Get a masked word from the given reg */ 2552 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) { 2553 IRExpr * val; 2554 vassert( reg < PPC_GST_MAX ); 2555 2556 switch (reg) { 2557 2558 case PPC_GST_FPSCR: { 2559 /* In the upper 32 bits of FPSCR, we're only keeping track 2560 * of the decimal floating point rounding mode, so if the mask 2561 * isn't asking for this, just return 0x0. 2562 */ 2563 if (mask & MASK_FPSCR_DRN) { 2564 val = binop( Iop_And32, 2565 unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ), 2566 unop( Iop_64HIto32, mkU64( mask ) ) ); 2567 } else { 2568 val = mkU32( 0x0ULL ); 2569 } 2570 break; 2571 } 2572 2573 default: 2574 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg ); 2575 vpanic( "getGST_masked_upper(ppc)" ); 2576 } 2577 return val; 2578 } 2579 2580 2581 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation) 2582 and return it at the bottom of an I32; the top 27 bits are 2583 guaranteed to be zero. */ 2584 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld ) 2585 { 2586 UInt shft, mask; 2587 2588 vassert( fld < 8 ); 2589 vassert( reg < PPC_GST_MAX ); 2590 2591 shft = 4*(7-fld); 2592 mask = 0xF<<shft; 2593 2594 switch (reg) { 2595 case PPC_GST_XER: 2596 vassert(fld ==7); 2597 return binop(Iop_Or32, 2598 binop(Iop_Or32, 2599 binop(Iop_Shl32, getXER_SO32(), mkU8(3)), 2600 binop(Iop_Shl32, getXER_OV32(), mkU8(2))), 2601 binop( Iop_Shl32, getXER_CA32(), mkU8(1))); 2602 break; 2603 2604 default: 2605 if (shft == 0) 2606 return getGST_masked( reg, mask ); 2607 else 2608 return binop(Iop_Shr32, 2609 getGST_masked( reg, mask ), 2610 mkU8(toUChar( shft ))); 2611 } 2612 } 2613 2614 static void putGST ( PPC_GST reg, IRExpr* src ) 2615 { 2616 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2617 IRType ty_src = typeOfIRExpr(irsb->tyenv,src ); 2618 vassert( reg < PPC_GST_MAX ); 2619 switch (reg) { 2620 case PPC_GST_IP_AT_SYSCALL: 2621 vassert( ty_src == ty ); 2622 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) ); 2623 break; 2624 case PPC_GST_CIA: 2625 vassert( ty_src == ty ); 2626 stmt( IRStmt_Put( OFFB_CIA, src ) ); 2627 break; 2628 case PPC_GST_LR: 2629 vassert( ty_src == ty ); 2630 stmt( IRStmt_Put( OFFB_LR, src ) ); 2631 break; 2632 case PPC_GST_CTR: 2633 vassert( ty_src == ty ); 2634 stmt( IRStmt_Put( OFFB_CTR, src ) ); 2635 break; 2636 case PPC_GST_VRSAVE: 2637 vassert( ty_src == Ity_I32 ); 2638 stmt( IRStmt_Put( OFFB_VRSAVE,src)); 2639 break; 2640 case PPC_GST_VSCR: 2641 vassert( ty_src == Ity_I32 ); 2642 stmt( IRStmt_Put( OFFB_VSCR, 2643 binop(Iop_And32, src, 2644 mkU32(MASK_VSCR_VALID)) ) ); 2645 break; 2646 case PPC_GST_XER: 2647 vassert( ty_src == Ity_I32 ); 2648 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) ); 2649 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) ); 2650 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) ); 2651 putXER_BC( unop(Iop_32to8, src) ); 2652 break; 2653 2654 case PPC_GST_EMWARN: 2655 vassert( ty_src == Ity_I32 ); 2656 stmt( IRStmt_Put( OFFB_EMWARN,src) ); 2657 break; 2658 2659 case PPC_GST_TISTART: 2660 vassert( ty_src == ty ); 2661 stmt( IRStmt_Put( OFFB_TISTART, src) ); 2662 break; 2663 2664 case PPC_GST_TILEN: 2665 vassert( ty_src == ty ); 2666 stmt( IRStmt_Put( OFFB_TILEN, src) ); 2667 break; 2668 2669 default: 2670 vex_printf("putGST(ppc): reg = %u", reg); 2671 vpanic("putGST(ppc)"); 2672 } 2673 } 2674 2675 /* Write masked src to the given reg */ 2676 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask ) 2677 { 2678 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2679 vassert( reg < PPC_GST_MAX ); 2680 vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 ); 2681 2682 switch (reg) { 2683 case PPC_GST_FPSCR: { 2684 /* Allow writes to either binary or decimal floating point 2685 * Rounding Mode 2686 */ 2687 if (mask & MASK_FPSCR_RN) { 2688 stmt( IRStmt_Put( OFFB_FPROUND, 2689 unop( Iop_32to8, 2690 binop( Iop_And32, 2691 unop( Iop_64to32, src ), 2692 mkU32( MASK_FPSCR_RN & mask ) ) ) ) ); 2693 } else if (mask & MASK_FPSCR_DRN) { 2694 stmt( IRStmt_Put( OFFB_DFPROUND, 2695 unop( Iop_32to8, 2696 binop( Iop_And32, 2697 unop( Iop_64HIto32, src ), 2698 mkU32( ( MASK_FPSCR_DRN & mask ) 2699 >> 32 ) ) ) ) ); 2700 } 2701 2702 /* Give EmWarn for attempted writes to: 2703 - Exception Controls 2704 - Non-IEEE Mode 2705 */ 2706 if (mask & 0xFC) { // Exception Control, Non-IEE mode 2707 VexEmWarn ew = EmWarn_PPCexns; 2708 2709 /* If any of the src::exception_control bits are actually set, 2710 side-exit to the next insn, reporting the warning, 2711 so that Valgrind's dispatcher sees the warning. */ 2712 putGST( PPC_GST_EMWARN, mkU32(ew) ); 2713 stmt( 2714 IRStmt_Exit( 2715 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)), 2716 Ijk_EmWarn, 2717 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 2718 } 2719 2720 /* Ignore all other writes */ 2721 break; 2722 } 2723 2724 default: 2725 vex_printf("putGST_masked(ppc): reg = %u", reg); 2726 vpanic("putGST_masked(ppc)"); 2727 } 2728 } 2729 2730 /* Write the least significant nibble of src to the specified 2731 REG[FLD] (as per IBM/hardware notation). */ 2732 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld ) 2733 { 2734 UInt shft; 2735 ULong mask; 2736 2737 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 2738 vassert( fld < 16 ); 2739 vassert( reg < PPC_GST_MAX ); 2740 2741 if (fld < 8) 2742 shft = 4*(7-fld); 2743 else 2744 shft = 4*(15-fld); 2745 mask = 0xF<<shft; 2746 2747 switch (reg) { 2748 case PPC_GST_CR: 2749 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src))); 2750 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src))); 2751 break; 2752 2753 default: 2754 { 2755 IRExpr * src64 = unop( Iop_32Uto64, src ); 2756 2757 if (shft == 0) { 2758 putGST_masked( reg, src64, mask ); 2759 } else { 2760 putGST_masked( reg, 2761 binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ), 2762 mask ); 2763 } 2764 } 2765 } 2766 } 2767 2768 /*------------------------------------------------------------*/ 2769 /* Helpers for VSX instructions that do floating point 2770 * operations and need to determine if a src contains a 2771 * special FP value. 2772 * 2773 *------------------------------------------------------------*/ 2774 2775 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL 2776 #define FP_FRAC_PART(x) binop( Iop_And64, \ 2777 mkexpr( x ), \ 2778 mkU64( NONZERO_FRAC_MASK ) ) 2779 2780 // Returns exponent part of a single precision floating point as I32 2781 static IRExpr * fp_exp_part_sp(IRTemp src) 2782 { 2783 return binop( Iop_And32, 2784 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 2785 mkU32( 0xff ) ); 2786 } 2787 2788 // Returns exponent part of floating point as I32 2789 static IRExpr * fp_exp_part(IRTemp src, Bool sp) 2790 { 2791 IRExpr * exp; 2792 if (sp) 2793 return fp_exp_part_sp(src); 2794 2795 if (!mode64) 2796 exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32, 2797 mkexpr( src ) ), 2798 mkU8( 20 ) ), mkU32( 0x7ff ) ); 2799 else 2800 exp = unop( Iop_64to32, 2801 binop( Iop_And64, 2802 binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ), 2803 mkU64( 0x7ff ) ) ); 2804 return exp; 2805 } 2806 2807 static IRExpr * is_Inf_sp(IRTemp src) 2808 { 2809 IRTemp frac_part = newTemp(Ity_I32); 2810 IRExpr * Inf_exp; 2811 2812 assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) ); 2813 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) ); 2814 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) ); 2815 } 2816 2817 2818 // Infinity: exp = 7ff and fraction is zero; s = 0/1 2819 static IRExpr * is_Inf(IRTemp src, Bool sp) 2820 { 2821 IRExpr * Inf_exp, * hi32, * low32; 2822 IRTemp frac_part; 2823 2824 if (sp) 2825 return is_Inf_sp(src); 2826 2827 frac_part = newTemp(Ity_I64); 2828 assign( frac_part, FP_FRAC_PART(src) ); 2829 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), mkU32( 0x7ff ) ); 2830 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 2831 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 2832 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 2833 mkU32( 0 ) ) ); 2834 } 2835 2836 static IRExpr * is_Zero_sp(IRTemp src) 2837 { 2838 IRTemp sign_less_part = newTemp(Ity_I32); 2839 assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) ); 2840 return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) ); 2841 } 2842 2843 // Zero: exp is zero and fraction is zero; s = 0/1 2844 static IRExpr * is_Zero(IRTemp src, Bool sp) 2845 { 2846 IRExpr * hi32, * low32; 2847 IRTemp sign_less_part; 2848 if (sp) 2849 return is_Zero_sp(src); 2850 2851 sign_less_part = newTemp(Ity_I64); 2852 2853 assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) ); 2854 hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) ); 2855 low32 = unop( Iop_64to32, mkexpr( sign_less_part ) ); 2856 return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 2857 mkU32( 0 ) ); 2858 } 2859 2860 /* SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1' 2861 * QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0' 2862 * This function returns an IRExpr value of '1' for any type of NaN. 2863 */ 2864 static IRExpr * is_NaN(IRTemp src) 2865 { 2866 IRExpr * NaN_exp, * hi32, * low32; 2867 IRTemp frac_part = newTemp(Ity_I64); 2868 2869 assign( frac_part, FP_FRAC_PART(src) ); 2870 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 2871 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 2872 NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), 2873 mkU32( 0x7ff ) ); 2874 2875 return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 2876 mkU32( 0 ) ) ); 2877 } 2878 2879 /* This function returns an IRExpr value of '1' for any type of NaN. 2880 * The passed 'src' argument is assumed to be Ity_I32. 2881 */ 2882 static IRExpr * is_NaN_32(IRTemp src) 2883 { 2884 #define NONZERO_FRAC_MASK32 0x007fffffULL 2885 #define FP_FRAC_PART32(x) binop( Iop_And32, \ 2886 mkexpr( x ), \ 2887 mkU32( NONZERO_FRAC_MASK32 ) ) 2888 2889 IRExpr * frac_part = FP_FRAC_PART32(src); 2890 IRExpr * exp_part = binop( Iop_And32, 2891 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 2892 mkU32( 0x0ff ) ); 2893 IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) ); 2894 2895 return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) ); 2896 } 2897 2898 /* This helper function performs the negation part of operations of the form: 2899 * "Negate Multiply-<op>" 2900 * where "<op>" is either "Add" or "Sub". 2901 * 2902 * This function takes one argument -- the floating point intermediate result (converted to 2903 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of 2904 * the operation described above. 2905 */ 2906 static IRTemp getNegatedResult(IRTemp intermediateResult) 2907 { 2908 ULong signbit_mask = 0x8000000000000000ULL; 2909 IRTemp signbit_32 = newTemp(Ity_I32); 2910 IRTemp resultantSignbit = newTemp(Ity_I1); 2911 IRTemp negatedResult = newTemp(Ity_I64); 2912 assign( signbit_32, binop( Iop_Shr32, 2913 unop( Iop_64HIto32, 2914 binop( Iop_And64, mkexpr( intermediateResult ), 2915 mkU64( signbit_mask ) ) ), 2916 mkU8( 31 ) ) ); 2917 /* We negate the signbit if and only if the intermediate result from the 2918 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 2919 */ 2920 assign( resultantSignbit, 2921 unop( Iop_Not1, 2922 binop( Iop_CmpEQ32, 2923 binop( Iop_Xor32, 2924 mkexpr( signbit_32 ), 2925 unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ), 2926 mkU32( 1 ) ) ) ); 2927 2928 assign( negatedResult, 2929 binop( Iop_Or64, 2930 binop( Iop_And64, 2931 mkexpr( intermediateResult ), 2932 mkU64( ~signbit_mask ) ), 2933 binop( Iop_32HLto64, 2934 binop( Iop_Shl32, 2935 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 2936 mkU8( 31 ) ), 2937 mkU32( 0 ) ) ) ); 2938 2939 return negatedResult; 2940 } 2941 2942 /* This helper function performs the negation part of operations of the form: 2943 * "Negate Multiply-<op>" 2944 * where "<op>" is either "Add" or "Sub". 2945 * 2946 * This function takes one argument -- the floating point intermediate result (converted to 2947 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of 2948 * the operation described above. 2949 */ 2950 static IRTemp getNegatedResult_32(IRTemp intermediateResult) 2951 { 2952 UInt signbit_mask = 0x80000000; 2953 IRTemp signbit_32 = newTemp(Ity_I32); 2954 IRTemp resultantSignbit = newTemp(Ity_I1); 2955 IRTemp negatedResult = newTemp(Ity_I32); 2956 assign( signbit_32, binop( Iop_Shr32, 2957 binop( Iop_And32, mkexpr( intermediateResult ), 2958 mkU32( signbit_mask ) ), 2959 mkU8( 31 ) ) ); 2960 /* We negate the signbit if and only if the intermediate result from the 2961 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 2962 */ 2963 assign( resultantSignbit, 2964 unop( Iop_Not1, 2965 binop( Iop_CmpEQ32, 2966 binop( Iop_Xor32, 2967 mkexpr( signbit_32 ), 2968 unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ), 2969 mkU32( 1 ) ) ) ); 2970 2971 assign( negatedResult, 2972 binop( Iop_Or32, 2973 binop( Iop_And32, 2974 mkexpr( intermediateResult ), 2975 mkU32( ~signbit_mask ) ), 2976 binop( Iop_Shl32, 2977 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 2978 mkU8( 31 ) ) ) ); 2979 2980 return negatedResult; 2981 } 2982 2983 /*------------------------------------------------------------*/ 2984 /*--- Integer Instruction Translation --- */ 2985 /*------------------------------------------------------------*/ 2986 2987 /* 2988 Integer Arithmetic Instructions 2989 */ 2990 static Bool dis_int_arith ( UInt theInstr ) 2991 { 2992 /* D-Form, XO-Form */ 2993 UChar opc1 = ifieldOPC(theInstr); 2994 UChar rD_addr = ifieldRegDS(theInstr); 2995 UChar rA_addr = ifieldRegA(theInstr); 2996 UInt uimm16 = ifieldUIMM16(theInstr); 2997 UChar rB_addr = ifieldRegB(theInstr); 2998 UChar flag_OE = ifieldBIT10(theInstr); 2999 UInt opc2 = ifieldOPClo9(theInstr); 3000 UChar flag_rC = ifieldBIT0(theInstr); 3001 3002 Long simm16 = extend_s_16to64(uimm16); 3003 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3004 IRTemp rA = newTemp(ty); 3005 IRTemp rB = newTemp(ty); 3006 IRTemp rD = newTemp(ty); 3007 3008 Bool do_rc = False; 3009 3010 assign( rA, getIReg(rA_addr) ); 3011 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB 3012 3013 switch (opc1) { 3014 /* D-Form */ 3015 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 3016 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3017 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3018 mkSzExtendS16(ty, uimm16) ) ); 3019 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3020 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3021 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3022 break; 3023 3024 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) 3025 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3026 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3027 mkSzExtendS16(ty, uimm16) ) ); 3028 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3029 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3030 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3031 do_rc = True; // Always record to CR 3032 flag_rC = 1; 3033 break; 3034 3035 case 0x0E: // addi (Add Immediate, PPC32 p350) 3036 // li rD,val == addi rD,0,val 3037 // la disp(rA) == addi rD,rA,disp 3038 if ( rA_addr == 0 ) { 3039 DIP("li r%u,%d\n", rD_addr, (Int)simm16); 3040 assign( rD, mkSzExtendS16(ty, uimm16) ); 3041 } else { 3042 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3043 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3044 mkSzExtendS16(ty, uimm16) ) ); 3045 } 3046 break; 3047 3048 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353) 3049 // lis rD,val == addis rD,0,val 3050 if ( rA_addr == 0 ) { 3051 DIP("lis r%u,%d\n", rD_addr, (Int)simm16); 3052 assign( rD, mkSzExtendS32(ty, uimm16 << 16) ); 3053 } else { 3054 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16); 3055 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3056 mkSzExtendS32(ty, uimm16 << 16) ) ); 3057 } 3058 break; 3059 3060 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490) 3061 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3062 if (mode64) 3063 assign( rD, unop(Iop_128to64, 3064 binop(Iop_MullS64, mkexpr(rA), 3065 mkSzExtendS16(ty, uimm16))) ); 3066 else 3067 assign( rD, unop(Iop_64to32, 3068 binop(Iop_MullS32, mkexpr(rA), 3069 mkSzExtendS16(ty, uimm16))) ); 3070 break; 3071 3072 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540) 3073 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3074 // rD = simm16 - rA 3075 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3076 mkSzExtendS16(ty, uimm16), 3077 mkexpr(rA)) ); 3078 set_XER_CA( ty, PPCG_FLAG_OP_SUBFI, 3079 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3080 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3081 break; 3082 3083 /* XO-Form */ 3084 case 0x1F: 3085 do_rc = True; // All below record to CR 3086 3087 switch (opc2) { 3088 case 0x10A: // add (Add, PPC32 p347) 3089 DIP("add%s%s r%u,r%u,r%u\n", 3090 flag_OE ? "o" : "", flag_rC ? ".":"", 3091 rD_addr, rA_addr, rB_addr); 3092 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3093 mkexpr(rA), mkexpr(rB) ) ); 3094 if (flag_OE) { 3095 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3096 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3097 } 3098 break; 3099 3100 case 0x00A: // addc (Add Carrying, PPC32 p348) 3101 DIP("addc%s%s r%u,r%u,r%u\n", 3102 flag_OE ? "o" : "", flag_rC ? ".":"", 3103 rD_addr, rA_addr, rB_addr); 3104 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3105 mkexpr(rA), mkexpr(rB)) ); 3106 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3107 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3108 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3109 if (flag_OE) { 3110 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3111 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3112 } 3113 break; 3114 3115 case 0x08A: { // adde (Add Extended, PPC32 p349) 3116 IRTemp old_xer_ca = newTemp(ty); 3117 DIP("adde%s%s r%u,r%u,r%u\n", 3118 flag_OE ? "o" : "", flag_rC ? ".":"", 3119 rD_addr, rA_addr, rB_addr); 3120 // rD = rA + rB + XER[CA] 3121 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3122 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3123 binop( mkSzOp(ty, Iop_Add8), 3124 mkexpr(rB), mkexpr(old_xer_ca))) ); 3125 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3126 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3127 mkexpr(old_xer_ca) ); 3128 if (flag_OE) { 3129 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3130 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3131 } 3132 break; 3133 } 3134 3135 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354) 3136 IRTemp old_xer_ca = newTemp(ty); 3137 IRExpr *min_one; 3138 if (rB_addr != 0) { 3139 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n"); 3140 return False; 3141 } 3142 DIP("addme%s%s r%u,r%u,r%u\n", 3143 flag_OE ? "o" : "", flag_rC ? ".":"", 3144 rD_addr, rA_addr, rB_addr); 3145 // rD = rA + (-1) + XER[CA] 3146 // => Just another form of adde 3147 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3148 min_one = mkSzImm(ty, (Long)-1); 3149 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3150 binop( mkSzOp(ty, Iop_Add8), 3151 min_one, mkexpr(old_xer_ca)) )); 3152 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3153 mkexpr(rD), mkexpr(rA), min_one, 3154 mkexpr(old_xer_ca) ); 3155 if (flag_OE) { 3156 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3157 mkexpr(rD), mkexpr(rA), min_one ); 3158 } 3159 break; 3160 } 3161 3162 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355) 3163 IRTemp old_xer_ca = newTemp(ty); 3164 if (rB_addr != 0) { 3165 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n"); 3166 return False; 3167 } 3168 DIP("addze%s%s r%u,r%u,r%u\n", 3169 flag_OE ? "o" : "", flag_rC ? ".":"", 3170 rD_addr, rA_addr, rB_addr); 3171 // rD = rA + (0) + XER[CA] 3172 // => Just another form of adde 3173 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3174 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3175 mkexpr(rA), mkexpr(old_xer_ca)) ); 3176 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3177 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3178 mkexpr(old_xer_ca) ); 3179 if (flag_OE) { 3180 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3181 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3182 } 3183 break; 3184 } 3185 3186 case 0x1EB: // divw (Divide Word, PPC32 p388) 3187 DIP("divw%s%s r%u,r%u,r%u\n", 3188 flag_OE ? "o" : "", flag_rC ? ".":"", 3189 rD_addr, rA_addr, rB_addr); 3190 if (mode64) { 3191 /* Note: 3192 XER settings are mode independent, and reflect the 3193 overflow of the low-order 32bit result 3194 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3195 */ 3196 /* rD[hi32] are undefined: setting them to sign of lo32 3197 - makes set_CR0 happy */ 3198 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) ); 3199 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) ); 3200 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend, 3201 divisor) ) ); 3202 if (flag_OE) { 3203 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3204 mkexpr(rD), dividend, divisor ); 3205 } 3206 } else { 3207 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) ); 3208 if (flag_OE) { 3209 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3210 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3211 } 3212 } 3213 /* Note: 3214 if (0x8000_0000 / -1) or (x / 0) 3215 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3216 => But _no_ exception raised. */ 3217 break; 3218 3219 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389) 3220 DIP("divwu%s%s r%u,r%u,r%u\n", 3221 flag_OE ? "o" : "", flag_rC ? ".":"", 3222 rD_addr, rA_addr, rB_addr); 3223 if (mode64) { 3224 /* Note: 3225 XER settings are mode independent, and reflect the 3226 overflow of the low-order 32bit result 3227 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3228 */ 3229 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) ); 3230 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) ); 3231 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend, 3232 divisor) ) ); 3233 if (flag_OE) { 3234 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3235 mkexpr(rD), dividend, divisor ); 3236 } 3237 } else { 3238 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) ); 3239 if (flag_OE) { 3240 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3241 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3242 } 3243 } 3244 /* Note: ditto comment divw, for (x / 0) */ 3245 break; 3246 3247 case 0x04B: // mulhw (Multiply High Word, PPC32 p488) 3248 if (flag_OE != 0) { 3249 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n"); 3250 return False; 3251 } 3252 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3253 rD_addr, rA_addr, rB_addr); 3254 if (mode64) { 3255 /* rD[hi32] are undefined: setting them to sign of lo32 3256 - makes set_CR0 happy */ 3257 assign( rD, binop(Iop_Sar64, 3258 binop(Iop_Mul64, 3259 mk64lo32Sto64( mkexpr(rA) ), 3260 mk64lo32Sto64( mkexpr(rB) )), 3261 mkU8(32)) ); 3262 } else { 3263 assign( rD, unop(Iop_64HIto32, 3264 binop(Iop_MullS32, 3265 mkexpr(rA), mkexpr(rB))) ); 3266 } 3267 break; 3268 3269 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489) 3270 if (flag_OE != 0) { 3271 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n"); 3272 return False; 3273 } 3274 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3275 rD_addr, rA_addr, rB_addr); 3276 if (mode64) { 3277 /* rD[hi32] are undefined: setting them to sign of lo32 3278 - makes set_CR0 happy */ 3279 assign( rD, binop(Iop_Sar64, 3280 binop(Iop_Mul64, 3281 mk64lo32Uto64( mkexpr(rA) ), 3282 mk64lo32Uto64( mkexpr(rB) ) ), 3283 mkU8(32)) ); 3284 } else { 3285 assign( rD, unop(Iop_64HIto32, 3286 binop(Iop_MullU32, 3287 mkexpr(rA), mkexpr(rB))) ); 3288 } 3289 break; 3290 3291 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491) 3292 DIP("mullw%s%s r%u,r%u,r%u\n", 3293 flag_OE ? "o" : "", flag_rC ? ".":"", 3294 rD_addr, rA_addr, rB_addr); 3295 if (mode64) { 3296 /* rD[hi32] are undefined: setting them to sign of lo32 3297 - set_XER_OV() and set_CR0() depend on this */ 3298 IRExpr *a = unop(Iop_64to32, mkexpr(rA) ); 3299 IRExpr *b = unop(Iop_64to32, mkexpr(rB) ); 3300 assign( rD, binop(Iop_MullS32, a, b) ); 3301 if (flag_OE) { 3302 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3303 mkexpr(rD), 3304 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) ); 3305 } 3306 } else { 3307 assign( rD, unop(Iop_64to32, 3308 binop(Iop_MullU32, 3309 mkexpr(rA), mkexpr(rB))) ); 3310 if (flag_OE) { 3311 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3312 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3313 } 3314 } 3315 break; 3316 3317 case 0x068: // neg (Negate, PPC32 p493) 3318 if (rB_addr != 0) { 3319 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n"); 3320 return False; 3321 } 3322 DIP("neg%s%s r%u,r%u\n", 3323 flag_OE ? "o" : "", flag_rC ? ".":"", 3324 rD_addr, rA_addr); 3325 // rD = (~rA) + 1 3326 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3327 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ), 3328 mkSzImm(ty, 1)) ); 3329 if (flag_OE) { 3330 set_XER_OV( ty, PPCG_FLAG_OP_NEG, 3331 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3332 } 3333 break; 3334 3335 case 0x028: // subf (Subtract From, PPC32 p537) 3336 DIP("subf%s%s r%u,r%u,r%u\n", 3337 flag_OE ? "o" : "", flag_rC ? ".":"", 3338 rD_addr, rA_addr, rB_addr); 3339 // rD = rB - rA 3340 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3341 mkexpr(rB), mkexpr(rA)) ); 3342 if (flag_OE) { 3343 set_XER_OV( ty, PPCG_FLAG_OP_SUBF, 3344 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3345 } 3346 break; 3347 3348 case 0x008: // subfc (Subtract from Carrying, PPC32 p538) 3349 DIP("subfc%s%s r%u,r%u,r%u\n", 3350 flag_OE ? "o" : "", flag_rC ? ".":"", 3351 rD_addr, rA_addr, rB_addr); 3352 // rD = rB - rA 3353 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3354 mkexpr(rB), mkexpr(rA)) ); 3355 set_XER_CA( ty, PPCG_FLAG_OP_SUBFC, 3356 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3357 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3358 if (flag_OE) { 3359 set_XER_OV( ty, PPCG_FLAG_OP_SUBFC, 3360 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3361 } 3362 break; 3363 3364 case 0x088: {// subfe (Subtract from Extended, PPC32 p539) 3365 IRTemp old_xer_ca = newTemp(ty); 3366 DIP("subfe%s%s r%u,r%u,r%u\n", 3367 flag_OE ? "o" : "", flag_rC ? ".":"", 3368 rD_addr, rA_addr, rB_addr); 3369 // rD = (log not)rA + rB + XER[CA] 3370 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3371 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3372 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3373 binop( mkSzOp(ty, Iop_Add8), 3374 mkexpr(rB), mkexpr(old_xer_ca))) ); 3375 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3376 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3377 mkexpr(old_xer_ca) ); 3378 if (flag_OE) { 3379 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3380 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3381 } 3382 break; 3383 } 3384 3385 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541) 3386 IRTemp old_xer_ca = newTemp(ty); 3387 IRExpr *min_one; 3388 if (rB_addr != 0) { 3389 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n"); 3390 return False; 3391 } 3392 DIP("subfme%s%s r%u,r%u\n", 3393 flag_OE ? "o" : "", flag_rC ? ".":"", 3394 rD_addr, rA_addr); 3395 // rD = (log not)rA + (-1) + XER[CA] 3396 // => Just another form of subfe 3397 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3398 min_one = mkSzImm(ty, (Long)-1); 3399 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3400 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3401 binop( mkSzOp(ty, Iop_Add8), 3402 min_one, mkexpr(old_xer_ca))) ); 3403 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3404 mkexpr(rD), mkexpr(rA), min_one, 3405 mkexpr(old_xer_ca) ); 3406 if (flag_OE) { 3407 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3408 mkexpr(rD), mkexpr(rA), min_one ); 3409 } 3410 break; 3411 } 3412 3413 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542) 3414 IRTemp old_xer_ca = newTemp(ty); 3415 if (rB_addr != 0) { 3416 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n"); 3417 return False; 3418 } 3419 DIP("subfze%s%s r%u,r%u\n", 3420 flag_OE ? "o" : "", flag_rC ? ".":"", 3421 rD_addr, rA_addr); 3422 // rD = (log not)rA + (0) + XER[CA] 3423 // => Just another form of subfe 3424 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3425 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3426 unop( mkSzOp(ty, Iop_Not8), 3427 mkexpr(rA)), mkexpr(old_xer_ca)) ); 3428 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3429 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3430 mkexpr(old_xer_ca) ); 3431 if (flag_OE) { 3432 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3433 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3434 } 3435 break; 3436 } 3437 3438 3439 /* 64bit Arithmetic */ 3440 case 0x49: // mulhd (Multiply High DWord, PPC64 p539) 3441 if (flag_OE != 0) { 3442 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n"); 3443 return False; 3444 } 3445 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3446 rD_addr, rA_addr, rB_addr); 3447 assign( rD, unop(Iop_128HIto64, 3448 binop(Iop_MullS64, 3449 mkexpr(rA), mkexpr(rB))) ); 3450 3451 break; 3452 3453 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540) 3454 if (flag_OE != 0) { 3455 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n"); 3456 return False; 3457 } 3458 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3459 rD_addr, rA_addr, rB_addr); 3460 assign( rD, unop(Iop_128HIto64, 3461 binop(Iop_MullU64, 3462 mkexpr(rA), mkexpr(rB))) ); 3463 break; 3464 3465 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543) 3466 DIP("mulld%s%s r%u,r%u,r%u\n", 3467 flag_OE ? "o" : "", flag_rC ? ".":"", 3468 rD_addr, rA_addr, rB_addr); 3469 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) ); 3470 if (flag_OE) { 3471 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3472 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3473 } 3474 break; 3475 3476 case 0x1E9: // divd (Divide DWord, PPC64 p419) 3477 DIP("divd%s%s r%u,r%u,r%u\n", 3478 flag_OE ? "o" : "", flag_rC ? ".":"", 3479 rD_addr, rA_addr, rB_addr); 3480 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) ); 3481 if (flag_OE) { 3482 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3483 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3484 } 3485 break; 3486 /* Note: 3487 if (0x8000_0000_0000_0000 / -1) or (x / 0) 3488 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3489 => But _no_ exception raised. */ 3490 3491 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420) 3492 DIP("divdu%s%s r%u,r%u,r%u\n", 3493 flag_OE ? "o" : "", flag_rC ? ".":"", 3494 rD_addr, rA_addr, rB_addr); 3495 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) ); 3496 if (flag_OE) { 3497 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3498 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3499 } 3500 break; 3501 /* Note: ditto comment divd, for (x / 0) */ 3502 3503 case 0x18B: // divweu (Divide Word Extended Unsigned) 3504 { 3505 /* 3506 * If (RA) >= (RB), or if an attempt is made to perform the division 3507 * <anything> / 0 3508 * then the contents of register RD are undefined as are (if Rc=1) the contents of 3509 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set 3510 * to 1. 3511 */ 3512 IRTemp res = newTemp(Ity_I32); 3513 IRExpr * dividend, * divisor; 3514 DIP("divweu%s%s r%u,r%u,r%u\n", 3515 flag_OE ? "o" : "", flag_rC ? ".":"", 3516 rD_addr, rA_addr, rB_addr); 3517 if (mode64) { 3518 dividend = unop( Iop_64to32, mkexpr( rA ) ); 3519 divisor = unop( Iop_64to32, mkexpr( rB ) ); 3520 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 3521 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 3522 } else { 3523 dividend = mkexpr( rA ); 3524 divisor = mkexpr( rB ); 3525 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 3526 assign( rD, mkexpr( res) ); 3527 } 3528 3529 if (flag_OE) { 3530 set_XER_OV_32( PPCG_FLAG_OP_DIVWEU, 3531 mkexpr(res), dividend, divisor ); 3532 } 3533 break; 3534 } 3535 3536 case 0x1AB: // divwe (Divide Word Extended) 3537 { 3538 /* 3539 * If the quotient cannot be represented in 32 bits, or if an 3540 * attempt is made to perform the division 3541 * <anything> / 0 3542 * then the contents of register RD are undefined as are (if 3543 * Rc=1) the contents of the LT, GT, and EQ bits of CR 3544 * Field 0. In these cases, if OE=1 then OV is set to 1. 3545 */ 3546 3547 IRTemp res = newTemp(Ity_I32); 3548 IRExpr * dividend, * divisor; 3549 DIP("divwe%s%s r%u,r%u,r%u\n", 3550 flag_OE ? "o" : "", flag_rC ? ".":"", 3551 rD_addr, rA_addr, rB_addr); 3552 if (mode64) { 3553 dividend = unop( Iop_64to32, mkexpr( rA ) ); 3554 divisor = unop( Iop_64to32, mkexpr( rB ) ); 3555 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 3556 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 3557 } else { 3558 dividend = mkexpr( rA ); 3559 divisor = mkexpr( rB ); 3560 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 3561 assign( rD, mkexpr( res) ); 3562 } 3563 3564 if (flag_OE) { 3565 set_XER_OV_32( PPCG_FLAG_OP_DIVWE, 3566 mkexpr(res), dividend, divisor ); 3567 } 3568 break; 3569 } 3570 3571 3572 case 0x1A9: // divde (Divide Doubleword Extended) 3573 /* 3574 * If the quotient cannot be represented in 64 bits, or if an 3575 * attempt is made to perform the division 3576 * <anything> / 0 3577 * then the contents of register RD are undefined as are (if 3578 * Rc=1) the contents of the LT, GT, and EQ bits of CR 3579 * Field 0. In these cases, if OE=1 then OV is set to 1. 3580 */ 3581 DIP("divde%s%s r%u,r%u,r%u\n", 3582 flag_OE ? "o" : "", flag_rC ? ".":"", 3583 rD_addr, rA_addr, rB_addr); 3584 assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) ); 3585 if (flag_OE) { 3586 set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ), 3587 mkexpr( rA ), mkexpr( rB ) ); 3588 } 3589 break; 3590 3591 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned) 3592 // Same CR and OV rules as given for divweu above 3593 DIP("divdeu%s%s r%u,r%u,r%u\n", 3594 flag_OE ? "o" : "", flag_rC ? ".":"", 3595 rD_addr, rA_addr, rB_addr); 3596 assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) ); 3597 if (flag_OE) { 3598 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ), 3599 mkexpr( rA ), mkexpr( rB ) ); 3600 } 3601 break; 3602 3603 default: 3604 vex_printf("dis_int_arith(ppc)(opc2)\n"); 3605 return False; 3606 } 3607 break; 3608 3609 default: 3610 vex_printf("dis_int_arith(ppc)(opc1)\n"); 3611 return False; 3612 } 3613 3614 putIReg( rD_addr, mkexpr(rD) ); 3615 3616 if (do_rc && flag_rC) { 3617 set_CR0( mkexpr(rD) ); 3618 } 3619 return True; 3620 } 3621 3622 3623 3624 /* 3625 Integer Compare Instructions 3626 */ 3627 static Bool dis_int_cmp ( UInt theInstr ) 3628 { 3629 /* D-Form, X-Form */ 3630 UChar opc1 = ifieldOPC(theInstr); 3631 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 3632 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) ); 3633 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) ); 3634 UChar rA_addr = ifieldRegA(theInstr); 3635 UInt uimm16 = ifieldUIMM16(theInstr); 3636 UChar rB_addr = ifieldRegB(theInstr); 3637 UInt opc2 = ifieldOPClo10(theInstr); 3638 UChar b0 = ifieldBIT0(theInstr); 3639 3640 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3641 IRExpr *a = getIReg(rA_addr); 3642 IRExpr *b; 3643 3644 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit. 3645 vex_printf("dis_int_cmp(ppc)(flag_L)\n"); 3646 return False; 3647 } 3648 3649 if (b22 != 0) { 3650 vex_printf("dis_int_cmp(ppc)(b22)\n"); 3651 return False; 3652 } 3653 3654 switch (opc1) { 3655 case 0x0B: // cmpi (Compare Immediate, PPC32 p368) 3656 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr, 3657 (Int)extend_s_16to32(uimm16)); 3658 b = mkSzExtendS16( ty, uimm16 ); 3659 if (flag_L == 1) { 3660 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 3661 } else { 3662 a = mkNarrowTo32( ty, a ); 3663 b = mkNarrowTo32( ty, b ); 3664 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b))); 3665 } 3666 putCR0( crfD, getXER_SO() ); 3667 break; 3668 3669 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370) 3670 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16); 3671 b = mkSzImm( ty, uimm16 ); 3672 if (flag_L == 1) { 3673 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 3674 } else { 3675 a = mkNarrowTo32( ty, a ); 3676 b = mkNarrowTo32( ty, b ); 3677 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 3678 } 3679 putCR0( crfD, getXER_SO() ); 3680 break; 3681 3682 /* X Form */ 3683 case 0x1F: 3684 if (b0 != 0) { 3685 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n"); 3686 return False; 3687 } 3688 b = getIReg(rB_addr); 3689 3690 switch (opc2) { 3691 case 0x000: // cmp (Compare, PPC32 p367) 3692 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 3693 /* Comparing a reg with itself produces a result which 3694 doesn't depend on the contents of the reg. Therefore 3695 remove the false dependency, which has been known to cause 3696 memcheck to produce false errors. */ 3697 if (rA_addr == rB_addr) 3698 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 3699 ? mkU64(0) : mkU32(0); 3700 if (flag_L == 1) { 3701 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 3702 } else { 3703 a = mkNarrowTo32( ty, a ); 3704 b = mkNarrowTo32( ty, b ); 3705 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b))); 3706 } 3707 putCR0( crfD, getXER_SO() ); 3708 break; 3709 3710 case 0x020: // cmpl (Compare Logical, PPC32 p369) 3711 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 3712 /* Comparing a reg with itself produces a result which 3713 doesn't depend on the contents of the reg. Therefore 3714 remove the false dependency, which has been known to cause 3715 memcheck to produce false errors. */ 3716 if (rA_addr == rB_addr) 3717 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 3718 ? mkU64(0) : mkU32(0); 3719 if (flag_L == 1) { 3720 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 3721 } else { 3722 a = mkNarrowTo32( ty, a ); 3723 b = mkNarrowTo32( ty, b ); 3724 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 3725 } 3726 putCR0( crfD, getXER_SO() ); 3727 break; 3728 3729 default: 3730 vex_printf("dis_int_cmp(ppc)(opc2)\n"); 3731 return False; 3732 } 3733 break; 3734 3735 default: 3736 vex_printf("dis_int_cmp(ppc)(opc1)\n"); 3737 return False; 3738 } 3739 3740 return True; 3741 } 3742 3743 3744 /* 3745 Integer Logical Instructions 3746 */ 3747 static Bool dis_int_logic ( UInt theInstr ) 3748 { 3749 /* D-Form, X-Form */ 3750 UChar opc1 = ifieldOPC(theInstr); 3751 UChar rS_addr = ifieldRegDS(theInstr); 3752 UChar rA_addr = ifieldRegA(theInstr); 3753 UInt uimm16 = ifieldUIMM16(theInstr); 3754 UChar rB_addr = ifieldRegB(theInstr); 3755 UInt opc2 = ifieldOPClo10(theInstr); 3756 UChar flag_rC = ifieldBIT0(theInstr); 3757 3758 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3759 IRTemp rS = newTemp(ty); 3760 IRTemp rA = newTemp(ty); 3761 IRTemp rB = newTemp(ty); 3762 IRExpr* irx; 3763 Bool do_rc = False; 3764 3765 assign( rS, getIReg(rS_addr) ); 3766 assign( rB, getIReg(rB_addr) ); 3767 3768 switch (opc1) { 3769 case 0x1C: // andi. (AND Immediate, PPC32 p358) 3770 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3771 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 3772 mkSzImm(ty, uimm16)) ); 3773 do_rc = True; // Always record to CR 3774 flag_rC = 1; 3775 break; 3776 3777 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359) 3778 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3779 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 3780 mkSzImm(ty, uimm16 << 16)) ); 3781 do_rc = True; // Always record to CR 3782 flag_rC = 1; 3783 break; 3784 3785 case 0x18: // ori (OR Immediate, PPC32 p497) 3786 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3787 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 3788 mkSzImm(ty, uimm16)) ); 3789 break; 3790 3791 case 0x19: // oris (OR Immediate Shifted, PPC32 p498) 3792 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3793 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 3794 mkSzImm(ty, uimm16 << 16)) ); 3795 break; 3796 3797 case 0x1A: // xori (XOR Immediate, PPC32 p550) 3798 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3799 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 3800 mkSzImm(ty, uimm16)) ); 3801 break; 3802 3803 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551) 3804 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3805 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 3806 mkSzImm(ty, uimm16 << 16)) ); 3807 break; 3808 3809 /* X Form */ 3810 case 0x1F: 3811 do_rc = True; // All below record to CR, except for where we return at case end. 3812 3813 switch (opc2) { 3814 case 0x01C: // and (AND, PPC32 p356) 3815 DIP("and%s r%u,r%u,r%u\n", 3816 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3817 assign(rA, binop( mkSzOp(ty, Iop_And8), 3818 mkexpr(rS), mkexpr(rB))); 3819 break; 3820 3821 case 0x03C: // andc (AND with Complement, PPC32 p357) 3822 DIP("andc%s r%u,r%u,r%u\n", 3823 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3824 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 3825 unop( mkSzOp(ty, Iop_Not8), 3826 mkexpr(rB)))); 3827 break; 3828 3829 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371) 3830 IRExpr* lo32; 3831 if (rB_addr!=0) { 3832 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n"); 3833 return False; 3834 } 3835 DIP("cntlzw%s r%u,r%u\n", 3836 flag_rC ? ".":"", rA_addr, rS_addr); 3837 3838 // mode64: count in low word only 3839 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS); 3840 3841 // Iop_Clz32 undefined for arg==0, so deal with that case: 3842 irx = binop(Iop_CmpNE32, lo32, mkU32(0)); 3843 assign(rA, mkWidenFrom32(ty, 3844 IRExpr_Mux0X( unop(Iop_1Uto8, irx), 3845 mkU32(32), 3846 unop(Iop_Clz32, lo32)), 3847 False)); 3848 3849 // TODO: alternatively: assign(rA, verbose_Clz32(rS)); 3850 break; 3851 } 3852 3853 case 0x11C: // eqv (Equivalent, PPC32 p396) 3854 DIP("eqv%s r%u,r%u,r%u\n", 3855 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3856 assign( rA, unop( mkSzOp(ty, Iop_Not8), 3857 binop( mkSzOp(ty, Iop_Xor8), 3858 mkexpr(rS), mkexpr(rB))) ); 3859 break; 3860 3861 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397 3862 if (rB_addr!=0) { 3863 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n"); 3864 return False; 3865 } 3866 DIP("extsb%s r%u,r%u\n", 3867 flag_rC ? ".":"", rA_addr, rS_addr); 3868 if (mode64) 3869 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) ); 3870 else 3871 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) ); 3872 break; 3873 3874 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398) 3875 if (rB_addr!=0) { 3876 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n"); 3877 return False; 3878 } 3879 DIP("extsh%s r%u,r%u\n", 3880 flag_rC ? ".":"", rA_addr, rS_addr); 3881 if (mode64) 3882 assign( rA, unop(Iop_16Sto64, 3883 unop(Iop_64to16, mkexpr(rS))) ); 3884 else 3885 assign( rA, unop(Iop_16Sto32, 3886 unop(Iop_32to16, mkexpr(rS))) ); 3887 break; 3888 3889 case 0x1DC: // nand (NAND, PPC32 p492) 3890 DIP("nand%s r%u,r%u,r%u\n", 3891 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3892 assign( rA, unop( mkSzOp(ty, Iop_Not8), 3893 binop( mkSzOp(ty, Iop_And8), 3894 mkexpr(rS), mkexpr(rB))) ); 3895 break; 3896 3897 case 0x07C: // nor (NOR, PPC32 p494) 3898 DIP("nor%s r%u,r%u,r%u\n", 3899 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3900 assign( rA, unop( mkSzOp(ty, Iop_Not8), 3901 binop( mkSzOp(ty, Iop_Or8), 3902 mkexpr(rS), mkexpr(rB))) ); 3903 break; 3904 3905 case 0x1BC: // or (OR, PPC32 p495) 3906 if ((!flag_rC) && rS_addr == rB_addr) { 3907 DIP("mr r%u,r%u\n", rA_addr, rS_addr); 3908 assign( rA, mkexpr(rS) ); 3909 } else { 3910 DIP("or%s r%u,r%u,r%u\n", 3911 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3912 assign( rA, binop( mkSzOp(ty, Iop_Or8), 3913 mkexpr(rS), mkexpr(rB)) ); 3914 } 3915 break; 3916 3917 case 0x19C: // orc (OR with Complement, PPC32 p496) 3918 DIP("orc%s r%u,r%u,r%u\n", 3919 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3920 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 3921 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB)))); 3922 break; 3923 3924 case 0x13C: // xor (XOR, PPC32 p549) 3925 DIP("xor%s r%u,r%u,r%u\n", 3926 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 3927 assign( rA, binop( mkSzOp(ty, Iop_Xor8), 3928 mkexpr(rS), mkexpr(rB)) ); 3929 break; 3930 3931 3932 /* 64bit Integer Logical Instructions */ 3933 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430) 3934 if (rB_addr!=0) { 3935 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n"); 3936 return False; 3937 } 3938 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr); 3939 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS)))); 3940 break; 3941 3942 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401) 3943 if (rB_addr!=0) { 3944 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n"); 3945 return False; 3946 } 3947 DIP("cntlzd%s r%u,r%u\n", 3948 flag_rC ? ".":"", rA_addr, rS_addr); 3949 // Iop_Clz64 undefined for arg==0, so deal with that case: 3950 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0)); 3951 assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx), 3952 mkU64(64), 3953 unop(Iop_Clz64, mkexpr(rS)) )); 3954 // TODO: alternatively: assign(rA, verbose_Clz64(rS)); 3955 break; 3956 3957 case 0x1FC: // cmpb (Power6: compare bytes) 3958 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 3959 3960 if (mode64) 3961 assign( rA, unop( Iop_V128to64, 3962 binop( Iop_CmpEQ8x16, 3963 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ), 3964 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) ) 3965 )) ); 3966 else 3967 assign( rA, unop( Iop_V128to32, 3968 binop( Iop_CmpEQ8x16, 3969 unop( Iop_32UtoV128, mkexpr(rS) ), 3970 unop( Iop_32UtoV128, mkexpr(rB) ) 3971 )) ); 3972 break; 3973 3974 case 0x2DF: { // mftgpr (move floating-point to general purpose register) 3975 IRTemp frB = newTemp(Ity_F64); 3976 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr); 3977 3978 assign( frB, getFReg(rB_addr)); // always F64 3979 if (mode64) 3980 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 3981 else 3982 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) ); 3983 3984 putIReg( rS_addr, mkexpr(rA)); 3985 return True; 3986 } 3987 3988 case 0x25F: { // mffgpr (move floating-point from general purpose register) 3989 IRTemp frA = newTemp(Ity_F64); 3990 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr); 3991 3992 if (mode64) 3993 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) ); 3994 else 3995 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) ); 3996 3997 putFReg( rS_addr, mkexpr(frA)); 3998 return True; 3999 } 4000 case 0x1FA: // popcntd (population count doubleword 4001 { 4002 DIP("popcntd r%u,r%u\n", rA_addr, rS_addr); 4003 IRTemp result = gen_POPCOUNT(ty, rS, False); 4004 putIReg( rA_addr, mkexpr(result) ); 4005 return True; 4006 } 4007 case 0x17A: // popcntw (Population Count Words) 4008 { 4009 DIP("popcntw r%u,r%u\n", rA_addr, rS_addr); 4010 if (mode64) { 4011 IRTemp resultHi, resultLo; 4012 IRTemp argLo = newTemp(Ity_I32); 4013 IRTemp argHi = newTemp(Ity_I32); 4014 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4015 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4016 resultLo = gen_POPCOUNT(Ity_I32, argLo, False); 4017 resultHi = gen_POPCOUNT(Ity_I32, argHi, False); 4018 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo))); 4019 } else { 4020 IRTemp result = gen_POPCOUNT(ty, rS, False); 4021 putIReg( rA_addr, mkexpr(result) ); 4022 } 4023 return True; 4024 } 4025 case 0x7A: // popcntb (Population Count Byte) 4026 { 4027 DIP("popcntb r%u,r%u\n", rA_addr, rS_addr); 4028 4029 if (mode64) { 4030 IRTemp resultHi, resultLo; 4031 IRTemp argLo = newTemp(Ity_I32); 4032 IRTemp argHi = newTemp(Ity_I32); 4033 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4034 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4035 resultLo = gen_POPCOUNT(Ity_I32, argLo, True); 4036 resultHi = gen_POPCOUNT(Ity_I32, argHi, True); 4037 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), 4038 mkexpr(resultLo))); 4039 } else { 4040 IRTemp result = gen_POPCOUNT(ty, rS, True); 4041 putIReg( rA_addr, mkexpr(result) ); 4042 } 4043 return True; 4044 } 4045 case 0x0FC: // bpermd (Bit Permute Doubleword) 4046 { 4047 /* This is a lot of rigmarole to emulate bpermd like this, as it 4048 * could be done much faster by implementing a call to the native 4049 * instruction. However, where possible I want to avoid using new 4050 * native instructions so that we can use valgrind to emulate those 4051 * instructions on older PPC64 hardware. 4052 */ 4053 #define BPERMD_IDX_MASK 0x00000000000000FFULL 4054 #define BPERMD_BIT_MASK 0x8000000000000000ULL 4055 int i; 4056 IRExpr * rS_expr = mkexpr(rS); 4057 IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0)); 4058 DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 4059 for (i = 0; i < 8; i++) { 4060 IRTemp idx_tmp = newTemp( Ity_I64 ); 4061 IRTemp perm_bit = newTemp( Ity_I64 ); 4062 IRTemp idx = newTemp( Ity_I8 ); 4063 IRTemp idx_LT64 = newTemp( Ity_I1 ); 4064 IRTemp idx_LT64_ity64 = newTemp( Ity_I64 ); 4065 4066 assign( idx_tmp, 4067 binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) ); 4068 assign( idx_LT64, 4069 binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) ); 4070 assign( idx, 4071 binop( Iop_And8, 4072 unop( Iop_1Sto8, 4073 mkexpr(idx_LT64) ), 4074 unop( Iop_64to8, mkexpr( idx_tmp ) ) ) ); 4075 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx 4076 * to determine which bit of rB to use for the perm bit, and then we shift 4077 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64 4078 * to set the final perm bit. 4079 */ 4080 assign( idx_LT64_ity64, 4081 unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) ); 4082 assign( perm_bit, 4083 binop( Iop_And64, 4084 mkexpr( idx_LT64_ity64 ), 4085 binop( Iop_Shr64, 4086 binop( Iop_And64, 4087 mkU64( BPERMD_BIT_MASK ), 4088 binop( Iop_Shl64, 4089 mkexpr( rB ), 4090 mkexpr( idx ) ) ), 4091 mkU8( 63 ) ) ) ); 4092 res = binop( Iop_Or64, 4093 res, 4094 binop( Iop_Shl64, 4095 mkexpr( perm_bit ), 4096 mkU8( i ) ) ); 4097 rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) ); 4098 } 4099 putIReg(rA_addr, res); 4100 return True; 4101 } 4102 4103 default: 4104 vex_printf("dis_int_logic(ppc)(opc2)\n"); 4105 return False; 4106 } 4107 break; 4108 4109 default: 4110 vex_printf("dis_int_logic(ppc)(opc1)\n"); 4111 return False; 4112 } 4113 4114 putIReg( rA_addr, mkexpr(rA) ); 4115 4116 if (do_rc && flag_rC) { 4117 set_CR0( mkexpr(rA) ); 4118 } 4119 return True; 4120 } 4121 4122 /* 4123 Integer Parity Instructions 4124 */ 4125 static Bool dis_int_parity ( UInt theInstr ) 4126 { 4127 /* X-Form */ 4128 UChar opc1 = ifieldOPC(theInstr); 4129 UChar rS_addr = ifieldRegDS(theInstr); 4130 UChar rA_addr = ifieldRegA(theInstr); 4131 UChar rB_addr = ifieldRegB(theInstr); 4132 UInt opc2 = ifieldOPClo10(theInstr); 4133 UChar b0 = ifieldBIT0(theInstr); 4134 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4135 4136 IRTemp rS = newTemp(ty); 4137 IRTemp rA = newTemp(ty); 4138 IRTemp iTot1 = newTemp(Ity_I32); 4139 IRTemp iTot2 = newTemp(Ity_I32); 4140 IRTemp iTot3 = newTemp(Ity_I32); 4141 IRTemp iTot4 = newTemp(Ity_I32); 4142 IRTemp iTot5 = newTemp(Ity_I32); 4143 IRTemp iTot6 = newTemp(Ity_I32); 4144 IRTemp iTot7 = newTemp(Ity_I32); 4145 IRTemp iTot8 = newTemp(Ity_I32); 4146 IRTemp rS1 = newTemp(ty); 4147 IRTemp rS2 = newTemp(ty); 4148 IRTemp rS3 = newTemp(ty); 4149 IRTemp rS4 = newTemp(ty); 4150 IRTemp rS5 = newTemp(ty); 4151 IRTemp rS6 = newTemp(ty); 4152 IRTemp rS7 = newTemp(ty); 4153 IRTemp iHi = newTemp(Ity_I32); 4154 IRTemp iLo = newTemp(Ity_I32); 4155 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1); 4156 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32); 4157 4158 if (opc1 != 0x1f || rB_addr || b0) { 4159 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n"); 4160 return False; 4161 } 4162 4163 assign( rS, getIReg(rS_addr) ); 4164 4165 switch (opc2) { 4166 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320) 4167 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr); 4168 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4169 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4170 assign( iTot2, binop(Iop_Add32, 4171 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4172 mkexpr(iTot1)) ); 4173 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4174 assign( iTot3, binop(Iop_Add32, 4175 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4176 mkexpr(iTot2)) ); 4177 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4178 assign( iTot4, binop(Iop_Add32, 4179 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4180 mkexpr(iTot3)) ); 4181 if (mode64) { 4182 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4183 assign( iTot5, binop(Iop_Add32, 4184 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))), 4185 mkexpr(iTot4)) ); 4186 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4187 assign( iTot6, binop(Iop_Add32, 4188 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4189 mkexpr(iTot5)) ); 4190 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4191 assign( iTot7, binop(Iop_Add32, 4192 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4193 mkexpr(iTot6)) ); 4194 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) ); 4195 assign( iTot8, binop(Iop_Add32, 4196 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4197 mkexpr(iTot7)) ); 4198 assign( rA, unop(Iop_32Uto64, 4199 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) ); 4200 } else 4201 assign( rA, mkexpr(iTot4) ); 4202 4203 break; 4204 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320) 4205 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4206 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4207 assign( iTot2, binop(Iop_Add32, 4208 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4209 mkexpr(iTot1)) ); 4210 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4211 assign( iTot3, binop(Iop_Add32, 4212 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4213 mkexpr(iTot2)) ); 4214 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4215 assign( iTot4, binop(Iop_Add32, 4216 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4217 mkexpr(iTot3)) ); 4218 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) ); 4219 4220 if (mode64) { 4221 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4222 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) ); 4223 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4224 assign( iTot6, binop(Iop_Add32, 4225 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4226 mkexpr(iTot5)) ); 4227 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4228 assign( iTot7, binop(Iop_Add32, 4229 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4230 mkexpr(iTot6)) ); 4231 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8))); 4232 assign( iTot8, binop(Iop_Add32, 4233 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4234 mkexpr(iTot7)) ); 4235 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ), 4236 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) ); 4237 } else 4238 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) ); 4239 break; 4240 default: 4241 vex_printf("dis_int_parity(ppc)(opc2)\n"); 4242 return False; 4243 } 4244 4245 putIReg( rA_addr, mkexpr(rA) ); 4246 4247 return True; 4248 } 4249 4250 4251 /* 4252 Integer Rotate Instructions 4253 */ 4254 static Bool dis_int_rot ( UInt theInstr ) 4255 { 4256 /* M-Form, MDS-Form */ 4257 UChar opc1 = ifieldOPC(theInstr); 4258 UChar rS_addr = ifieldRegDS(theInstr); 4259 UChar rA_addr = ifieldRegA(theInstr); 4260 UChar rB_addr = ifieldRegB(theInstr); 4261 UChar sh_imm = rB_addr; 4262 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) ); 4263 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) ); 4264 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) ); 4265 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) ); 4266 UChar b1 = ifieldBIT1(theInstr); 4267 UChar flag_rC = ifieldBIT0(theInstr); 4268 4269 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4270 IRTemp rS = newTemp(ty); 4271 IRTemp rA = newTemp(ty); 4272 IRTemp rB = newTemp(ty); 4273 IRTemp rot = newTemp(ty); 4274 IRExpr *r; 4275 UInt mask32; 4276 ULong mask64; 4277 4278 assign( rS, getIReg(rS_addr) ); 4279 assign( rB, getIReg(rB_addr) ); 4280 4281 switch (opc1) { 4282 case 0x14: { 4283 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500) 4284 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4285 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4286 if (mode64) { 4287 // tmp32 = (ROTL(rS_Lo32, Imm) 4288 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64) 4289 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4290 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4291 r = unop(Iop_32Uto64, r); 4292 assign( rot, binop(Iop_Or64, r, 4293 binop(Iop_Shl64, r, mkU8(32))) ); 4294 assign( rA, 4295 binop(Iop_Or64, 4296 binop(Iop_And64, mkexpr(rot), mkU64(mask64)), 4297 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) ); 4298 } 4299 else { 4300 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask); 4301 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4302 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4303 assign( rA, 4304 binop(Iop_Or32, 4305 binop(Iop_And32, mkU32(mask32), r), 4306 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) ); 4307 } 4308 break; 4309 } 4310 4311 case 0x15: { 4312 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501) 4313 vassert(MaskBeg < 32); 4314 vassert(MaskEnd < 32); 4315 vassert(sh_imm < 32); 4316 4317 if (mode64) { 4318 IRTemp rTmp = newTemp(Ity_I64); 4319 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4320 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4321 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4322 // tmp32 = (ROTL(rS_Lo32, Imm) 4323 // rA = ((tmp32 || tmp32) & mask64) 4324 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4325 r = unop(Iop_32Uto64, r); 4326 assign( rTmp, r ); 4327 r = NULL; 4328 assign( rot, binop(Iop_Or64, mkexpr(rTmp), 4329 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) ); 4330 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4331 } 4332 else { 4333 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) { 4334 /* Special-case the ,n,0,31-n form as that is just n-bit 4335 shift left, PPC32 p501 */ 4336 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4337 rA_addr, rS_addr, sh_imm); 4338 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) ); 4339 } 4340 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) { 4341 /* Special-case the ,32-n,n,31 form as that is just n-bit 4342 unsigned shift right, PPC32 p501 */ 4343 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4344 rA_addr, rS_addr, MaskBeg); 4345 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) ); 4346 } 4347 else { 4348 /* General case. */ 4349 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4350 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4351 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4352 // rA = ROTL(rS, Imm) & mask 4353 assign( rA, binop(Iop_And32, 4354 ROTL(mkexpr(rS), mkU8(sh_imm)), 4355 mkU32(mask32)) ); 4356 } 4357 } 4358 break; 4359 } 4360 4361 case 0x17: { 4362 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503 4363 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"", 4364 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd); 4365 if (mode64) { 4366 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4367 /* weird insn alert! 4368 tmp32 = (ROTL(rS_Lo32, rB[0-4]) 4369 rA = ((tmp32 || tmp32) & mask64) 4370 */ 4371 // note, ROTL does the masking, so we don't do it here 4372 r = ROTL( unop(Iop_64to32, mkexpr(rS)), 4373 unop(Iop_64to8, mkexpr(rB)) ); 4374 r = unop(Iop_32Uto64, r); 4375 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)))); 4376 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4377 } else { 4378 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4379 // rA = ROTL(rS, rB[0-4]) & mask 4380 // note, ROTL does the masking, so we don't do it here 4381 assign( rA, binop(Iop_And32, 4382 ROTL(mkexpr(rS), 4383 unop(Iop_32to8, mkexpr(rB))), 4384 mkU32(mask32)) ); 4385 } 4386 break; 4387 } 4388 4389 /* 64bit Integer Rotates */ 4390 case 0x1E: { 4391 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1); 4392 sh_imm |= b1 << 5; 4393 4394 vassert( msk_imm < 64 ); 4395 vassert( sh_imm < 64 ); 4396 4397 switch (opc2) { 4398 case 0x4: { 4399 /* r = ROTL64( rS, rB_lo6) */ 4400 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) ); 4401 4402 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555) 4403 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4404 rA_addr, rS_addr, rB_addr, msk_imm); 4405 // note, ROTL does the masking, so we don't do it here 4406 mask64 = MASK64(0, 63-msk_imm); 4407 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4408 break; 4409 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556) 4410 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4411 rA_addr, rS_addr, rB_addr, msk_imm); 4412 mask64 = MASK64(63-msk_imm, 63); 4413 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4414 break; 4415 } 4416 break; 4417 } 4418 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557) 4419 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4420 rA_addr, rS_addr, sh_imm, msk_imm); 4421 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4422 mask64 = MASK64(sh_imm, 63-msk_imm); 4423 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4424 break; 4425 // later: deal with special case: (msk_imm==0) => SHL(sh_imm) 4426 /* 4427 Hmm... looks like this'll do the job more simply: 4428 r = SHL(rS, sh_imm) 4429 m = ~(1 << (63-msk_imm)) 4430 assign(rA, r & m); 4431 */ 4432 4433 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558) 4434 if (mode64 4435 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) { 4436 /* special-case the ,64-n,n form as that is just 4437 unsigned shift-right by n */ 4438 DIP("srdi%s r%u,r%u,%u\n", 4439 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm); 4440 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) ); 4441 } else { 4442 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4443 rA_addr, rS_addr, sh_imm, msk_imm); 4444 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4445 mask64 = MASK64(0, 63-msk_imm); 4446 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4447 } 4448 break; 4449 4450 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559) 4451 if (mode64 4452 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) { 4453 /* special-case the ,n,63-n form as that is just 4454 shift-left by n */ 4455 DIP("sldi%s r%u,r%u,%u\n", 4456 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 4457 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) ); 4458 } else { 4459 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4460 rA_addr, rS_addr, sh_imm, msk_imm); 4461 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4462 mask64 = MASK64(63-msk_imm, 63); 4463 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4464 } 4465 break; 4466 4467 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560) 4468 IRTemp rA_orig = newTemp(ty); 4469 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4470 rA_addr, rS_addr, sh_imm, msk_imm); 4471 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4472 mask64 = MASK64(sh_imm, 63-msk_imm); 4473 assign( rA_orig, getIReg(rA_addr) ); 4474 assign( rA, binop(Iop_Or64, 4475 binop(Iop_And64, mkU64(mask64), r), 4476 binop(Iop_And64, mkU64(~mask64), 4477 mkexpr(rA_orig))) ); 4478 break; 4479 } 4480 default: 4481 vex_printf("dis_int_rot(ppc)(opc2)\n"); 4482 return False; 4483 } 4484 break; 4485 } 4486 4487 default: 4488 vex_printf("dis_int_rot(ppc)(opc1)\n"); 4489 return False; 4490 } 4491 4492 putIReg( rA_addr, mkexpr(rA) ); 4493 4494 if (flag_rC) { 4495 set_CR0( mkexpr(rA) ); 4496 } 4497 return True; 4498 } 4499 4500 4501 /* 4502 Integer Load Instructions 4503 */ 4504 static Bool dis_int_load ( UInt theInstr ) 4505 { 4506 /* D-Form, X-Form, DS-Form */ 4507 UChar opc1 = ifieldOPC(theInstr); 4508 UChar rD_addr = ifieldRegDS(theInstr); 4509 UChar rA_addr = ifieldRegA(theInstr); 4510 UInt uimm16 = ifieldUIMM16(theInstr); 4511 UChar rB_addr = ifieldRegB(theInstr); 4512 UInt opc2 = ifieldOPClo10(theInstr); 4513 UChar b1 = ifieldBIT1(theInstr); 4514 UChar b0 = ifieldBIT0(theInstr); 4515 4516 Int simm16 = extend_s_16to32(uimm16); 4517 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4518 IRTemp EA = newTemp(ty); 4519 IRExpr* val; 4520 4521 switch (opc1) { 4522 case 0x1F: // register offset 4523 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 4524 break; 4525 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off 4526 // lowest 2 bits of immediate before forming EA 4527 simm16 = simm16 & 0xFFFFFFFC; 4528 default: // immediate offset 4529 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4530 break; 4531 } 4532 4533 switch (opc1) { 4534 case 0x22: // lbz (Load B & Zero, PPC32 p433) 4535 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4536 val = loadBE(Ity_I8, mkexpr(EA)); 4537 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4538 break; 4539 4540 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434) 4541 if (rA_addr == 0 || rA_addr == rD_addr) { 4542 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n"); 4543 return False; 4544 } 4545 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4546 val = loadBE(Ity_I8, mkexpr(EA)); 4547 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4548 putIReg( rA_addr, mkexpr(EA) ); 4549 break; 4550 4551 case 0x2A: // lha (Load HW Alg, PPC32 p445) 4552 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4553 val = loadBE(Ity_I16, mkexpr(EA)); 4554 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4555 break; 4556 4557 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446) 4558 if (rA_addr == 0 || rA_addr == rD_addr) { 4559 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n"); 4560 return False; 4561 } 4562 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4563 val = loadBE(Ity_I16, mkexpr(EA)); 4564 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4565 putIReg( rA_addr, mkexpr(EA) ); 4566 break; 4567 4568 case 0x28: // lhz (Load HW & Zero, PPC32 p450) 4569 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4570 val = loadBE(Ity_I16, mkexpr(EA)); 4571 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4572 break; 4573 4574 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451) 4575 if (rA_addr == 0 || rA_addr == rD_addr) { 4576 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n"); 4577 return False; 4578 } 4579 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4580 val = loadBE(Ity_I16, mkexpr(EA)); 4581 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4582 putIReg( rA_addr, mkexpr(EA) ); 4583 break; 4584 4585 case 0x20: // lwz (Load W & Zero, PPC32 p460) 4586 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4587 val = loadBE(Ity_I32, mkexpr(EA)); 4588 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4589 break; 4590 4591 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461)) 4592 if (rA_addr == 0 || rA_addr == rD_addr) { 4593 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n"); 4594 return False; 4595 } 4596 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4597 val = loadBE(Ity_I32, mkexpr(EA)); 4598 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4599 putIReg( rA_addr, mkexpr(EA) ); 4600 break; 4601 4602 /* X Form */ 4603 case 0x1F: 4604 if (b0 != 0) { 4605 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n"); 4606 return False; 4607 } 4608 4609 switch (opc2) { 4610 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435) 4611 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4612 if (rA_addr == 0 || rA_addr == rD_addr) { 4613 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 4614 return False; 4615 } 4616 val = loadBE(Ity_I8, mkexpr(EA)); 4617 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4618 putIReg( rA_addr, mkexpr(EA) ); 4619 break; 4620 4621 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436) 4622 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4623 val = loadBE(Ity_I8, mkexpr(EA)); 4624 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4625 break; 4626 4627 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447) 4628 if (rA_addr == 0 || rA_addr == rD_addr) { 4629 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n"); 4630 return False; 4631 } 4632 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4633 val = loadBE(Ity_I16, mkexpr(EA)); 4634 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4635 putIReg( rA_addr, mkexpr(EA) ); 4636 break; 4637 4638 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448) 4639 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4640 val = loadBE(Ity_I16, mkexpr(EA)); 4641 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4642 break; 4643 4644 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452) 4645 if (rA_addr == 0 || rA_addr == rD_addr) { 4646 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n"); 4647 return False; 4648 } 4649 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4650 val = loadBE(Ity_I16, mkexpr(EA)); 4651 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4652 putIReg( rA_addr, mkexpr(EA) ); 4653 break; 4654 4655 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453) 4656 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4657 val = loadBE(Ity_I16, mkexpr(EA)); 4658 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4659 break; 4660 4661 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462) 4662 if (rA_addr == 0 || rA_addr == rD_addr) { 4663 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 4664 return False; 4665 } 4666 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4667 val = loadBE(Ity_I32, mkexpr(EA)); 4668 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4669 putIReg( rA_addr, mkexpr(EA) ); 4670 break; 4671 4672 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463) 4673 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4674 val = loadBE(Ity_I32, mkexpr(EA)); 4675 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4676 break; 4677 4678 4679 /* 64bit Loads */ 4680 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475) 4681 if (rA_addr == 0 || rA_addr == rD_addr) { 4682 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n"); 4683 return False; 4684 } 4685 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4686 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4687 putIReg( rA_addr, mkexpr(EA) ); 4688 break; 4689 4690 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476) 4691 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4692 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4693 break; 4694 4695 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501) 4696 if (rA_addr == 0 || rA_addr == rD_addr) { 4697 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n"); 4698 return False; 4699 } 4700 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4701 putIReg( rD_addr, 4702 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 4703 putIReg( rA_addr, mkexpr(EA) ); 4704 break; 4705 4706 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502) 4707 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4708 putIReg( rD_addr, 4709 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 4710 break; 4711 4712 default: 4713 vex_printf("dis_int_load(ppc)(opc2)\n"); 4714 return False; 4715 } 4716 break; 4717 4718 /* DS Form - 64bit Loads. In each case EA will have been formed 4719 with the lowest 2 bits masked off the immediate offset. */ 4720 case 0x3A: 4721 switch ((b1<<1) | b0) { 4722 case 0x0: // ld (Load DWord, PPC64 p472) 4723 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4724 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4725 break; 4726 4727 case 0x1: // ldu (Load DWord, Update, PPC64 p474) 4728 if (rA_addr == 0 || rA_addr == rD_addr) { 4729 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n"); 4730 return False; 4731 } 4732 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4733 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4734 putIReg( rA_addr, mkexpr(EA) ); 4735 break; 4736 4737 case 0x2: // lwa (Load Word Alg, PPC64 p499) 4738 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4739 putIReg( rD_addr, 4740 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 4741 break; 4742 4743 default: 4744 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 4745 return False; 4746 } 4747 break; 4748 4749 default: 4750 vex_printf("dis_int_load(ppc)(opc1)\n"); 4751 return False; 4752 } 4753 return True; 4754 } 4755 4756 4757 4758 /* 4759 Integer Store Instructions 4760 */ 4761 static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi ) 4762 { 4763 /* D-Form, X-Form, DS-Form */ 4764 UChar opc1 = ifieldOPC(theInstr); 4765 UInt rS_addr = ifieldRegDS(theInstr); 4766 UInt rA_addr = ifieldRegA(theInstr); 4767 UInt uimm16 = ifieldUIMM16(theInstr); 4768 UInt rB_addr = ifieldRegB(theInstr); 4769 UInt opc2 = ifieldOPClo10(theInstr); 4770 UChar b1 = ifieldBIT1(theInstr); 4771 UChar b0 = ifieldBIT0(theInstr); 4772 4773 Int simm16 = extend_s_16to32(uimm16); 4774 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4775 IRTemp rS = newTemp(ty); 4776 IRTemp rB = newTemp(ty); 4777 IRTemp EA = newTemp(ty); 4778 4779 assign( rB, getIReg(rB_addr) ); 4780 assign( rS, getIReg(rS_addr) ); 4781 4782 switch (opc1) { 4783 case 0x1F: // register offset 4784 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 4785 break; 4786 case 0x3E: // immediate offset: 64bit: std/stdu: mask off 4787 // lowest 2 bits of immediate before forming EA 4788 simm16 = simm16 & 0xFFFFFFFC; 4789 default: // immediate offset 4790 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4791 break; 4792 } 4793 4794 switch (opc1) { 4795 case 0x26: // stb (Store B, PPC32 p509) 4796 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4797 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 4798 break; 4799 4800 case 0x27: // stbu (Store B, Update, PPC32 p510) 4801 if (rA_addr == 0 ) { 4802 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n"); 4803 return False; 4804 } 4805 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4806 putIReg( rA_addr, mkexpr(EA) ); 4807 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 4808 break; 4809 4810 case 0x2C: // sth (Store HW, PPC32 p522) 4811 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4812 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 4813 break; 4814 4815 case 0x2D: // sthu (Store HW, Update, PPC32 p524) 4816 if (rA_addr == 0) { 4817 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n"); 4818 return False; 4819 } 4820 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4821 putIReg( rA_addr, mkexpr(EA) ); 4822 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 4823 break; 4824 4825 case 0x24: // stw (Store W, PPC32 p530) 4826 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4827 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 4828 break; 4829 4830 case 0x25: // stwu (Store W, Update, PPC32 p534) 4831 if (rA_addr == 0) { 4832 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n"); 4833 return False; 4834 } 4835 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4836 putIReg( rA_addr, mkexpr(EA) ); 4837 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 4838 break; 4839 4840 /* X Form : all these use EA_indexed */ 4841 case 0x1F: 4842 if (b0 != 0) { 4843 vex_printf("dis_int_store(ppc)(0x1F,b0)\n"); 4844 return False; 4845 } 4846 4847 switch (opc2) { 4848 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511) 4849 if (rA_addr == 0) { 4850 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n"); 4851 return False; 4852 } 4853 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4854 putIReg( rA_addr, mkexpr(EA) ); 4855 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 4856 break; 4857 4858 case 0x0D7: // stbx (Store B Indexed, PPC32 p512) 4859 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4860 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 4861 break; 4862 4863 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525) 4864 if (rA_addr == 0) { 4865 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n"); 4866 return False; 4867 } 4868 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4869 putIReg( rA_addr, mkexpr(EA) ); 4870 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 4871 break; 4872 4873 case 0x197: // sthx (Store HW Indexed, PPC32 p526) 4874 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4875 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 4876 break; 4877 4878 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535) 4879 if (rA_addr == 0) { 4880 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n"); 4881 return False; 4882 } 4883 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4884 putIReg( rA_addr, mkexpr(EA) ); 4885 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 4886 break; 4887 4888 case 0x097: // stwx (Store W Indexed, PPC32 p536) 4889 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4890 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 4891 break; 4892 4893 4894 /* 64bit Stores */ 4895 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584) 4896 if (rA_addr == 0) { 4897 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n"); 4898 return False; 4899 } 4900 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4901 putIReg( rA_addr, mkexpr(EA) ); 4902 storeBE( mkexpr(EA), mkexpr(rS) ); 4903 break; 4904 4905 case 0x095: // stdx (Store DWord Indexed, PPC64 p585) 4906 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 4907 storeBE( mkexpr(EA), mkexpr(rS) ); 4908 break; 4909 4910 default: 4911 vex_printf("dis_int_store(ppc)(opc2)\n"); 4912 return False; 4913 } 4914 break; 4915 4916 /* DS Form - 64bit Stores. In each case EA will have been formed 4917 with the lowest 2 bits masked off the immediate offset. */ 4918 case 0x3E: 4919 switch ((b1<<1) | b0) { 4920 case 0x0: // std (Store DWord, PPC64 p580) 4921 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4922 storeBE( mkexpr(EA), mkexpr(rS) ); 4923 break; 4924 4925 case 0x1: // stdu (Store DWord, Update, PPC64 p583) 4926 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4927 putIReg( rA_addr, mkexpr(EA) ); 4928 storeBE( mkexpr(EA), mkexpr(rS) ); 4929 break; 4930 4931 default: 4932 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 4933 return False; 4934 } 4935 break; 4936 4937 default: 4938 vex_printf("dis_int_store(ppc)(opc1)\n"); 4939 return False; 4940 } 4941 return True; 4942 } 4943 4944 4945 4946 /* 4947 Integer Load/Store Multiple Instructions 4948 */ 4949 static Bool dis_int_ldst_mult ( UInt theInstr ) 4950 { 4951 /* D-Form */ 4952 UChar opc1 = ifieldOPC(theInstr); 4953 UChar rD_addr = ifieldRegDS(theInstr); 4954 UChar rS_addr = rD_addr; 4955 UChar rA_addr = ifieldRegA(theInstr); 4956 UInt uimm16 = ifieldUIMM16(theInstr); 4957 4958 Int simm16 = extend_s_16to32(uimm16); 4959 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4960 IRTemp EA = newTemp(ty); 4961 UInt r = 0; 4962 UInt ea_off = 0; 4963 IRExpr* irx_addr; 4964 4965 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4966 4967 switch (opc1) { 4968 case 0x2E: // lmw (Load Multiple Word, PPC32 p454) 4969 if (rA_addr >= rD_addr) { 4970 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n"); 4971 return False; 4972 } 4973 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4974 for (r = rD_addr; r <= 31; r++) { 4975 irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off)); 4976 putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ), 4977 False) ); 4978 ea_off += 4; 4979 } 4980 break; 4981 4982 case 0x2F: // stmw (Store Multiple Word, PPC32 p527) 4983 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 4984 for (r = rS_addr; r <= 31; r++) { 4985 irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off)); 4986 storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) ); 4987 ea_off += 4; 4988 } 4989 break; 4990 4991 default: 4992 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n"); 4993 return False; 4994 } 4995 return True; 4996 } 4997 4998 4999 5000 /* 5001 Integer Load/Store String Instructions 5002 */ 5003 static 5004 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5005 IRTemp EA, // EA 5006 Int rD, // first dst register 5007 Int maxBytes ) // 32 or 128 5008 { 5009 Int i, shift = 24; 5010 IRExpr* e_nbytes = mkexpr(tNBytes); 5011 IRExpr* e_EA = mkexpr(EA); 5012 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5013 5014 vassert(rD >= 0 && rD < 32); 5015 rD--; if (rD < 0) rD = 31; 5016 5017 for (i = 0; i < maxBytes; i++) { 5018 /* if (nBytes < (i+1)) goto NIA; */ 5019 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5020 Ijk_Boring, 5021 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 5022 /* when crossing into a new dest register, set it to zero. */ 5023 if ((i % 4) == 0) { 5024 rD++; if (rD == 32) rD = 0; 5025 putIReg(rD, mkSzImm(ty, 0)); 5026 shift = 24; 5027 } 5028 /* rD |= (8Uto32(*(EA+i))) << shift */ 5029 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5030 putIReg( 5031 rD, 5032 mkWidenFrom32( 5033 ty, 5034 binop( 5035 Iop_Or32, 5036 mkNarrowTo32(ty, getIReg(rD)), 5037 binop( 5038 Iop_Shl32, 5039 unop( 5040 Iop_8Uto32, 5041 loadBE(Ity_I8, 5042 binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i))) 5043 ), 5044 mkU8(toUChar(shift)) 5045 ) 5046 ), 5047 /*Signed*/False 5048 ) 5049 ); 5050 shift -= 8; 5051 } 5052 } 5053 5054 static 5055 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5056 IRTemp EA, // EA 5057 Int rS, // first src register 5058 Int maxBytes ) // 32 or 128 5059 { 5060 Int i, shift = 24; 5061 IRExpr* e_nbytes = mkexpr(tNBytes); 5062 IRExpr* e_EA = mkexpr(EA); 5063 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5064 5065 vassert(rS >= 0 && rS < 32); 5066 rS--; if (rS < 0) rS = 31; 5067 5068 for (i = 0; i < maxBytes; i++) { 5069 /* if (nBytes < (i+1)) goto NIA; */ 5070 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5071 Ijk_Boring, 5072 mkSzConst( ty, nextInsnAddr() ), OFFB_CIA )); 5073 /* check for crossing into a new src register. */ 5074 if ((i % 4) == 0) { 5075 rS++; if (rS == 32) rS = 0; 5076 shift = 24; 5077 } 5078 /* *(EA+i) = 32to8(rS >> shift) */ 5079 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5080 storeBE( 5081 binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)), 5082 unop(Iop_32to8, 5083 binop(Iop_Shr32, 5084 mkNarrowTo32(ty, getIReg(rS)), 5085 mkU8(toUChar(shift)))) 5086 ); 5087 shift -= 8; 5088 } 5089 } 5090 5091 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) 5092 { 5093 /* X-Form */ 5094 UChar opc1 = ifieldOPC(theInstr); 5095 UChar rD_addr = ifieldRegDS(theInstr); 5096 UChar rS_addr = rD_addr; 5097 UChar rA_addr = ifieldRegA(theInstr); 5098 UChar rB_addr = ifieldRegB(theInstr); 5099 UChar NumBytes = rB_addr; 5100 UInt opc2 = ifieldOPClo10(theInstr); 5101 UChar b0 = ifieldBIT0(theInstr); 5102 5103 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5104 IRTemp t_EA = newTemp(ty); 5105 IRTemp t_nbytes = IRTemp_INVALID; 5106 5107 *stopHere = False; 5108 5109 if (opc1 != 0x1F || b0 != 0) { 5110 vex_printf("dis_int_ldst_str(ppc)(opc1)\n"); 5111 return False; 5112 } 5113 5114 switch (opc2) { 5115 case 0x255: // lswi (Load String Word Immediate, PPC32 p455) 5116 /* NB: does not reject the case where RA is in the range of 5117 registers to be loaded. It should. */ 5118 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes); 5119 assign( t_EA, ea_rAor0(rA_addr) ); 5120 if (NumBytes == 8 && !mode64) { 5121 /* Special case hack */ 5122 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */ 5123 putIReg( rD_addr, 5124 loadBE(Ity_I32, mkexpr(t_EA)) ); 5125 putIReg( (rD_addr+1) % 32, 5126 loadBE(Ity_I32, 5127 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) ); 5128 } else { 5129 t_nbytes = newTemp(Ity_I32); 5130 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5131 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5132 *stopHere = True; 5133 } 5134 return True; 5135 5136 case 0x215: // lswx (Load String Word Indexed, PPC32 p456) 5137 /* NB: does not reject the case where RA is in the range of 5138 registers to be loaded. It should. Although considering 5139 that that can only be detected at run time, it's not easy to 5140 do so. */ 5141 if (rD_addr == rA_addr || rD_addr == rB_addr) 5142 return False; 5143 if (rD_addr == 0 && rA_addr == 0) 5144 return False; 5145 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5146 t_nbytes = newTemp(Ity_I32); 5147 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5148 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5149 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 ); 5150 *stopHere = True; 5151 return True; 5152 5153 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528) 5154 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes); 5155 assign( t_EA, ea_rAor0(rA_addr) ); 5156 if (NumBytes == 8 && !mode64) { 5157 /* Special case hack */ 5158 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */ 5159 storeBE( mkexpr(t_EA), 5160 getIReg(rD_addr) ); 5161 storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)), 5162 getIReg((rD_addr+1) % 32) ); 5163 } else { 5164 t_nbytes = newTemp(Ity_I32); 5165 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5166 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5167 *stopHere = True; 5168 } 5169 return True; 5170 5171 case 0x295: // stswx (Store String Word Indexed, PPC32 p529) 5172 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5173 t_nbytes = newTemp(Ity_I32); 5174 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5175 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5176 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 ); 5177 *stopHere = True; 5178 return True; 5179 5180 default: 5181 vex_printf("dis_int_ldst_str(ppc)(opc2)\n"); 5182 return False; 5183 } 5184 return True; 5185 } 5186 5187 5188 /* ------------------------------------------------------------------ 5189 Integer Branch Instructions 5190 ------------------------------------------------------------------ */ 5191 5192 /* 5193 Branch helper function 5194 ok = BO[2] | ((CTR[0] != 0) ^ BO[1]) 5195 Returns an I32 which is 0x00000000 if the ctr condition failed 5196 and 0xFFFFFFFF otherwise. 5197 */ 5198 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO ) 5199 { 5200 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5201 IRTemp ok = newTemp(Ity_I32); 5202 5203 if ((BO >> 2) & 1) { // independent of ctr 5204 assign( ok, mkU32(0xFFFFFFFF) ); 5205 } else { 5206 if ((BO >> 1) & 1) { // ctr == 0 ? 5207 assign( ok, unop( Iop_1Sto32, 5208 binop( mkSzOp(ty, Iop_CmpEQ8), 5209 getGST( PPC_GST_CTR ), 5210 mkSzImm(ty,0))) ); 5211 } else { // ctr != 0 ? 5212 assign( ok, unop( Iop_1Sto32, 5213 binop( mkSzOp(ty, Iop_CmpNE8), 5214 getGST( PPC_GST_CTR ), 5215 mkSzImm(ty,0))) ); 5216 } 5217 } 5218 return mkexpr(ok); 5219 } 5220 5221 5222 /* 5223 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3]) 5224 Returns an I32 which is either 0 if the condition failed or 5225 some arbitrary nonzero value otherwise. */ 5226 5227 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) 5228 { 5229 Int where; 5230 IRTemp res = newTemp(Ity_I32); 5231 IRTemp cr_bi = newTemp(Ity_I32); 5232 5233 if ((BO >> 4) & 1) { 5234 assign( res, mkU32(1) ); 5235 } else { 5236 // ok = (CR[BI] == BO[3]) Note, the following relies on 5237 // getCRbit_anywhere returning a value which 5238 // is either zero or has exactly 1 bit set. 5239 assign( cr_bi, getCRbit_anywhere( BI, &where ) ); 5240 5241 if ((BO >> 3) & 1) { 5242 /* We can use cr_bi as-is. */ 5243 assign( res, mkexpr(cr_bi) ); 5244 } else { 5245 /* We have to invert the sense of the information held in 5246 cr_bi. For that we need to know which bit 5247 getCRbit_anywhere regards as significant. */ 5248 assign( res, binop(Iop_Xor32, mkexpr(cr_bi), 5249 mkU32(1<<where)) ); 5250 } 5251 } 5252 return mkexpr(res); 5253 } 5254 5255 5256 /* 5257 Integer Branch Instructions 5258 */ 5259 static Bool dis_branch ( UInt theInstr, 5260 VexAbiInfo* vbi, 5261 /*OUT*/DisResult* dres, 5262 Bool (*resteerOkFn)(void*,Addr64), 5263 void* callback_opaque ) 5264 { 5265 UChar opc1 = ifieldOPC(theInstr); 5266 UChar BO = ifieldRegDS(theInstr); 5267 UChar BI = ifieldRegA(theInstr); 5268 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */ 5269 UChar b11to15 = ifieldRegB(theInstr); 5270 UInt opc2 = ifieldOPClo10(theInstr); 5271 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */ 5272 UChar flag_AA = ifieldBIT1(theInstr); 5273 UChar flag_LK = ifieldBIT0(theInstr); 5274 5275 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5276 Addr64 tgt = 0; 5277 Int BD = extend_s_16to32(BD_u16); 5278 IRTemp do_branch = newTemp(Ity_I32); 5279 IRTemp ctr_ok = newTemp(Ity_I32); 5280 IRTemp cond_ok = newTemp(Ity_I32); 5281 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr()); 5282 IRConst* c_nia = mkSzConst(ty, nextInsnAddr()); 5283 IRTemp lr_old = newTemp(ty); 5284 5285 /* Hack to pass through code that just wants to read the PC */ 5286 if (theInstr == 0x429F0005) { 5287 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI); 5288 putGST( PPC_GST_LR, e_nia ); 5289 return True; 5290 } 5291 5292 /* The default what-next. Individual cases can override it. */ 5293 dres->whatNext = Dis_StopHere; 5294 vassert(dres->jk_StopHere == Ijk_INVALID); 5295 5296 switch (opc1) { 5297 case 0x12: // b (Branch, PPC32 p360) 5298 if (flag_AA) { 5299 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) ); 5300 } else { 5301 tgt = mkSzAddr( ty, guest_CIA_curr_instr + 5302 (Long)extend_s_26to64(LI_u26) ); 5303 } 5304 if (mode64) { 5305 DIP("b%s%s 0x%llx\n", 5306 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt); 5307 } else { 5308 DIP("b%s%s 0x%x\n", 5309 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt); 5310 } 5311 5312 if (flag_LK) { 5313 putGST( PPC_GST_LR, e_nia ); 5314 if (vbi->guest_ppc_zap_RZ_at_bl 5315 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) { 5316 IRTemp t_tgt = newTemp(ty); 5317 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) ); 5318 make_redzone_AbiHint( vbi, t_tgt, 5319 "branch-and-link (unconditional call)" ); 5320 } 5321 } 5322 5323 if (resteerOkFn( callback_opaque, tgt )) { 5324 dres->whatNext = Dis_ResteerU; 5325 dres->continueAt = tgt; 5326 } else { 5327 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ; 5328 putGST( PPC_GST_CIA, mkSzImm(ty, tgt) ); 5329 } 5330 break; 5331 5332 case 0x10: // bc (Branch Conditional, PPC32 p361) 5333 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", 5334 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); 5335 5336 if (!(BO & 0x4)) { 5337 putGST( PPC_GST_CTR, 5338 binop(mkSzOp(ty, Iop_Sub8), 5339 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5340 } 5341 5342 /* This is a bit subtle. ctr_ok is either all 0s or all 1s. 5343 cond_ok is either zero or nonzero, since that's the cheapest 5344 way to compute it. Anding them together gives a value which 5345 is either zero or non zero and so that's what we must test 5346 for in the IRStmt_Exit. */ 5347 assign( ctr_ok, branch_ctr_ok( BO ) ); 5348 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5349 assign( do_branch, 5350 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5351 5352 if (flag_AA) { 5353 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16)); 5354 } else { 5355 tgt = mkSzAddr(ty, guest_CIA_curr_instr + 5356 (Long)extend_s_16to64(BD_u16)); 5357 } 5358 if (flag_LK) 5359 putGST( PPC_GST_LR, e_nia ); 5360 5361 stmt( IRStmt_Exit( 5362 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)), 5363 flag_LK ? Ijk_Call : Ijk_Boring, 5364 mkSzConst(ty, tgt), OFFB_CIA ) ); 5365 5366 dres->jk_StopHere = Ijk_Boring; 5367 putGST( PPC_GST_CIA, e_nia ); 5368 break; 5369 5370 case 0x13: 5371 /* For bclr and bcctr, it appears that the lowest two bits of 5372 b11to15 are a branch hint, and so we only need to ensure it's 5373 of the form 000XX. */ 5374 if ((b11to15 & ~3) != 0) { 5375 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15); 5376 return False; 5377 } 5378 5379 switch (opc2) { 5380 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363) 5381 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid 5382 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n"); 5383 return False; 5384 } 5385 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5386 5387 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5388 5389 /* FIXME: this is confusing. lr_old holds the old value 5390 of ctr, not lr :-) */ 5391 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 )); 5392 5393 if (flag_LK) 5394 putGST( PPC_GST_LR, e_nia ); 5395 5396 stmt( IRStmt_Exit( 5397 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)), 5398 Ijk_Boring, 5399 c_nia, OFFB_CIA )); 5400 5401 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) { 5402 make_redzone_AbiHint( vbi, lr_old, 5403 "b-ctr-l (indirect call)" ); 5404 } 5405 5406 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;; 5407 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 5408 break; 5409 5410 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365) 5411 Bool vanilla_return = False; 5412 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) { 5413 DIP("blr\n"); 5414 vanilla_return = True; 5415 } else { 5416 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5417 } 5418 5419 if (!(BO & 0x4)) { 5420 putGST( PPC_GST_CTR, 5421 binop(mkSzOp(ty, Iop_Sub8), 5422 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5423 } 5424 5425 /* See comments above for 'bc' about this */ 5426 assign( ctr_ok, branch_ctr_ok( BO ) ); 5427 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5428 assign( do_branch, 5429 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5430 5431 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 )); 5432 5433 if (flag_LK) 5434 putGST( PPC_GST_LR, e_nia ); 5435 5436 stmt( IRStmt_Exit( 5437 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)), 5438 Ijk_Boring, 5439 c_nia, OFFB_CIA )); 5440 5441 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) { 5442 make_redzone_AbiHint( vbi, lr_old, 5443 "branch-to-lr (unconditional return)" ); 5444 } 5445 5446 /* blrl is pretty strange; it's like a return that sets the 5447 return address of its caller to the insn following this 5448 one. Mark it as a return. */ 5449 dres->jk_StopHere = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */ 5450 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 5451 break; 5452 } 5453 default: 5454 vex_printf("dis_int_branch(ppc)(opc2)\n"); 5455 return False; 5456 } 5457 break; 5458 5459 default: 5460 vex_printf("dis_int_branch(ppc)(opc1)\n"); 5461 return False; 5462 } 5463 5464 return True; 5465 } 5466 5467 5468 5469 /* 5470 Condition Register Logical Instructions 5471 */ 5472 static Bool dis_cond_logic ( UInt theInstr ) 5473 { 5474 /* XL-Form */ 5475 UChar opc1 = ifieldOPC(theInstr); 5476 UChar crbD_addr = ifieldRegDS(theInstr); 5477 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) ); 5478 UChar crbA_addr = ifieldRegA(theInstr); 5479 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) ); 5480 UChar crbB_addr = ifieldRegB(theInstr); 5481 UInt opc2 = ifieldOPClo10(theInstr); 5482 UChar b0 = ifieldBIT0(theInstr); 5483 5484 IRTemp crbD = newTemp(Ity_I32); 5485 IRTemp crbA = newTemp(Ity_I32); 5486 IRTemp crbB = newTemp(Ity_I32); 5487 5488 if (opc1 != 19 || b0 != 0) { 5489 vex_printf("dis_cond_logic(ppc)(opc1)\n"); 5490 return False; 5491 } 5492 5493 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464) 5494 if (((crbD_addr & 0x3) != 0) || 5495 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) { 5496 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n"); 5497 return False; 5498 } 5499 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr); 5500 putCR0( crfD_addr, getCR0( crfS_addr) ); 5501 putCR321( crfD_addr, getCR321(crfS_addr) ); 5502 } else { 5503 assign( crbA, getCRbit(crbA_addr) ); 5504 if (crbA_addr == crbB_addr) 5505 crbB = crbA; 5506 else 5507 assign( crbB, getCRbit(crbB_addr) ); 5508 5509 switch (opc2) { 5510 case 0x101: // crand (Cond Reg AND, PPC32 p372) 5511 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5512 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) ); 5513 break; 5514 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373) 5515 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5516 assign( crbD, binop(Iop_And32, 5517 mkexpr(crbA), 5518 unop(Iop_Not32, mkexpr(crbB))) ); 5519 break; 5520 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374) 5521 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5522 assign( crbD, unop(Iop_Not32, 5523 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) ); 5524 break; 5525 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375) 5526 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5527 assign( crbD, unop(Iop_Not32, 5528 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) ); 5529 break; 5530 case 0x021: // crnor (Cond Reg NOR, PPC32 p376) 5531 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5532 assign( crbD, unop(Iop_Not32, 5533 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) ); 5534 break; 5535 case 0x1C1: // cror (Cond Reg OR, PPC32 p377) 5536 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5537 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) ); 5538 break; 5539 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378) 5540 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5541 assign( crbD, binop(Iop_Or32, 5542 mkexpr(crbA), 5543 unop(Iop_Not32, mkexpr(crbB))) ); 5544 break; 5545 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379) 5546 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5547 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) ); 5548 break; 5549 default: 5550 vex_printf("dis_cond_logic(ppc)(opc2)\n"); 5551 return False; 5552 } 5553 5554 putCRbit( crbD_addr, mkexpr(crbD) ); 5555 } 5556 return True; 5557 } 5558 5559 5560 /* 5561 Trap instructions 5562 */ 5563 5564 /* Do the code generation for a trap. Returned Bool is true iff 5565 this is an unconditional trap. If the two arg IRExpr*s are 5566 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s 5567 then they are 64-bit, and we must be disassembling 64-bit 5568 instructions. */ 5569 static Bool do_trap ( UChar TO, 5570 IRExpr* argL0, IRExpr* argR0, Addr64 cia ) 5571 { 5572 IRTemp argL, argR; 5573 IRExpr *argLe, *argRe, *cond, *tmp; 5574 5575 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32; 5576 5577 IROp opAND = is32bit ? Iop_And32 : Iop_And64; 5578 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64; 5579 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S; 5580 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U; 5581 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64; 5582 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64; 5583 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0); 5584 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2); 5585 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4); 5586 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8); 5587 5588 const UChar b11100 = 0x1C; 5589 const UChar b00111 = 0x07; 5590 5591 if (is32bit) { 5592 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 ); 5593 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 ); 5594 } else { 5595 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 ); 5596 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 ); 5597 vassert( mode64 ); 5598 } 5599 5600 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) { 5601 /* Unconditional trap. Just do the exit without 5602 testing the arguments. */ 5603 stmt( IRStmt_Exit( 5604 binop(opCMPEQ, const0, const0), 5605 Ijk_SigTRAP, 5606 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 5607 OFFB_CIA 5608 )); 5609 return True; /* unconditional trap */ 5610 } 5611 5612 if (is32bit) { 5613 argL = newTemp(Ity_I32); 5614 argR = newTemp(Ity_I32); 5615 } else { 5616 argL = newTemp(Ity_I64); 5617 argR = newTemp(Ity_I64); 5618 } 5619 5620 assign( argL, argL0 ); 5621 assign( argR, argR0 ); 5622 5623 argLe = mkexpr(argL); 5624 argRe = mkexpr(argR); 5625 5626 cond = const0; 5627 if (TO & 16) { // L <s R 5628 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8); 5629 cond = binop(opOR, tmp, cond); 5630 } 5631 if (TO & 8) { // L >s R 5632 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4); 5633 cond = binop(opOR, tmp, cond); 5634 } 5635 if (TO & 4) { // L == R 5636 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2); 5637 cond = binop(opOR, tmp, cond); 5638 } 5639 if (TO & 2) { // L <u R 5640 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8); 5641 cond = binop(opOR, tmp, cond); 5642 } 5643 if (TO & 1) { // L >u R 5644 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4); 5645 cond = binop(opOR, tmp, cond); 5646 } 5647 stmt( IRStmt_Exit( 5648 binop(opCMPNE, cond, const0), 5649 Ijk_SigTRAP, 5650 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 5651 OFFB_CIA 5652 )); 5653 return False; /* not an unconditional trap */ 5654 } 5655 5656 static Bool dis_trapi ( UInt theInstr, 5657 /*OUT*/DisResult* dres ) 5658 { 5659 /* D-Form */ 5660 UChar opc1 = ifieldOPC(theInstr); 5661 UChar TO = ifieldRegDS(theInstr); 5662 UChar rA_addr = ifieldRegA(theInstr); 5663 UInt uimm16 = ifieldUIMM16(theInstr); 5664 ULong simm16 = extend_s_16to64(uimm16); 5665 Addr64 cia = guest_CIA_curr_instr; 5666 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5667 Bool uncond = False; 5668 5669 switch (opc1) { 5670 case 0x03: // twi (Trap Word Immediate, PPC32 p548) 5671 uncond = do_trap( TO, 5672 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 5673 : getIReg(rA_addr), 5674 mkU32( (UInt)simm16 ), 5675 cia ); 5676 if (TO == 4) { 5677 DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 5678 } else { 5679 DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 5680 } 5681 break; 5682 case 0x02: // tdi 5683 if (!mode64) 5684 return False; 5685 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia ); 5686 if (TO == 4) { 5687 DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 5688 } else { 5689 DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 5690 } 5691 break; 5692 default: 5693 return False; 5694 } 5695 5696 if (uncond) { 5697 /* If the trap shows signs of being unconditional, don't 5698 continue decoding past it. */ 5699 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 5700 dres->jk_StopHere = Ijk_Boring; 5701 dres->whatNext = Dis_StopHere; 5702 } 5703 5704 return True; 5705 } 5706 5707 static Bool dis_trap ( UInt theInstr, 5708 /*OUT*/DisResult* dres ) 5709 { 5710 /* X-Form */ 5711 UInt opc2 = ifieldOPClo10(theInstr); 5712 UChar TO = ifieldRegDS(theInstr); 5713 UChar rA_addr = ifieldRegA(theInstr); 5714 UChar rB_addr = ifieldRegB(theInstr); 5715 Addr64 cia = guest_CIA_curr_instr; 5716 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5717 Bool uncond = False; 5718 5719 if (ifieldBIT0(theInstr) != 0) 5720 return False; 5721 5722 switch (opc2) { 5723 case 0x004: // tw (Trap Word, PPC64 p540) 5724 uncond = do_trap( TO, 5725 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 5726 : getIReg(rA_addr), 5727 mode64 ? unop(Iop_64to32, getIReg(rB_addr)) 5728 : getIReg(rB_addr), 5729 cia ); 5730 if (TO == 4) { 5731 DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 5732 } else { 5733 DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 5734 } 5735 break; 5736 case 0x044: // td (Trap Doubleword, PPC64 p534) 5737 if (!mode64) 5738 return False; 5739 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia ); 5740 if (TO == 4) { 5741 DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 5742 } else { 5743 DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 5744 } 5745 break; 5746 default: 5747 return False; 5748 } 5749 5750 if (uncond) { 5751 /* If the trap shows signs of being unconditional, don't 5752 continue decoding past it. */ 5753 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 5754 dres->jk_StopHere = Ijk_Boring; 5755 dres->whatNext = Dis_StopHere; 5756 } 5757 5758 return True; 5759 } 5760 5761 5762 /* 5763 System Linkage Instructions 5764 */ 5765 static Bool dis_syslink ( UInt theInstr, 5766 VexAbiInfo* abiinfo, DisResult* dres ) 5767 { 5768 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5769 5770 if (theInstr != 0x44000002) { 5771 vex_printf("dis_syslink(ppc)(theInstr)\n"); 5772 return False; 5773 } 5774 5775 // sc (System Call, PPC32 p504) 5776 DIP("sc\n"); 5777 5778 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX 5779 Valgrind can back the guest up to this instruction if it needs 5780 to restart the syscall. */ 5781 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) ); 5782 5783 /* It's important that all ArchRegs carry their up-to-date value 5784 at this point. So we declare an end-of-block here, which 5785 forces any TempRegs caching ArchRegs to be flushed. */ 5786 putGST( PPC_GST_CIA, abiinfo->guest_ppc_sc_continues_at_LR 5787 ? getGST( PPC_GST_LR ) 5788 : mkSzImm( ty, nextInsnAddr() )); 5789 5790 dres->whatNext = Dis_StopHere; 5791 dres->jk_StopHere = Ijk_Sys_syscall; 5792 return True; 5793 } 5794 5795 5796 /* 5797 Memory Synchronization Instructions 5798 5799 Note on Reservations: 5800 We rely on the assumption that V will in fact only allow one thread at 5801 once to run. In effect, a thread can make a reservation, but we don't 5802 check any stores it does. Instead, the reservation is cancelled when 5803 the scheduler switches to another thread (run_thread_for_a_while()). 5804 */ 5805 static Bool dis_memsync ( UInt theInstr ) 5806 { 5807 /* X-Form, XL-Form */ 5808 UChar opc1 = ifieldOPC(theInstr); 5809 UInt b11to25 = IFIELD(theInstr, 11, 15); 5810 UChar flag_L = ifieldRegDS(theInstr); 5811 UInt b11to20 = IFIELD(theInstr, 11, 10); 5812 UChar rD_addr = ifieldRegDS(theInstr); 5813 UChar rS_addr = rD_addr; 5814 UChar rA_addr = ifieldRegA(theInstr); 5815 UChar rB_addr = ifieldRegB(theInstr); 5816 UInt opc2 = ifieldOPClo10(theInstr); 5817 UChar b0 = ifieldBIT0(theInstr); 5818 5819 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5820 IRTemp EA = newTemp(ty); 5821 5822 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 5823 5824 switch (opc1) { 5825 /* XL-Form */ 5826 case 0x13: // isync (Instruction Synchronize, PPC32 p432) 5827 if (opc2 != 0x096) { 5828 vex_printf("dis_memsync(ppc)(0x13,opc2)\n"); 5829 return False; 5830 } 5831 if (b11to25 != 0 || b0 != 0) { 5832 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n"); 5833 return False; 5834 } 5835 DIP("isync\n"); 5836 stmt( IRStmt_MBE(Imbe_Fence) ); 5837 break; 5838 5839 /* X-Form */ 5840 case 0x1F: 5841 switch (opc2) { 5842 case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394) 5843 if (b11to25 != 0 || b0 != 0) { 5844 vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n"); 5845 return False; 5846 } 5847 DIP("eieio\n"); 5848 /* Insert a memory fence, just to be on the safe side. */ 5849 stmt( IRStmt_MBE(Imbe_Fence) ); 5850 break; 5851 5852 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458) 5853 IRTemp res; 5854 /* According to the PowerPC ISA version 2.05, b0 (called EH 5855 in the documentation) is merely a hint bit to the 5856 hardware, I think as to whether or not contention is 5857 likely. So we can just ignore it. */ 5858 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 5859 5860 // trap if misaligned 5861 gen_SIGBUS_if_misaligned( EA, 4 ); 5862 5863 // and actually do the load 5864 res = newTemp(Ity_I32); 5865 stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) ); 5866 5867 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) ); 5868 break; 5869 } 5870 5871 case 0x096: { 5872 // stwcx. (Store Word Conditional Indexed, PPC32 p532) 5873 // Note this has to handle stwcx. in both 32- and 64-bit modes, 5874 // so isn't quite as straightforward as it might otherwise be. 5875 IRTemp rS = newTemp(Ity_I32); 5876 IRTemp resSC; 5877 if (b0 != 1) { 5878 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 5879 return False; 5880 } 5881 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5882 5883 // trap if misaligned 5884 gen_SIGBUS_if_misaligned( EA, 4 ); 5885 5886 // Get the data to be stored, and narrow to 32 bits if necessary 5887 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) ); 5888 5889 // Do the store, and get success/failure bit into resSC 5890 resSC = newTemp(Ity_I1); 5891 stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) ); 5892 5893 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 5894 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 5895 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 5896 putCR0(0, getXER_SO()); 5897 5898 /* Note: 5899 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 5900 whether rS is stored is dependent on that value. */ 5901 /* So I guess we can just ignore this case? */ 5902 break; 5903 } 5904 5905 case 0x256: // sync (Synchronize, PPC32 p543), 5906 // also lwsync (L==1), ptesync (L==2) 5907 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html 5908 5909 The PowerPC architecture used in IBM chips has expanded 5910 the sync instruction into two variants: lightweight sync 5911 and heavyweight sync. The original sync instruction is 5912 the new heavyweight sync and lightweight sync is a strict 5913 subset of the heavyweight sync functionality. This allows 5914 the programmer to specify a less expensive operation on 5915 high-end systems when the full sync functionality is not 5916 necessary. 5917 5918 The basic "sync" mnemonic now utilizes an operand. "sync" 5919 without an operand now becomes a extended mnemonic for 5920 heavyweight sync. Processors without the lwsync 5921 instruction will not decode the L field and will perform a 5922 heavyweight sync. Everything is backward compatible. 5923 5924 sync = sync 0 5925 lwsync = sync 1 5926 ptesync = sync 2 *** TODO - not implemented *** 5927 */ 5928 if (b11to20 != 0 || b0 != 0) { 5929 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n"); 5930 return False; 5931 } 5932 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) { 5933 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n"); 5934 return False; 5935 } 5936 DIP("%ssync\n", flag_L == 1 ? "lw" : ""); 5937 /* Insert a memory fence. It's sometimes important that these 5938 are carried through to the generated code. */ 5939 stmt( IRStmt_MBE(Imbe_Fence) ); 5940 break; 5941 5942 /* 64bit Memsync */ 5943 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473) 5944 IRTemp res; 5945 /* According to the PowerPC ISA version 2.05, b0 (called EH 5946 in the documentation) is merely a hint bit to the 5947 hardware, I think as to whether or not contention is 5948 likely. So we can just ignore it. */ 5949 if (!mode64) 5950 return False; 5951 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 5952 5953 // trap if misaligned 5954 gen_SIGBUS_if_misaligned( EA, 8 ); 5955 5956 // and actually do the load 5957 res = newTemp(Ity_I64); 5958 stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) ); 5959 5960 putIReg( rD_addr, mkexpr(res) ); 5961 break; 5962 } 5963 5964 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581) 5965 // A marginally simplified version of the stwcx. case 5966 IRTemp rS = newTemp(Ity_I64); 5967 IRTemp resSC; 5968 if (b0 != 1) { 5969 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n"); 5970 return False; 5971 } 5972 if (!mode64) 5973 return False; 5974 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5975 5976 // trap if misaligned 5977 gen_SIGBUS_if_misaligned( EA, 8 ); 5978 5979 // Get the data to be stored 5980 assign( rS, getIReg(rS_addr) ); 5981 5982 // Do the store, and get success/failure bit into resSC 5983 resSC = newTemp(Ity_I1); 5984 stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) ); 5985 5986 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 5987 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 5988 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 5989 putCR0(0, getXER_SO()); 5990 5991 /* Note: 5992 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 5993 whether rS is stored is dependent on that value. */ 5994 /* So I guess we can just ignore this case? */ 5995 break; 5996 } 5997 5998 default: 5999 vex_printf("dis_memsync(ppc)(opc2)\n"); 6000 return False; 6001 } 6002 break; 6003 6004 default: 6005 vex_printf("dis_memsync(ppc)(opc1)\n"); 6006 return False; 6007 } 6008 return True; 6009 } 6010 6011 6012 6013 /* 6014 Integer Shift Instructions 6015 */ 6016 static Bool dis_int_shift ( UInt theInstr ) 6017 { 6018 /* X-Form, XS-Form */ 6019 UChar opc1 = ifieldOPC(theInstr); 6020 UChar rS_addr = ifieldRegDS(theInstr); 6021 UChar rA_addr = ifieldRegA(theInstr); 6022 UChar rB_addr = ifieldRegB(theInstr); 6023 UChar sh_imm = rB_addr; 6024 UInt opc2 = ifieldOPClo10(theInstr); 6025 UChar b1 = ifieldBIT1(theInstr); 6026 UChar flag_rC = ifieldBIT0(theInstr); 6027 6028 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6029 IRTemp rA = newTemp(ty); 6030 IRTemp rS = newTemp(ty); 6031 IRTemp rB = newTemp(ty); 6032 IRTemp outofrange = newTemp(Ity_I8); 6033 IRTemp rS_lo32 = newTemp(Ity_I32); 6034 IRTemp rB_lo32 = newTemp(Ity_I32); 6035 IRExpr* e_tmp; 6036 6037 assign( rS, getIReg(rS_addr) ); 6038 assign( rB, getIReg(rB_addr) ); 6039 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) ); 6040 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) ); 6041 6042 if (opc1 == 0x1F) { 6043 switch (opc2) { 6044 case 0x018: { // slw (Shift Left Word, PPC32 p505) 6045 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6046 rA_addr, rS_addr, rB_addr); 6047 /* rA = rS << rB */ 6048 /* ppc32 semantics are: 6049 slw(x,y) = (x << (y & 31)) -- primary result 6050 & ~((y << 26) >>s 31) -- make result 0 6051 for y in 32 .. 63 6052 */ 6053 e_tmp = 6054 binop( Iop_And32, 6055 binop( Iop_Shl32, 6056 mkexpr(rS_lo32), 6057 unop( Iop_32to8, 6058 binop(Iop_And32, 6059 mkexpr(rB_lo32), mkU32(31)))), 6060 unop( Iop_Not32, 6061 binop( Iop_Sar32, 6062 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)), 6063 mkU8(31))) ); 6064 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6065 break; 6066 } 6067 6068 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506) 6069 IRTemp sh_amt = newTemp(Ity_I32); 6070 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6071 rA_addr, rS_addr, rB_addr); 6072 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is: 6073 amt = rB & 63 6074 rA = Sar32( rS, amt > 31 ? 31 : amt ) 6075 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi) 6076 */ 6077 assign( sh_amt, binop(Iop_And32, mkU32(0x3F), 6078 mkexpr(rB_lo32)) ); 6079 assign( outofrange, 6080 unop( Iop_1Uto8, 6081 binop(Iop_CmpLT32U, mkU32(31), 6082 mkexpr(sh_amt)) )); 6083 e_tmp = binop( Iop_Sar32, 6084 mkexpr(rS_lo32), 6085 unop( Iop_32to8, 6086 IRExpr_Mux0X( mkexpr(outofrange), 6087 mkexpr(sh_amt), 6088 mkU32(31)) ) ); 6089 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) ); 6090 6091 set_XER_CA( ty, PPCG_FLAG_OP_SRAW, 6092 mkexpr(rA), 6093 mkWidenFrom32(ty, mkexpr(rS_lo32), True), 6094 mkWidenFrom32(ty, mkexpr(sh_amt), True ), 6095 mkWidenFrom32(ty, getXER_CA32(), True) ); 6096 break; 6097 } 6098 6099 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507) 6100 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"", 6101 rA_addr, rS_addr, sh_imm); 6102 vassert(sh_imm < 32); 6103 if (mode64) { 6104 assign( rA, binop(Iop_Sar64, 6105 binop(Iop_Shl64, getIReg(rS_addr), 6106 mkU8(32)), 6107 mkU8(32 + sh_imm)) ); 6108 } else { 6109 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32), 6110 mkU8(sh_imm)) ); 6111 } 6112 6113 set_XER_CA( ty, PPCG_FLAG_OP_SRAWI, 6114 mkexpr(rA), 6115 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True), 6116 mkSzImm(ty, sh_imm), 6117 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6118 break; 6119 6120 case 0x218: // srw (Shift Right Word, PPC32 p508) 6121 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6122 rA_addr, rS_addr, rB_addr); 6123 /* rA = rS >>u rB */ 6124 /* ppc32 semantics are: 6125 srw(x,y) = (x >>u (y & 31)) -- primary result 6126 & ~((y << 26) >>s 31) -- make result 0 6127 for y in 32 .. 63 6128 */ 6129 e_tmp = 6130 binop( 6131 Iop_And32, 6132 binop( Iop_Shr32, 6133 mkexpr(rS_lo32), 6134 unop( Iop_32to8, 6135 binop(Iop_And32, mkexpr(rB_lo32), 6136 mkU32(31)))), 6137 unop( Iop_Not32, 6138 binop( Iop_Sar32, 6139 binop(Iop_Shl32, mkexpr(rB_lo32), 6140 mkU8(26)), 6141 mkU8(31)))); 6142 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6143 break; 6144 6145 6146 /* 64bit Shifts */ 6147 case 0x01B: // sld (Shift Left DWord, PPC64 p568) 6148 DIP("sld%s r%u,r%u,r%u\n", 6149 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6150 /* rA = rS << rB */ 6151 /* ppc64 semantics are: 6152 slw(x,y) = (x << (y & 63)) -- primary result 6153 & ~((y << 57) >>s 63) -- make result 0 6154 for y in 64 .. 6155 */ 6156 assign( rA, 6157 binop( 6158 Iop_And64, 6159 binop( Iop_Shl64, 6160 mkexpr(rS), 6161 unop( Iop_64to8, 6162 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6163 unop( Iop_Not64, 6164 binop( Iop_Sar64, 6165 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6166 mkU8(63)))) ); 6167 break; 6168 6169 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570) 6170 IRTemp sh_amt = newTemp(Ity_I64); 6171 DIP("srad%s r%u,r%u,r%u\n", 6172 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6173 /* amt = rB & 127 6174 rA = Sar64( rS, amt > 63 ? 63 : amt ) 6175 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi) 6176 */ 6177 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) ); 6178 assign( outofrange, 6179 unop( Iop_1Uto8, 6180 binop(Iop_CmpLT64U, mkU64(63), 6181 mkexpr(sh_amt)) )); 6182 assign( rA, 6183 binop( Iop_Sar64, 6184 mkexpr(rS), 6185 unop( Iop_64to8, 6186 IRExpr_Mux0X( mkexpr(outofrange), 6187 mkexpr(sh_amt), 6188 mkU64(63)) )) 6189 ); 6190 set_XER_CA( ty, PPCG_FLAG_OP_SRAD, 6191 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt), 6192 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6193 break; 6194 } 6195 6196 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571) 6197 sh_imm |= b1<<5; 6198 vassert(sh_imm < 64); 6199 DIP("sradi%s r%u,r%u,%u\n", 6200 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 6201 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) ); 6202 6203 set_XER_CA( ty, PPCG_FLAG_OP_SRADI, 6204 mkexpr(rA), 6205 getIReg(rS_addr), 6206 mkU64(sh_imm), 6207 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6208 break; 6209 6210 case 0x21B: // srd (Shift Right DWord, PPC64 p574) 6211 DIP("srd%s r%u,r%u,r%u\n", 6212 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6213 /* rA = rS >>u rB */ 6214 /* ppc semantics are: 6215 srw(x,y) = (x >>u (y & 63)) -- primary result 6216 & ~((y << 57) >>s 63) -- make result 0 6217 for y in 64 .. 127 6218 */ 6219 assign( rA, 6220 binop( 6221 Iop_And64, 6222 binop( Iop_Shr64, 6223 mkexpr(rS), 6224 unop( Iop_64to8, 6225 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6226 unop( Iop_Not64, 6227 binop( Iop_Sar64, 6228 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6229 mkU8(63)))) ); 6230 break; 6231 6232 default: 6233 vex_printf("dis_int_shift(ppc)(opc2)\n"); 6234 return False; 6235 } 6236 } else { 6237 vex_printf("dis_int_shift(ppc)(opc1)\n"); 6238 return False; 6239 } 6240 6241 putIReg( rA_addr, mkexpr(rA) ); 6242 6243 if (flag_rC) { 6244 set_CR0( mkexpr(rA) ); 6245 } 6246 return True; 6247 } 6248 6249 6250 6251 /* 6252 Integer Load/Store Reverse Instructions 6253 */ 6254 /* Generates code to swap the byte order in an Ity_I32. */ 6255 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t ) 6256 { 6257 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 6258 return 6259 binop(Iop_Or32, 6260 binop(Iop_Shl32, mkexpr(t), mkU8(24)), 6261 binop(Iop_Or32, 6262 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 6263 mkU32(0x00FF0000)), 6264 binop(Iop_Or32, 6265 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 6266 mkU32(0x0000FF00)), 6267 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)), 6268 mkU32(0x000000FF) ) 6269 ))); 6270 } 6271 6272 /* Generates code to swap the byte order in the lower half of an Ity_I32, 6273 and zeroes the upper half. */ 6274 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t ) 6275 { 6276 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 6277 return 6278 binop(Iop_Or32, 6279 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 6280 mkU32(0x0000FF00)), 6281 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 6282 mkU32(0x000000FF)) 6283 ); 6284 } 6285 6286 static Bool dis_int_ldst_rev ( UInt theInstr ) 6287 { 6288 /* X-Form */ 6289 UChar opc1 = ifieldOPC(theInstr); 6290 UChar rD_addr = ifieldRegDS(theInstr); 6291 UChar rS_addr = rD_addr; 6292 UChar rA_addr = ifieldRegA(theInstr); 6293 UChar rB_addr = ifieldRegB(theInstr); 6294 UInt opc2 = ifieldOPClo10(theInstr); 6295 UChar b0 = ifieldBIT0(theInstr); 6296 6297 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6298 IRTemp EA = newTemp(ty); 6299 IRTemp w1 = newTemp(Ity_I32); 6300 IRTemp w2 = newTemp(Ity_I32); 6301 6302 if (opc1 != 0x1F || b0 != 0) { 6303 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n"); 6304 return False; 6305 } 6306 6307 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6308 6309 switch (opc2) { 6310 6311 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449) 6312 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6313 assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) ); 6314 assign( w2, gen_byterev16(w1) ); 6315 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 6316 /* Signed */False) ); 6317 break; 6318 6319 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459) 6320 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6321 assign( w1, loadBE(Ity_I32, mkexpr(EA)) ); 6322 assign( w2, gen_byterev32(w1) ); 6323 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 6324 /* Signed */False) ); 6325 break; 6326 6327 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed) 6328 { 6329 IRExpr * nextAddr; 6330 IRTemp w3 = newTemp( Ity_I32 ); 6331 IRTemp w4 = newTemp( Ity_I32 ); 6332 DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6333 assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) ); 6334 assign( w2, gen_byterev32( w1 ) ); 6335 nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 6336 ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) ); 6337 assign( w3, loadBE( Ity_I32, nextAddr ) ); 6338 assign( w4, gen_byterev32( w3 ) ); 6339 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) ); 6340 break; 6341 } 6342 6343 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523) 6344 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6345 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6346 storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) ); 6347 break; 6348 6349 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531) 6350 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6351 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6352 storeBE( mkexpr(EA), gen_byterev32(w1) ); 6353 break; 6354 6355 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed) 6356 { 6357 IRTemp lo = newTemp(Ity_I32); 6358 IRTemp hi = newTemp(Ity_I32); 6359 IRTemp rS = newTemp(Ity_I64); 6360 assign( rS, getIReg( rS_addr ) ); 6361 DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6362 assign(lo, unop(Iop_64HIto32, mkexpr(rS))); 6363 assign(hi, unop(Iop_64to32, mkexpr(rS))); 6364 storeBE( mkexpr( EA ), 6365 binop( Iop_32HLto64, gen_byterev32( hi ), gen_byterev32( lo ) ) ); 6366 break; 6367 } 6368 6369 default: 6370 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n"); 6371 return False; 6372 } 6373 return True; 6374 } 6375 6376 6377 6378 /* 6379 Processor Control Instructions 6380 */ 6381 static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr ) 6382 { 6383 UChar opc1 = ifieldOPC(theInstr); 6384 6385 /* X-Form */ 6386 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 6387 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 6388 UChar rD_addr = ifieldRegDS(theInstr); 6389 UInt b11to20 = IFIELD( theInstr, 11, 10 ); 6390 6391 /* XFX-Form */ 6392 UChar rS_addr = rD_addr; 6393 UInt SPR = b11to20; 6394 UInt TBR = b11to20; 6395 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) ); 6396 UInt CRM = IFIELD( theInstr, 12, 8 ); 6397 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 6398 6399 UInt opc2 = ifieldOPClo10(theInstr); 6400 UChar b0 = ifieldBIT0(theInstr); 6401 6402 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6403 IRTemp rS = newTemp(ty); 6404 assign( rS, getIReg(rS_addr) ); 6405 6406 /* Reorder SPR field as per PPC32 p470 */ 6407 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); 6408 /* Reorder TBR field as per PPC32 p475 */ 6409 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31); 6410 6411 if (opc1 != 0x1F || b0 != 0) { 6412 vex_printf("dis_proc_ctl(ppc)(opc1|b0)\n"); 6413 return False; 6414 } 6415 6416 switch (opc2) { 6417 /* X-Form */ 6418 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466) 6419 if (b21to22 != 0 || b11to20 != 0) { 6420 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n"); 6421 return False; 6422 } 6423 DIP("mcrxr crf%d\n", crfD); 6424 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */ 6425 putGST_field( PPC_GST_CR, 6426 getGST_field( PPC_GST_XER, 7 ), 6427 crfD ); 6428 6429 // Clear XER[0-3] 6430 putXER_SO( mkU8(0) ); 6431 putXER_OV( mkU8(0) ); 6432 putXER_CA( mkU8(0) ); 6433 break; 6434 } 6435 6436 case 0x013: 6437 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467) 6438 // b20==1 & b11==0: mfocrf (Move from One CR Field) 6439 // However it seems that the 'mfcr' behaviour is an acceptable 6440 // implementation of mfocr (from the 2.02 arch spec) 6441 if (b11to20 == 0) { 6442 DIP("mfcr r%u\n", rD_addr); 6443 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 6444 /* Signed */False) ); 6445 break; 6446 } 6447 if (b20 == 1 && b11 == 0) { 6448 DIP("mfocrf r%u,%u\n", rD_addr, CRM); 6449 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 6450 /* Signed */False) ); 6451 break; 6452 } 6453 /* not decodable */ 6454 return False; 6455 6456 /* XFX-Form */ 6457 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470) 6458 6459 switch (SPR) { // Choose a register... 6460 case 0x1: 6461 DIP("mfxer r%u\n", rD_addr); 6462 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ), 6463 /* Signed */False) ); 6464 break; 6465 case 0x8: 6466 DIP("mflr r%u\n", rD_addr); 6467 putIReg( rD_addr, getGST( PPC_GST_LR ) ); 6468 break; 6469 case 0x9: 6470 DIP("mfctr r%u\n", rD_addr); 6471 putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 6472 break; 6473 case 0x100: 6474 DIP("mfvrsave r%u\n", rD_addr); 6475 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ), 6476 /* Signed */False) ); 6477 break; 6478 6479 case 0x103: 6480 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr); 6481 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) ); 6482 break; 6483 6484 /* Even a lowly PPC7400 can run the associated helper, so no 6485 obvious need for feature testing at this point. */ 6486 case 268 /* 0x10C */: 6487 case 269 /* 0x10D */: { 6488 UInt arg = SPR==268 ? 0 : 1; 6489 IRTemp val = newTemp(Ity_I32); 6490 IRExpr** args = mkIRExprVec_1( mkU32(arg) ); 6491 IRDirty* d = unsafeIRDirty_1_N( 6492 val, 6493 0/*regparms*/, 6494 "ppc32g_dirtyhelper_MFSPR_268_269", 6495 fnptr_to_fnentry 6496 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269), 6497 args 6498 ); 6499 /* execute the dirty call, dumping the result in val. */ 6500 stmt( IRStmt_Dirty(d) ); 6501 putIReg( rD_addr, 6502 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 6503 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 6504 break; 6505 } 6506 6507 /* Again, runs natively on PPC7400 (7447, really). Not 6508 bothering with a feature test. */ 6509 case 287: /* 0x11F */ { 6510 IRTemp val = newTemp(Ity_I32); 6511 IRExpr** args = mkIRExprVec_0(); 6512 IRDirty* d = unsafeIRDirty_1_N( 6513 val, 6514 0/*regparms*/, 6515 "ppc32g_dirtyhelper_MFSPR_287", 6516 fnptr_to_fnentry 6517 (vbi, &ppc32g_dirtyhelper_MFSPR_287), 6518 args 6519 ); 6520 /* execute the dirty call, dumping the result in val. */ 6521 stmt( IRStmt_Dirty(d) ); 6522 putIReg( rD_addr, 6523 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 6524 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 6525 break; 6526 } 6527 6528 default: 6529 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR); 6530 return False; 6531 } 6532 break; 6533 6534 case 0x173: { // mftb (Move from Time Base, PPC32 p475) 6535 IRTemp val = newTemp(Ity_I64); 6536 IRExpr** args = mkIRExprVec_0(); 6537 IRDirty* d = unsafeIRDirty_1_N( 6538 val, 6539 0/*regparms*/, 6540 "ppcg_dirtyhelper_MFTB", 6541 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB), 6542 args ); 6543 /* execute the dirty call, dumping the result in val. */ 6544 stmt( IRStmt_Dirty(d) ); 6545 6546 switch (TBR) { 6547 case 269: 6548 DIP("mftbu r%u", rD_addr); 6549 putIReg( rD_addr, 6550 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)), 6551 /* Signed */False) ); 6552 break; 6553 case 268: 6554 DIP("mftb r%u", rD_addr); 6555 putIReg( rD_addr, (mode64) ? mkexpr(val) : 6556 unop(Iop_64to32, mkexpr(val)) ); 6557 break; 6558 default: 6559 return False; /* illegal instruction */ 6560 } 6561 break; 6562 } 6563 6564 case 0x090: { 6565 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477) 6566 // b20==1: mtocrf (Move to One Cond Reg Field) 6567 Int cr; 6568 UChar shft; 6569 if (b11 != 0) 6570 return False; 6571 if (b20 == 1) { 6572 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if > 6573 1 field is written. It seems more robust to decline to 6574 decode the insn if so. */ 6575 switch (CRM) { 6576 case 0x01: case 0x02: case 0x04: case 0x08: 6577 case 0x10: case 0x20: case 0x40: case 0x80: 6578 break; 6579 default: 6580 return False; 6581 } 6582 } 6583 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf", 6584 CRM, rS_addr); 6585 /* Write to each field specified by CRM */ 6586 for (cr = 0; cr < 8; cr++) { 6587 if ((CRM & (1 << (7-cr))) == 0) 6588 continue; 6589 shft = 4*(7-cr); 6590 putGST_field( PPC_GST_CR, 6591 binop(Iop_Shr32, 6592 mkNarrowTo32(ty, mkexpr(rS)), 6593 mkU8(shft)), cr ); 6594 } 6595 break; 6596 } 6597 6598 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483) 6599 6600 switch (SPR) { // Choose a register... 6601 case 0x1: 6602 DIP("mtxer r%u\n", rS_addr); 6603 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) ); 6604 break; 6605 case 0x8: 6606 DIP("mtlr r%u\n", rS_addr); 6607 putGST( PPC_GST_LR, mkexpr(rS) ); 6608 break; 6609 case 0x9: 6610 DIP("mtctr r%u\n", rS_addr); 6611 putGST( PPC_GST_CTR, mkexpr(rS) ); 6612 break; 6613 case 0x100: 6614 DIP("mtvrsave r%u\n", rS_addr); 6615 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) ); 6616 break; 6617 6618 default: 6619 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR); 6620 return False; 6621 } 6622 break; 6623 6624 default: 6625 vex_printf("dis_proc_ctl(ppc)(opc2)\n"); 6626 return False; 6627 } 6628 return True; 6629 } 6630 6631 6632 /* 6633 Cache Management Instructions 6634 */ 6635 static Bool dis_cache_manage ( UInt theInstr, 6636 DisResult* dres, 6637 VexArchInfo* guest_archinfo ) 6638 { 6639 /* X-Form */ 6640 UChar opc1 = ifieldOPC(theInstr); 6641 UChar b21to25 = ifieldRegDS(theInstr); 6642 UChar rA_addr = ifieldRegA(theInstr); 6643 UChar rB_addr = ifieldRegB(theInstr); 6644 UInt opc2 = ifieldOPClo10(theInstr); 6645 UChar b0 = ifieldBIT0(theInstr); 6646 UInt lineszB = guest_archinfo->ppc_cache_line_szB; 6647 Bool is_dcbzl = False; 6648 6649 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6650 6651 /* For dcbt, the lowest two bits of b21to25 encode an 6652 access-direction hint (TH field) which we ignore. Well, that's 6653 what the PowerPC documentation says. In fact xlc -O4 on POWER5 6654 seems to generate values of 8 and 10 for b21to25. */ 6655 if (opc1 == 0x1F && opc2 == 0x116) { 6656 /* b21to25 &= ~3; */ /* if the docs were true */ 6657 b21to25 = 0; /* blunt instrument */ 6658 } 6659 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz 6660 if (b21to25 == 1) { 6661 is_dcbzl = True; 6662 b21to25 = 0; 6663 if (!(guest_archinfo->ppc_dcbzl_szB)) { 6664 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n"); 6665 return False; 6666 } 6667 } 6668 } 6669 6670 if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) { 6671 if (0) vex_printf("dis_cache_manage %d %d %d\n", 6672 (Int)opc1, (Int)b21to25, (Int)b0); 6673 vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n"); 6674 return False; 6675 } 6676 6677 /* stay sane .. */ 6678 vassert(lineszB == 32 || lineszB == 64 || lineszB == 128); 6679 6680 switch (opc2) { 6681 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380) 6682 //zz vassert(0); /* AWAITING TEST CASE */ 6683 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr); 6684 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n"); 6685 //zz break; 6686 6687 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382) 6688 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr); 6689 /* nop as far as vex is concerned */ 6690 break; 6691 6692 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384) 6693 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr); 6694 /* nop as far as vex is concerned */ 6695 break; 6696 6697 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385) 6698 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr); 6699 /* nop as far as vex is concerned */ 6700 break; 6701 6702 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386) 6703 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr); 6704 /* nop as far as vex is concerned */ 6705 break; 6706 6707 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387) 6708 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264) 6709 /* Clear all bytes in cache block at (rA|0) + rB. */ 6710 IRTemp EA = newTemp(ty); 6711 IRTemp addr = newTemp(ty); 6712 IRExpr* irx_addr; 6713 UInt i; 6714 UInt clearszB; 6715 if (is_dcbzl) { 6716 clearszB = guest_archinfo->ppc_dcbzl_szB; 6717 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr); 6718 } 6719 else { 6720 clearszB = guest_archinfo->ppc_dcbz_szB; 6721 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr); 6722 } 6723 6724 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6725 6726 if (mode64) { 6727 /* Round EA down to the start of the containing block. */ 6728 assign( addr, binop( Iop_And64, 6729 mkexpr(EA), 6730 mkU64( ~((ULong)clearszB-1) )) ); 6731 6732 for (i = 0; i < clearszB / 8; i++) { 6733 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) ); 6734 storeBE( irx_addr, mkU64(0) ); 6735 } 6736 } else { 6737 /* Round EA down to the start of the containing block. */ 6738 assign( addr, binop( Iop_And32, 6739 mkexpr(EA), 6740 mkU32( ~(clearszB-1) )) ); 6741 6742 for (i = 0; i < clearszB / 4; i++) { 6743 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) ); 6744 storeBE( irx_addr, mkU32(0) ); 6745 } 6746 } 6747 break; 6748 } 6749 6750 case 0x3D6: { 6751 // icbi (Instruction Cache Block Invalidate, PPC32 p431) 6752 /* Invalidate all translations containing code from the cache 6753 block at (rA|0) + rB. */ 6754 IRTemp EA = newTemp(ty); 6755 IRTemp addr = newTemp(ty); 6756 DIP("icbi r%u,r%u\n", rA_addr, rB_addr); 6757 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 6758 6759 /* Round EA down to the start of the containing block. */ 6760 assign( addr, binop( mkSzOp(ty, Iop_And8), 6761 mkexpr(EA), 6762 mkSzImm(ty, ~(((ULong)lineszB)-1) )) ); 6763 putGST( PPC_GST_TISTART, mkexpr(addr) ); 6764 putGST( PPC_GST_TILEN, mkSzImm(ty, lineszB) ); 6765 6766 /* be paranoid ... */ 6767 stmt( IRStmt_MBE(Imbe_Fence) ); 6768 6769 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr())); 6770 dres->jk_StopHere = Ijk_TInval; 6771 dres->whatNext = Dis_StopHere; 6772 break; 6773 } 6774 6775 default: 6776 vex_printf("dis_cache_manage(ppc)(opc2)\n"); 6777 return False; 6778 } 6779 return True; 6780 } 6781 6782 6783 /*------------------------------------------------------------*/ 6784 /*--- Floating Point Helpers ---*/ 6785 /*------------------------------------------------------------*/ 6786 6787 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */ 6788 /* Produces a value in 0 .. 3, which is encoded as per the type 6789 IRRoundingMode. PPCRoundingMode encoding is different to 6790 IRRoundingMode, so need to map it. 6791 */ 6792 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void ) 6793 { 6794 /* 6795 rounding mode | PPC | IR 6796 ------------------------ 6797 to nearest | 00 | 00 6798 to zero | 01 | 11 6799 to +infinity | 10 | 10 6800 to -infinity | 11 | 01 6801 */ 6802 IRTemp rm_PPC32 = newTemp(Ity_I32); 6803 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) ); 6804 6805 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 6806 return binop( Iop_Xor32, 6807 mkexpr(rm_PPC32), 6808 binop( Iop_And32, 6809 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)), 6810 mkU32(2) )); 6811 } 6812 6813 /* The DFP IR rounding modes were chosen such that the existing PPC to IR 6814 * mapping would still work with the extended three bit DFP rounding 6815 * mode designator. 6816 6817 * rounding mode | PPC | IR 6818 * ----------------------------------------------- 6819 * to nearest, ties to even | 000 | 000 6820 * to zero | 001 | 011 6821 * to +infinity | 010 | 010 6822 * to -infinity | 011 | 001 6823 * to nearest, ties away from 0 | 100 | 100 6824 * to nearest, ties toward 0 | 101 | 111 6825 * to away from 0 | 110 | 110 6826 * to prepare for shorter precision | 111 | 101 6827 */ 6828 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void ) 6829 { 6830 IRTemp rm_PPC32 = newTemp( Ity_I32 ); 6831 assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) ); 6832 6833 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 6834 return binop( Iop_Xor32, 6835 mkexpr( rm_PPC32 ), 6836 binop( Iop_And32, 6837 binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ), 6838 mkU32( 2 ) ) ); 6839 } 6840 6841 #define NANmaskSingle 0x7F800000 6842 #define NANmaskDouble 0x7FF00000 6843 6844 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask ) 6845 { 6846 IRTemp exp_zero = newTemp(Ity_I8); 6847 IRTemp frac_mask = newTemp(Ity_I32); 6848 IRTemp frac_not_zero = newTemp(Ity_I8); 6849 6850 /* Check if the result is QNAN or SNAN and not +infinity or -infinity. 6851 * The input value is always 64-bits, for single precision values, the 6852 * lower 32 bits must be zero. 6853 * 6854 * Single Pricision 6855 * [62:54] exponent field is equal to 0xFF for NAN and Infinity. 6856 * [53:32] fraction field is zero for Infinity and non-zero for NAN 6857 * [31:0] unused for single precision representation 6858 * 6859 * Double Pricision 6860 * [62:51] exponent field is equal to 0xFF for NAN and Infinity. 6861 * [50:0] fraction field is zero for Infinity and non-zero for NAN 6862 * 6863 * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise. 6864 */ 6865 assign( frac_mask, unop( Iop_Not32, 6866 binop( Iop_Or32, 6867 mkU32( 0x80000000ULL ), Hi32Mask) ) ); 6868 6869 assign( exp_zero, 6870 unop( Iop_1Sto8, 6871 binop( Iop_CmpEQ32, 6872 binop( Iop_And32, 6873 unop( Iop_64HIto32, 6874 unop( Iop_ReinterpF64asI64, 6875 value ) ), 6876 Hi32Mask ), 6877 Hi32Mask ) ) ); 6878 assign( frac_not_zero, 6879 binop( Iop_Or8, 6880 unop( Iop_1Sto8, 6881 binop( Iop_CmpNE32, 6882 binop( Iop_And32, 6883 unop( Iop_64HIto32, 6884 unop( Iop_ReinterpF64asI64, 6885 value ) ), 6886 mkexpr( frac_mask ) ), 6887 mkU32( 0x0 ) ) ), 6888 unop( Iop_1Sto8, 6889 binop( Iop_CmpNE32, 6890 binop( Iop_And32, 6891 unop( Iop_64to32, 6892 unop( Iop_ReinterpF64asI64, 6893 value ) ), 6894 mkU32( 0xFFFFFFFF ) ), 6895 mkU32( 0x0 ) ) ) ) ); 6896 return unop( Iop_8Sto32, 6897 binop( Iop_And8, 6898 mkexpr( exp_zero ), 6899 mkexpr( frac_not_zero ) ) ); 6900 } 6901 6902 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask ) 6903 { 6904 /* This function will only complement the 64-bit floating point value if it 6905 * is not Nan. NaN is not a signed value. Need to do computations using 6906 * 32-bit operands to ensure it will run in 32-bit mode. 6907 */ 6908 return binop( Iop_32HLto64, 6909 binop( Iop_Or32, 6910 binop( Iop_And32, 6911 nan_mask, 6912 unop( Iop_64HIto32, 6913 unop( Iop_ReinterpF64asI64, 6914 value ) ) ), 6915 binop( Iop_And32, 6916 unop( Iop_Not32, 6917 nan_mask ), 6918 unop( Iop_64HIto32, 6919 unop( Iop_ReinterpF64asI64, 6920 unop( Iop_NegF64, 6921 value ) ) ) ) ), 6922 unop( Iop_64to32, 6923 unop( Iop_ReinterpF64asI64, value ) ) ); 6924 } 6925 6926 /*------------------------------------------------------------*/ 6927 /*--- Floating Point Instruction Translation ---*/ 6928 /*------------------------------------------------------------*/ 6929 6930 /* 6931 Floating Point Load Instructions 6932 */ 6933 static Bool dis_fp_load ( UInt theInstr ) 6934 { 6935 /* X-Form, D-Form */ 6936 UChar opc1 = ifieldOPC(theInstr); 6937 UChar frD_addr = ifieldRegDS(theInstr); 6938 UChar rA_addr = ifieldRegA(theInstr); 6939 UChar rB_addr = ifieldRegB(theInstr); 6940 UInt opc2 = ifieldOPClo10(theInstr); 6941 UChar b0 = ifieldBIT0(theInstr); 6942 UInt uimm16 = ifieldUIMM16(theInstr); 6943 6944 Int simm16 = extend_s_16to32(uimm16); 6945 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6946 IRTemp EA = newTemp(ty); 6947 IRTemp rA = newTemp(ty); 6948 IRTemp rB = newTemp(ty); 6949 IRTemp iHi = newTemp(Ity_I32); 6950 IRTemp iLo = newTemp(Ity_I32); 6951 6952 assign( rA, getIReg(rA_addr) ); 6953 assign( rB, getIReg(rB_addr) ); 6954 6955 /* These are completely straightforward from a rounding and status 6956 bits perspective: no rounding involved and no funny status or CR 6957 bits affected. */ 6958 6959 switch (opc1) { 6960 case 0x30: // lfs (Load Float Single, PPC32 p441) 6961 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 6962 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 6963 putFReg( frD_addr, 6964 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 6965 break; 6966 6967 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442) 6968 if (rA_addr == 0) 6969 return False; 6970 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 6971 assign( EA, ea_rA_simm(rA_addr, simm16) ); 6972 putFReg( frD_addr, 6973 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 6974 putIReg( rA_addr, mkexpr(EA) ); 6975 break; 6976 6977 case 0x32: // lfd (Load Float Double, PPC32 p437) 6978 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 6979 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 6980 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 6981 break; 6982 6983 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438) 6984 if (rA_addr == 0) 6985 return False; 6986 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 6987 assign( EA, ea_rA_simm(rA_addr, simm16) ); 6988 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 6989 putIReg( rA_addr, mkexpr(EA) ); 6990 break; 6991 6992 case 0x1F: 6993 if (b0 != 0) { 6994 vex_printf("dis_fp_load(ppc)(instr,b0)\n"); 6995 return False; 6996 } 6997 6998 switch(opc2) { 6999 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444) 7000 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7001 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7002 putFReg( frD_addr, unop( Iop_F32toF64, 7003 loadBE(Ity_F32, mkexpr(EA))) ); 7004 break; 7005 7006 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443) 7007 if (rA_addr == 0) 7008 return False; 7009 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7010 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7011 putFReg( frD_addr, 7012 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 7013 putIReg( rA_addr, mkexpr(EA) ); 7014 break; 7015 7016 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440) 7017 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7018 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7019 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 7020 break; 7021 7022 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439) 7023 if (rA_addr == 0) 7024 return False; 7025 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7026 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7027 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 7028 putIReg( rA_addr, mkexpr(EA) ); 7029 break; 7030 7031 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120) 7032 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7033 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7034 assign( iLo, loadBE(Ity_I32, mkexpr(EA)) ); 7035 assign( iHi, binop(Iop_Sub32, 7036 mkU32(0), 7037 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) ); 7038 putFReg( frD_addr, unop(Iop_ReinterpI64asF64, 7039 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) ); 7040 break; 7041 7042 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed 7043 { 7044 IRTemp dw = newTemp( Ity_I64 ); 7045 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7046 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7047 assign( iLo, loadBE(Ity_I32, mkexpr(EA)) ); 7048 assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) ); 7049 putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) ); 7050 break; 7051 } 7052 7053 default: 7054 vex_printf("dis_fp_load(ppc)(opc2)\n"); 7055 return False; 7056 } 7057 break; 7058 7059 default: 7060 vex_printf("dis_fp_load(ppc)(opc1)\n"); 7061 return False; 7062 } 7063 return True; 7064 } 7065 7066 7067 7068 /* 7069 Floating Point Store Instructions 7070 */ 7071 static Bool dis_fp_store ( UInt theInstr ) 7072 { 7073 /* X-Form, D-Form */ 7074 UChar opc1 = ifieldOPC(theInstr); 7075 UChar frS_addr = ifieldRegDS(theInstr); 7076 UChar rA_addr = ifieldRegA(theInstr); 7077 UChar rB_addr = ifieldRegB(theInstr); 7078 UInt opc2 = ifieldOPClo10(theInstr); 7079 UChar b0 = ifieldBIT0(theInstr); 7080 Int uimm16 = ifieldUIMM16(theInstr); 7081 7082 Int simm16 = extend_s_16to32(uimm16); 7083 IRTemp frS = newTemp(Ity_F64); 7084 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7085 IRTemp EA = newTemp(ty); 7086 IRTemp rA = newTemp(ty); 7087 IRTemp rB = newTemp(ty); 7088 7089 assign( frS, getFReg(frS_addr) ); 7090 assign( rA, getIReg(rA_addr) ); 7091 assign( rB, getIReg(rB_addr) ); 7092 7093 /* These are straightforward from a status bits perspective: no 7094 funny status or CR bits affected. For single precision stores, 7095 the values are truncated and denormalised (not rounded) to turn 7096 them into single precision values. */ 7097 7098 switch (opc1) { 7099 7100 case 0x34: // stfs (Store Float Single, PPC32 p518) 7101 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7102 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7103 /* Use Iop_TruncF64asF32 to truncate and possible denormalise 7104 the value to be stored in the correct way, without any 7105 rounding. */ 7106 storeBE( mkexpr(EA), 7107 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7108 break; 7109 7110 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519) 7111 if (rA_addr == 0) 7112 return False; 7113 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7114 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7115 /* See comment for stfs */ 7116 storeBE( mkexpr(EA), 7117 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7118 putIReg( rA_addr, mkexpr(EA) ); 7119 break; 7120 7121 case 0x36: // stfd (Store Float Double, PPC32 p513) 7122 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7123 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7124 storeBE( mkexpr(EA), mkexpr(frS) ); 7125 break; 7126 7127 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514) 7128 if (rA_addr == 0) 7129 return False; 7130 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7131 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7132 storeBE( mkexpr(EA), mkexpr(frS) ); 7133 putIReg( rA_addr, mkexpr(EA) ); 7134 break; 7135 7136 case 0x1F: 7137 if (b0 != 0) { 7138 vex_printf("dis_fp_store(ppc)(instr,b0)\n"); 7139 return False; 7140 } 7141 switch(opc2) { 7142 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521) 7143 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7144 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7145 /* See note for stfs */ 7146 storeBE( mkexpr(EA), 7147 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7148 break; 7149 7150 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520) 7151 if (rA_addr == 0) 7152 return False; 7153 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7154 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7155 /* See note for stfs */ 7156 storeBE( mkexpr(EA), 7157 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7158 putIReg( rA_addr, mkexpr(EA) ); 7159 break; 7160 7161 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516) 7162 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7163 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7164 storeBE( mkexpr(EA), mkexpr(frS) ); 7165 break; 7166 7167 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515) 7168 if (rA_addr == 0) 7169 return False; 7170 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7171 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7172 storeBE( mkexpr(EA), mkexpr(frS) ); 7173 putIReg( rA_addr, mkexpr(EA) ); 7174 break; 7175 7176 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517) 7177 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7178 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7179 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7180 storeBE( mkexpr(EA), 7181 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) ); 7182 break; 7183 7184 default: 7185 vex_printf("dis_fp_store(ppc)(opc2)\n"); 7186 return False; 7187 } 7188 break; 7189 7190 default: 7191 vex_printf("dis_fp_store(ppc)(opc1)\n"); 7192 return False; 7193 } 7194 return True; 7195 } 7196 7197 7198 7199 /* 7200 Floating Point Arith Instructions 7201 */ 7202 static Bool dis_fp_arith ( UInt theInstr ) 7203 { 7204 /* A-Form */ 7205 UChar opc1 = ifieldOPC(theInstr); 7206 UChar frD_addr = ifieldRegDS(theInstr); 7207 UChar frA_addr = ifieldRegA(theInstr); 7208 UChar frB_addr = ifieldRegB(theInstr); 7209 UChar frC_addr = ifieldRegC(theInstr); 7210 UChar opc2 = ifieldOPClo5(theInstr); 7211 UChar flag_rC = ifieldBIT0(theInstr); 7212 7213 IRTemp frD = newTemp(Ity_F64); 7214 IRTemp frA = newTemp(Ity_F64); 7215 IRTemp frB = newTemp(Ity_F64); 7216 IRTemp frC = newTemp(Ity_F64); 7217 IRExpr* rm = get_IR_roundingmode(); 7218 7219 /* By default, we will examine the results of the operation and set 7220 fpscr[FPRF] accordingly. */ 7221 Bool set_FPRF = True; 7222 7223 /* By default, if flag_RC is set, we will clear cr1 after the 7224 operation. In reality we should set cr1 to indicate the 7225 exception status of the operation, but since we're not 7226 simulating exceptions, the exception status will appear to be 7227 zero. Hence cr1 should be cleared if this is a . form insn. */ 7228 Bool clear_CR1 = True; 7229 7230 assign( frA, getFReg(frA_addr)); 7231 assign( frB, getFReg(frB_addr)); 7232 assign( frC, getFReg(frC_addr)); 7233 7234 switch (opc1) { 7235 case 0x3B: 7236 switch (opc2) { 7237 case 0x12: // fdivs (Floating Divide Single, PPC32 p407) 7238 if (frC_addr != 0) 7239 return False; 7240 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7241 frD_addr, frA_addr, frB_addr); 7242 assign( frD, triop( Iop_DivF64r32, 7243 rm, mkexpr(frA), mkexpr(frB) )); 7244 break; 7245 7246 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430) 7247 if (frC_addr != 0) 7248 return False; 7249 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7250 frD_addr, frA_addr, frB_addr); 7251 assign( frD, triop( Iop_SubF64r32, 7252 rm, mkexpr(frA), mkexpr(frB) )); 7253 break; 7254 7255 case 0x15: // fadds (Floating Add Single, PPC32 p401) 7256 if (frC_addr != 0) 7257 return False; 7258 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7259 frD_addr, frA_addr, frB_addr); 7260 assign( frD, triop( Iop_AddF64r32, 7261 rm, mkexpr(frA), mkexpr(frB) )); 7262 break; 7263 7264 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428) 7265 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 7266 if (frA_addr != 0 || frC_addr != 0) 7267 return False; 7268 DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"", 7269 frD_addr, frB_addr); 7270 // however illogically, on ppc970 this insn behaves identically 7271 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32. 7272 assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) )); 7273 break; 7274 7275 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421) 7276 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7277 if (frA_addr != 0 || frC_addr != 0) 7278 return False; 7279 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"", 7280 frD_addr, frB_addr); 7281 { IRExpr* ieee_one 7282 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 7283 assign( frD, triop( Iop_DivF64r32, 7284 rm, 7285 ieee_one, mkexpr(frB) )); 7286 } 7287 break; 7288 7289 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414) 7290 if (frB_addr != 0) 7291 return False; 7292 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7293 frD_addr, frA_addr, frC_addr); 7294 assign( frD, triop( Iop_MulF64r32, 7295 rm, mkexpr(frA), mkexpr(frC) )); 7296 break; 7297 7298 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single) 7299 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7300 // Undocumented instruction? 7301 if (frA_addr != 0 || frC_addr != 0) 7302 return False; 7303 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"", 7304 frD_addr, frB_addr); 7305 assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) ); 7306 break; 7307 7308 default: 7309 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n"); 7310 return False; 7311 } 7312 break; 7313 7314 case 0x3F: 7315 switch (opc2) { 7316 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406) 7317 if (frC_addr != 0) 7318 return False; 7319 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7320 frD_addr, frA_addr, frB_addr); 7321 assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) ); 7322 break; 7323 7324 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429) 7325 if (frC_addr != 0) 7326 return False; 7327 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7328 frD_addr, frA_addr, frB_addr); 7329 assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) ); 7330 break; 7331 7332 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400) 7333 if (frC_addr != 0) 7334 return False; 7335 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7336 frD_addr, frA_addr, frB_addr); 7337 assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) ); 7338 break; 7339 7340 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427) 7341 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 7342 if (frA_addr != 0 || frC_addr != 0) 7343 return False; 7344 DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"", 7345 frD_addr, frB_addr); 7346 assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) ); 7347 break; 7348 7349 case 0x17: { // fsel (Floating Select, PPC32 p426) 7350 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7351 IRTemp cc = newTemp(Ity_I32); 7352 IRTemp cc_b0 = newTemp(Ity_I32); 7353 7354 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7355 frD_addr, frA_addr, frC_addr, frB_addr); 7356 7357 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40 7358 // => GT|EQ == (cc & 0x1 == 0) 7359 assign( cc, binop(Iop_CmpF64, mkexpr(frA), 7360 IRExpr_Const(IRConst_F64(0))) ); 7361 assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) ); 7362 7363 // frD = (frA >= 0.0) ? frC : frB 7364 // = (cc_b0 == 0) ? frC : frB 7365 assign( frD, 7366 IRExpr_Mux0X( 7367 unop(Iop_1Uto8, 7368 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0))), 7369 mkexpr(frB), 7370 mkexpr(frC) )); 7371 7372 /* One of the rare ones which don't mess with FPRF */ 7373 set_FPRF = False; 7374 break; 7375 } 7376 7377 case 0x18: // fre (Floating Reciprocal Estimate) 7378 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7379 // Note: unclear whether this insn really exists or not 7380 // ppc970 doesn't have it, but POWER5 does 7381 if (frA_addr != 0 || frC_addr != 0) 7382 return False; 7383 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"", 7384 frD_addr, frB_addr); 7385 { IRExpr* ieee_one 7386 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 7387 assign( frD, triop( Iop_DivF64, 7388 rm, 7389 ieee_one, mkexpr(frB) )); 7390 } 7391 break; 7392 7393 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413) 7394 if (frB_addr != 0) 7395 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n"); 7396 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7397 frD_addr, frA_addr, frC_addr); 7398 assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) ); 7399 break; 7400 7401 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424) 7402 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7403 if (frA_addr != 0 || frC_addr != 0) 7404 return False; 7405 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"", 7406 frD_addr, frB_addr); 7407 assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) ); 7408 break; 7409 7410 default: 7411 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n"); 7412 return False; 7413 } 7414 break; 7415 7416 default: 7417 vex_printf("dis_fp_arith(ppc)(opc1)\n"); 7418 return False; 7419 } 7420 7421 putFReg( frD_addr, mkexpr(frD) ); 7422 7423 if (set_FPRF) { 7424 // XXX XXX XXX FIXME 7425 // set FPRF from frD 7426 } 7427 7428 if (flag_rC && clear_CR1) { 7429 putCR321( 1, mkU8(0) ); 7430 putCR0( 1, mkU8(0) ); 7431 } 7432 7433 return True; 7434 } 7435 7436 7437 7438 /* 7439 Floating Point Mult-Add Instructions 7440 */ 7441 static Bool dis_fp_multadd ( UInt theInstr ) 7442 { 7443 /* A-Form */ 7444 UChar opc1 = ifieldOPC(theInstr); 7445 UChar frD_addr = ifieldRegDS(theInstr); 7446 UChar frA_addr = ifieldRegA(theInstr); 7447 UChar frB_addr = ifieldRegB(theInstr); 7448 UChar frC_addr = ifieldRegC(theInstr); 7449 UChar opc2 = ifieldOPClo5(theInstr); 7450 UChar flag_rC = ifieldBIT0(theInstr); 7451 7452 IRTemp frD = newTemp(Ity_F64); 7453 IRTemp frA = newTemp(Ity_F64); 7454 IRTemp frB = newTemp(Ity_F64); 7455 IRTemp frC = newTemp(Ity_F64); 7456 IRTemp rmt = newTemp(Ity_I32); 7457 IRTemp tmp = newTemp(Ity_F64); 7458 IRTemp sign_tmp = newTemp(Ity_I64); 7459 IRTemp nan_mask = newTemp(Ity_I32); 7460 IRExpr* rm; 7461 7462 /* By default, we will examine the results of the operation and set 7463 fpscr[FPRF] accordingly. */ 7464 Bool set_FPRF = True; 7465 7466 /* By default, if flag_RC is set, we will clear cr1 after the 7467 operation. In reality we should set cr1 to indicate the 7468 exception status of the operation, but since we're not 7469 simulating exceptions, the exception status will appear to be 7470 zero. Hence cr1 should be cleared if this is a . form insn. */ 7471 Bool clear_CR1 = True; 7472 7473 /* Bind the rounding mode expression to a temp; there's no 7474 point in creating gratuitous CSEs, as we know we'll need 7475 to use it twice. */ 7476 assign( rmt, get_IR_roundingmode() ); 7477 rm = mkexpr(rmt); 7478 7479 assign( frA, getFReg(frA_addr)); 7480 assign( frB, getFReg(frB_addr)); 7481 assign( frC, getFReg(frC_addr)); 7482 7483 /* The rounding in this is all a bit dodgy. The idea is to only do 7484 one rounding. That clearly isn't achieveable without dedicated 7485 four-input IR primops, although in the single precision case we 7486 can sort-of simulate it by doing the inner multiply in double 7487 precision. 7488 7489 In the negated cases, the negation happens after rounding. */ 7490 7491 switch (opc1) { 7492 case 0x3B: 7493 switch (opc2) { 7494 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412) 7495 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7496 frD_addr, frA_addr, frC_addr, frB_addr); 7497 assign( frD, qop( Iop_MSubF64r32, rm, 7498 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 7499 break; 7500 7501 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409) 7502 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7503 frD_addr, frA_addr, frC_addr, frB_addr); 7504 assign( frD, qop( Iop_MAddF64r32, rm, 7505 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 7506 break; 7507 7508 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420) 7509 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418) 7510 7511 if (opc2 == 0x1E) { 7512 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7513 frD_addr, frA_addr, frC_addr, frB_addr); 7514 assign( tmp, qop( Iop_MSubF64r32, rm, 7515 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 7516 } else { 7517 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7518 frD_addr, frA_addr, frC_addr, frB_addr); 7519 assign( tmp, qop( Iop_MAddF64r32, rm, 7520 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 7521 } 7522 7523 assign( nan_mask, Check_NaN( mkexpr( tmp ), 7524 mkU32( NANmaskSingle ) ) ); 7525 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 7526 mkexpr( nan_mask ) ) ); 7527 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 7528 break; 7529 7530 default: 7531 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n"); 7532 return False; 7533 } 7534 break; 7535 7536 case 0x3F: 7537 switch (opc2) { 7538 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411) 7539 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7540 frD_addr, frA_addr, frC_addr, frB_addr); 7541 assign( frD, qop( Iop_MSubF64, rm, 7542 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 7543 break; 7544 7545 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408) 7546 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7547 frD_addr, frA_addr, frC_addr, frB_addr); 7548 assign( frD, qop( Iop_MAddF64, rm, 7549 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 7550 break; 7551 7552 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419) 7553 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417) 7554 7555 if (opc2 == 0x1E) { 7556 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7557 frD_addr, frA_addr, frC_addr, frB_addr); 7558 assign( tmp, qop( Iop_MSubF64, rm, 7559 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 7560 } else { 7561 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7562 frD_addr, frA_addr, frC_addr, frB_addr); 7563 assign( tmp, qop( Iop_MAddF64, rm, 7564 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 7565 } 7566 7567 assign( nan_mask, Check_NaN( mkexpr( tmp ), 7568 mkU32( NANmaskDouble ) ) ); 7569 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 7570 mkexpr( nan_mask ) ) ); 7571 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 7572 break; 7573 7574 default: 7575 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n"); 7576 return False; 7577 } 7578 break; 7579 7580 default: 7581 vex_printf("dis_fp_multadd(ppc)(opc1)\n"); 7582 return False; 7583 } 7584 7585 putFReg( frD_addr, mkexpr(frD) ); 7586 7587 if (set_FPRF) { 7588 // XXX XXX XXX FIXME 7589 // set FPRF from frD 7590 } 7591 7592 if (flag_rC && clear_CR1) { 7593 putCR321( 1, mkU8(0) ); 7594 putCR0( 1, mkU8(0) ); 7595 } 7596 7597 return True; 7598 } 7599 7600 /* 7601 * fe_flag is set to 1 if any of the following conditions occurs: 7602 * - The floating-point operand in register FRB is a Zero, a 7603 * NaN, an Infinity, or a negative value. 7604 * - e_b is less than or equal to: -970 for double precision; -103 for single precision 7605 * Otherwise fe_flag is set to 0. 7606 * 7607 * fg_flag is set to 1 if either of the following conditions occurs. 7608 * - The floating-point operand in register FRB is a Zero, an 7609 * Infinity, or a denormalized value. 7610 * Otherwise fg_flag is set to 0. 7611 * 7612 */ 7613 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 7614 { 7615 // The following temps are for holding intermediate results 7616 IRTemp e_b = newTemp(Ity_I32); 7617 IRExpr * fe_flag, * fg_flag; 7618 IRTemp frB_exp_shR = newTemp(Ity_I32); 7619 UInt bias = sp? 127 : 1023; 7620 IRExpr * frbNaN, * frbDenorm, * frBNeg; 7621 IRExpr * eb_LTE; 7622 IRTemp frbZero_tmp = newTemp(Ity_I1); 7623 IRTemp frbInf_tmp = newTemp(Ity_I1); 7624 *fe_flag_tmp = newTemp(Ity_I32); 7625 *fg_flag_tmp = newTemp(Ity_I32); 7626 assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) ); 7627 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 7628 7629 ////////////////// fe_flag tests BEGIN ////////////////////// 7630 /* We first do all tests that may result in setting fe_flag to '1'. 7631 * (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv() 7632 * for details.) 7633 */ 7634 frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int); 7635 assign( frbInf_tmp, is_Inf(frB_Int, sp) ); 7636 assign( frbZero_tmp, is_Zero(frB_Int, sp ) ); 7637 { 7638 // Test_value = -970 for double precision 7639 UInt test_value = sp ? 0xffffff99 : 0xfffffc36; 7640 eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) ); 7641 } 7642 frBNeg = binop( Iop_CmpEQ32, 7643 binop( Iop_Shr32, 7644 sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ), 7645 mkU8( 31 ) ), 7646 mkU32( 1 ) ); 7647 ////////////////// fe_flag tests END ////////////////////// 7648 7649 ////////////////// fg_flag tests BEGIN ////////////////////// 7650 /* 7651 * The following tests were already performed above in the fe_flag 7652 * tests. So these conditions will result in both fe_ and fg_ flags 7653 * being set. 7654 * - Test if FRB is Zero 7655 * - Test if FRB is an Infinity 7656 */ 7657 7658 /* 7659 * Test if FRB holds a denormalized value. A denormalized value is one where 7660 * the exp is 0 and the fraction is non-zero. 7661 */ 7662 if (sp) { 7663 IRTemp frac_part = newTemp(Ity_I32); 7664 assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) ); 7665 frbDenorm 7666 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 7667 binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) ); 7668 } else { 7669 IRExpr * hi32, * low32, * fraction_is_nonzero; 7670 IRTemp frac_part = newTemp(Ity_I64); 7671 7672 assign( frac_part, FP_FRAC_PART(frB_Int) ); 7673 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 7674 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 7675 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 7676 mkU32( 0 ) ); 7677 frbDenorm 7678 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 7679 fraction_is_nonzero ); 7680 } 7681 ////////////////// fg_flag tests END ////////////////////// 7682 7683 ///////////////////////// 7684 fe_flag = mkOR1( mkexpr( frbZero_tmp ), 7685 mkOR1( frbNaN, 7686 mkOR1( mkexpr( frbInf_tmp ), 7687 mkOR1( frBNeg, eb_LTE ) ) ) ); 7688 7689 fe_flag = unop(Iop_1Uto32, fe_flag); 7690 7691 fg_flag = mkOR1( mkexpr( frbZero_tmp ), 7692 mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) ); 7693 fg_flag = unop(Iop_1Uto32, fg_flag); 7694 assign (*fg_flag_tmp, fg_flag); 7695 assign (*fe_flag_tmp, fe_flag); 7696 } 7697 /* 7698 * fe_flag is set to 1 if any of the following conditions occurs: 7699 * - The double-precision floating-point operand in register FRA is a NaN or an 7700 * Infinity. 7701 * - The double-precision floating-point operand in register FRB is a Zero, a 7702 * NaN, or an Infinity. 7703 * - e_b is less than or equal to -1022. 7704 * - e_b is greater than or equal to 1021. 7705 * - The double-precision floating-point operand in register FRA is not a zero 7706 * and the difference, e_a - e_b, is greater than or equal to 1023. 7707 * - The double-precision floating-point operand in register FRA is not a zero 7708 * and the difference, e_a - e_b, is less than or equal to -1021. 7709 * - The double-precision floating-point operand in register FRA is not a zero 7710 * and e_a is less than or equal to -970 7711 * Otherwise fe_flag is set to 0. 7712 * 7713 * fg_flag is set to 1 if either of the following conditions occurs. 7714 * - The double-precision floating-point operand in register FRA is an Infinity. 7715 * - The double-precision floating-point operand in register FRB is a Zero, an 7716 * Infinity, or a denormalized value. 7717 * Otherwise fg_flag is set to 0. 7718 * 7719 */ 7720 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 7721 { 7722 // The following temps are for holding intermediate results 7723 IRTemp e_a = newTemp(Ity_I32); 7724 IRTemp e_b = newTemp(Ity_I32); 7725 IRTemp frA_exp_shR = newTemp(Ity_I32); 7726 IRTemp frB_exp_shR = newTemp(Ity_I32); 7727 7728 UInt bias = sp? 127 : 1023; 7729 *fe_flag_tmp = newTemp(Ity_I32); 7730 *fg_flag_tmp = newTemp(Ity_I32); 7731 7732 /* The following variables hold boolean results from tests 7733 * that are OR'ed together for setting the fe_ and fg_ flags. 7734 * For some cases, the booleans are used more than once, so 7735 * I make those IRTemp's instead of IRExpr's. 7736 */ 7737 IRExpr * fraNaN, * frbNaN, * frbDenorm; 7738 IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE; 7739 IRTemp fraInf_tmp = newTemp(Ity_I1); 7740 IRTemp frbZero_tmp = newTemp(Ity_I1); 7741 IRTemp frbInf_tmp = newTemp(Ity_I1); 7742 IRTemp fraNotZero_tmp = newTemp(Ity_I1); 7743 7744 /* The following are the flags that are set by OR'ing the results of 7745 * all the tests done for tdiv. These flags are the input to the specified CR. 7746 */ 7747 IRExpr * fe_flag, * fg_flag; 7748 7749 // Create temps that will be used throughout the following tests. 7750 assign( frA_exp_shR, fp_exp_part( frA_int, sp ) ); 7751 assign( frB_exp_shR, fp_exp_part( frB_int, sp ) ); 7752 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */ 7753 assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) )); 7754 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 7755 7756 7757 ////////////////// fe_flag tests BEGIN ////////////////////// 7758 /* We first do all tests that may result in setting fe_flag to '1'. */ 7759 7760 /* 7761 * Test if the double-precision floating-point operand in register FRA is 7762 * a NaN: 7763 */ 7764 fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int); 7765 /* 7766 * Test if the double-precision floating-point operand in register FRA is 7767 * an Infinity. 7768 */ 7769 assign(fraInf_tmp, is_Inf(frA_int, sp)); 7770 7771 /* 7772 * Test if the double-precision floating-point operand in register FRB is 7773 * a NaN: 7774 */ 7775 frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int); 7776 /* 7777 * Test if the double-precision floating-point operand in register FRB is 7778 * an Infinity. 7779 */ 7780 assign( frbInf_tmp, is_Inf(frB_int, sp) ); 7781 /* 7782 * Test if the double-precision floating-point operand in register FRB is 7783 * a Zero. 7784 */ 7785 assign( frbZero_tmp, is_Zero(frB_int, sp) ); 7786 7787 /* 7788 * Test if e_b <= -1022 for double precision; 7789 * or e_b <= -126 for single precision 7790 */ 7791 { 7792 UInt test_value = sp ? 0xffffff82 : 0xfffffc02; 7793 eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value)); 7794 } 7795 7796 /* 7797 * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision; 7798 * or e_b >= -125 (125 < e_b) for single precision 7799 */ 7800 { 7801 Int test_value = sp ? 125 : 1021; 7802 eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b)); 7803 } 7804 7805 /* 7806 * Test if FRA != Zero and (e_a - e_b) >= bias 7807 */ 7808 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) ); 7809 ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ), 7810 binop( Iop_CmpLT32S, mkU32( bias ), 7811 binop( Iop_Sub32, mkexpr( e_a ), 7812 mkexpr( e_b ) ) ) ); 7813 7814 /* 7815 * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)] 7816 */ 7817 { 7818 UInt test_value = sp ? 0xffffff83 : 0xfffffc03; 7819 7820 ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ), 7821 binop( Iop_CmpLE32S, 7822 binop( Iop_Sub32, 7823 mkexpr( e_a ), 7824 mkexpr( e_b ) ), 7825 mkU32( test_value ) ) ); 7826 } 7827 7828 /* 7829 * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)] 7830 */ 7831 { 7832 UInt test_value = 0xfffffc36; //Int test_value = -970; 7833 7834 ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S, 7835 mkexpr( e_a ), 7836 mkU32( test_value ) ) ); 7837 } 7838 ////////////////// fe_flag tests END ////////////////////// 7839 7840 ////////////////// fg_flag tests BEGIN ////////////////////// 7841 /* 7842 * The following tests were already performed above in the fe_flag 7843 * tests. So these conditions will result in both fe_ and fg_ flags 7844 * being set. 7845 * - Test if FRA is an Infinity 7846 * - Test if FRB ix Zero 7847 * - Test if FRB is an Infinity 7848 */ 7849 7850 /* 7851 * Test if FRB holds a denormalized value. A denormalized value is one where 7852 * the exp is 0 and the fraction is non-zero. 7853 */ 7854 { 7855 IRExpr * fraction_is_nonzero; 7856 7857 if (sp) { 7858 fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int), 7859 mkU32( 0 ) ); 7860 } else { 7861 IRExpr * hi32, * low32; 7862 IRTemp frac_part = newTemp(Ity_I64); 7863 assign( frac_part, FP_FRAC_PART(frB_int) ); 7864 7865 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 7866 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 7867 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 7868 mkU32( 0 ) ); 7869 } 7870 frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), 7871 mkU32( 0x0 ) ), fraction_is_nonzero ); 7872 7873 } 7874 ////////////////// fg_flag tests END ////////////////////// 7875 7876 fe_flag 7877 = mkOR1( 7878 fraNaN, 7879 mkOR1( 7880 mkexpr( fraInf_tmp ), 7881 mkOR1( 7882 mkexpr( frbZero_tmp ), 7883 mkOR1( 7884 frbNaN, 7885 mkOR1( 7886 mkexpr( frbInf_tmp ), 7887 mkOR1( eb_LTE, 7888 mkOR1( eb_GTE, 7889 mkOR1( ea_eb_GTE, 7890 mkOR1( ea_eb_LTE, 7891 ea_LTE ) ) ) ) ) ) ) ) ); 7892 7893 fe_flag = unop(Iop_1Uto32, fe_flag); 7894 7895 fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ), 7896 mkOR1( mkexpr( frbInf_tmp ), 7897 frbDenorm ) ) ); 7898 fg_flag = unop(Iop_1Uto32, fg_flag); 7899 assign(*fe_flag_tmp, fe_flag); 7900 assign(*fg_flag_tmp, fg_flag); 7901 } 7902 7903 /* See description for _do_fp_tdiv() above. */ 7904 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int) 7905 { 7906 IRTemp fe_flag, fg_flag; 7907 ///////////////////////// 7908 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 7909 * where fl_flag == 1 on ppc64. 7910 */ 7911 IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE)); 7912 fe_flag = fg_flag = IRTemp_INVALID; 7913 _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag); 7914 return binop( Iop_Or32, 7915 binop( Iop_Or32, 7916 binop( Iop_Shl32, fl_flag, mkU8( 3 ) ), 7917 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 7918 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ); 7919 } 7920 7921 static Bool dis_fp_tests ( UInt theInstr ) 7922 { 7923 UChar opc1 = ifieldOPC(theInstr); 7924 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 7925 UChar frB_addr = ifieldRegB(theInstr); 7926 UChar b0 = ifieldBIT0(theInstr); 7927 UInt opc2 = ifieldOPClo10(theInstr); 7928 IRTemp frB_I64 = newTemp(Ity_I64); 7929 7930 if (opc1 != 0x3F || b0 != 0 ){ 7931 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 7932 return False; 7933 } 7934 assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) ); 7935 7936 switch (opc2) { 7937 case 0x080: // ftdiv 7938 { 7939 UChar frA_addr = ifieldRegA(theInstr); 7940 IRTemp frA_I64 = newTemp(Ity_I64); 7941 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 7942 if (b21to22 != 0 ) { 7943 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 7944 return False; 7945 } 7946 7947 assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) ); 7948 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 7949 7950 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 7951 break; 7952 } 7953 case 0x0A0: // ftsqrt 7954 { 7955 IRTemp flags = newTemp(Ity_I32); 7956 IRTemp fe_flag, fg_flag; 7957 fe_flag = fg_flag = IRTemp_INVALID; 7958 UChar b18to22 = toUChar( IFIELD( theInstr, 18, 5 ) ); 7959 if ( b18to22 != 0) { 7960 vex_printf("dis_fp_tests(ppc)(ftsqrt)\n"); 7961 return False; 7962 } 7963 DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr); 7964 do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag); 7965 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 7966 * where fl_flag == 1 on ppc64. 7967 */ 7968 assign( flags, 7969 binop( Iop_Or32, 7970 binop( Iop_Or32, mkU32( 8 ), // fl_flag 7971 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 7972 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 7973 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 7974 break; 7975 } 7976 7977 default: 7978 vex_printf("dis_fp_tests(ppc)(opc2)\n"); 7979 return False; 7980 7981 } 7982 return True; 7983 } 7984 7985 /* 7986 Floating Point Compare Instructions 7987 */ 7988 static Bool dis_fp_cmp ( UInt theInstr ) 7989 { 7990 /* X-Form */ 7991 UChar opc1 = ifieldOPC(theInstr); 7992 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 7993 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 7994 UChar frA_addr = ifieldRegA(theInstr); 7995 UChar frB_addr = ifieldRegB(theInstr); 7996 UInt opc2 = ifieldOPClo10(theInstr); 7997 UChar b0 = ifieldBIT0(theInstr); 7998 7999 IRTemp ccIR = newTemp(Ity_I32); 8000 IRTemp ccPPC32 = newTemp(Ity_I32); 8001 8002 IRTemp frA = newTemp(Ity_F64); 8003 IRTemp frB = newTemp(Ity_F64); 8004 8005 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) { 8006 vex_printf("dis_fp_cmp(ppc)(instr)\n"); 8007 return False; 8008 } 8009 8010 assign( frA, getFReg(frA_addr)); 8011 assign( frB, getFReg(frB_addr)); 8012 8013 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) ); 8014 8015 /* Map compare result from IR to PPC32 */ 8016 /* 8017 FP cmp result | PPC | IR 8018 -------------------------- 8019 UN | 0x1 | 0x45 8020 EQ | 0x2 | 0x40 8021 GT | 0x4 | 0x00 8022 LT | 0x8 | 0x01 8023 */ 8024 8025 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2) 8026 // | ((ccIR ^ (ccIR>>6)) & 1) 8027 assign( 8028 ccPPC32, 8029 binop( 8030 Iop_Shl32, 8031 mkU32(1), 8032 unop( 8033 Iop_32to8, 8034 binop( 8035 Iop_Or32, 8036 binop( 8037 Iop_And32, 8038 unop( 8039 Iop_Not32, 8040 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5)) 8041 ), 8042 mkU32(2) 8043 ), 8044 binop( 8045 Iop_And32, 8046 binop( 8047 Iop_Xor32, 8048 mkexpr(ccIR), 8049 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6)) 8050 ), 8051 mkU32(1) 8052 ) 8053 ) 8054 ) 8055 ) 8056 ); 8057 8058 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 8059 8060 /* CAB: TODO?: Support writing cc to FPSCR->FPCC ? 8061 putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 ); 8062 */ 8063 // XXX XXX XXX FIXME 8064 // Also write the result into FPRF (it's not entirely clear how) 8065 8066 /* Note: Differences between fcmpu and fcmpo are only in exception 8067 flag settings, which aren't supported anyway. */ 8068 switch (opc2) { 8069 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403) 8070 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8071 break; 8072 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402) 8073 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8074 break; 8075 default: 8076 vex_printf("dis_fp_cmp(ppc)(opc2)\n"); 8077 return False; 8078 } 8079 return True; 8080 } 8081 8082 8083 8084 /* 8085 Floating Point Rounding/Conversion Instructions 8086 */ 8087 static Bool dis_fp_round ( UInt theInstr ) 8088 { 8089 /* X-Form */ 8090 UChar opc1 = ifieldOPC(theInstr); 8091 UChar b16to20 = ifieldRegA(theInstr); 8092 UChar frD_addr = ifieldRegDS(theInstr); 8093 UChar frB_addr = ifieldRegB(theInstr); 8094 UInt opc2 = ifieldOPClo10(theInstr); 8095 UChar flag_rC = ifieldBIT0(theInstr); 8096 8097 IRTemp frD = newTemp(Ity_F64); 8098 IRTemp frB = newTemp(Ity_F64); 8099 IRTemp r_tmp32 = newTemp(Ity_I32); 8100 IRTemp r_tmp64 = newTemp(Ity_I64); 8101 IRExpr* rm = get_IR_roundingmode(); 8102 8103 /* By default, we will examine the results of the operation and set 8104 fpscr[FPRF] accordingly. */ 8105 Bool set_FPRF = True; 8106 8107 /* By default, if flag_RC is set, we will clear cr1 after the 8108 operation. In reality we should set cr1 to indicate the 8109 exception status of the operation, but since we're not 8110 simulating exceptions, the exception status will appear to be 8111 zero. Hence cr1 should be cleared if this is a . form insn. */ 8112 Bool clear_CR1 = True; 8113 if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) { 8114 vex_printf("dis_fp_round(ppc)(instr)\n"); 8115 return False; 8116 } 8117 8118 assign( frB, getFReg(frB_addr)); 8119 if (opc1 == 0x3B) { 8120 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because 8121 * they're very similar to the other instructions handled here, but have 8122 * a different primary opcode. 8123 */ 8124 switch (opc2) { 8125 case 0x34E: // fcfids (Float convert from signed DWord to single precision) 8126 DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8127 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8128 assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm, 8129 mkexpr( r_tmp64 ) ) ) ); 8130 goto putFR; 8131 8132 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision) 8133 DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8134 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8135 assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) ); 8136 goto putFR; 8137 } 8138 } 8139 8140 8141 switch (opc2) { 8142 case 0x00C: // frsp (Float Round to Single, PPC32 p423) 8143 DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8144 assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) )); 8145 break; 8146 8147 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404) 8148 DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8149 assign( r_tmp32, 8150 binop(Iop_F64toI32S, rm, mkexpr(frB)) ); 8151 assign( frD, unop( Iop_ReinterpI64asF64, 8152 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8153 /* FPRF is undefined after fctiw. Leave unchanged. */ 8154 set_FPRF = False; 8155 break; 8156 8157 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405) 8158 DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8159 assign( r_tmp32, 8160 binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) )); 8161 assign( frD, unop( Iop_ReinterpI64asF64, 8162 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8163 /* FPRF is undefined after fctiwz. Leave unchanged. */ 8164 set_FPRF = False; 8165 break; 8166 8167 case 0x08F: case 0x08E: // fctiwu[z] 8168 DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "", 8169 flag_rC ? ".":"", frD_addr, frB_addr); 8170 assign( r_tmp32, 8171 binop( Iop_F64toI32U, 8172 opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm, 8173 mkexpr( frB ) ) ); 8174 assign( frD, unop( Iop_ReinterpI64asF64, 8175 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8176 /* FPRF is undefined after fctiwz. Leave unchanged. */ 8177 set_FPRF = False; 8178 break; 8179 8180 8181 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437) 8182 DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8183 assign( r_tmp64, 8184 binop(Iop_F64toI64S, rm, mkexpr(frB)) ); 8185 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8186 /* FPRF is undefined after fctid. Leave unchanged. */ 8187 set_FPRF = False; 8188 break; 8189 8190 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437) 8191 DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8192 assign( r_tmp64, 8193 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 8194 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8195 /* FPRF is undefined after fctidz. Leave unchanged. */ 8196 set_FPRF = False; 8197 break; 8198 8199 case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero]) 8200 { 8201 DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z", 8202 flag_rC ? ".":"", frD_addr, frB_addr); 8203 assign( r_tmp64, 8204 binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) ); 8205 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8206 /* FPRF is undefined after fctidz. Leave unchanged. */ 8207 set_FPRF = False; 8208 break; 8209 } 8210 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434) 8211 DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8212 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8213 assign( frD, 8214 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) ); 8215 break; 8216 8217 case 0x3CE: // fcfidu (Float convert from unsigned DWord) 8218 DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8219 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8220 assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) ); 8221 break; 8222 8223 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim 8224 switch(opc2) { 8225 case 0x188: // frin (Floating Round to Integer Nearest) 8226 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8227 assign( r_tmp64, 8228 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) ); 8229 break; 8230 case 0x1A8: // friz (Floating Round to Integer Toward Zero) 8231 DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8232 assign( r_tmp64, 8233 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 8234 break; 8235 case 0x1C8: // frip (Floating Round to Integer Plus) 8236 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8237 assign( r_tmp64, 8238 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) ); 8239 break; 8240 case 0x1E8: // frim (Floating Round to Integer Minus) 8241 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8242 assign( r_tmp64, 8243 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) ); 8244 break; 8245 } 8246 8247 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 8248 /* F64 has only log10(2**52) significant digits anyway */ 8249 /* need to preserve sign of zero */ 8250 /* frD = (fabs(frB) > 9e18) ? frB : 8251 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */ 8252 assign(frD, IRExpr_Mux0X( unop(Iop_32to8, 8253 binop(Iop_CmpF64, 8254 IRExpr_Const(IRConst_F64(9e18)), 8255 unop(Iop_AbsF64, mkexpr(frB)))), 8256 IRExpr_Mux0X(unop(Iop_32to8, 8257 binop(Iop_Shr32, 8258 unop(Iop_64HIto32, 8259 unop(Iop_ReinterpF64asI64, 8260 mkexpr(frB))), mkU8(31))), 8261 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ), 8262 unop(Iop_NegF64, 8263 unop( Iop_AbsF64, 8264 binop(Iop_I64StoF64, mkU32(0), 8265 mkexpr(r_tmp64)) )) ), 8266 mkexpr(frB))); 8267 break; 8268 8269 default: 8270 vex_printf("dis_fp_round(ppc)(opc2)\n"); 8271 return False; 8272 } 8273 putFR: 8274 putFReg( frD_addr, mkexpr(frD) ); 8275 8276 if (set_FPRF) { 8277 // XXX XXX XXX FIXME 8278 // set FPRF from frD 8279 } 8280 8281 if (flag_rC && clear_CR1) { 8282 putCR321( 1, mkU8(0) ); 8283 putCR0( 1, mkU8(0) ); 8284 } 8285 8286 return True; 8287 } 8288 8289 /* 8290 Floating Point Pair Instructions 8291 */ 8292 static Bool dis_fp_pair ( UInt theInstr ) 8293 { 8294 /* X-Form/DS-Form */ 8295 UChar opc1 = ifieldOPC(theInstr); 8296 UChar frT_hi_addr = ifieldRegDS(theInstr); 8297 UChar frT_lo_addr = frT_hi_addr + 1; 8298 UChar rA_addr = ifieldRegA(theInstr); 8299 UChar rB_addr = ifieldRegB(theInstr); 8300 UInt uimm16 = ifieldUIMM16(theInstr); 8301 Int simm16 = extend_s_16to32(uimm16); 8302 UInt opc2 = ifieldOPClo10(theInstr); 8303 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8304 IRTemp EA_hi = newTemp(ty); 8305 IRTemp EA_lo = newTemp(ty); 8306 IRTemp frT_hi = newTemp(Ity_F64); 8307 IRTemp frT_lo = newTemp(Ity_F64); 8308 UChar b0 = ifieldBIT0(theInstr); 8309 Bool is_load = 0; 8310 8311 if ((frT_hi_addr %2) != 0) { 8312 vex_printf("dis_fp_pair(ppc) : odd frT register\n"); 8313 return False; 8314 } 8315 8316 switch (opc1) { 8317 case 0x1F: // register offset 8318 switch(opc2) { 8319 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125) 8320 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 8321 is_load = 1; 8322 break; 8323 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125) 8324 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 8325 break; 8326 default: 8327 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n"); 8328 return False; 8329 } 8330 8331 if (b0 != 0) { 8332 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n"); 8333 return False; 8334 } 8335 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) ); 8336 break; 8337 case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125) 8338 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 8339 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 8340 is_load = 1; 8341 break; 8342 case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125) 8343 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 8344 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 8345 break; 8346 default: // immediate offset 8347 vex_printf("dis_fp_pair(ppc)(instr)\n"); 8348 return False; 8349 } 8350 8351 if (mode64) 8352 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) ); 8353 else 8354 assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) ); 8355 8356 assign( frT_hi, getFReg(frT_hi_addr) ); 8357 assign( frT_lo, getFReg(frT_lo_addr) ); 8358 8359 if (is_load) { 8360 putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) ); 8361 putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) ); 8362 } else { 8363 storeBE( mkexpr(EA_hi), mkexpr(frT_hi) ); 8364 storeBE( mkexpr(EA_lo), mkexpr(frT_lo) ); 8365 } 8366 8367 return True; 8368 } 8369 8370 8371 /* 8372 Floating Point Move Instructions 8373 */ 8374 static Bool dis_fp_move ( UInt theInstr ) 8375 { 8376 /* X-Form */ 8377 UChar opc1 = ifieldOPC(theInstr); 8378 UChar frD_addr = ifieldRegDS(theInstr); 8379 UChar frA_addr = ifieldRegA(theInstr); 8380 UChar frB_addr = ifieldRegB(theInstr); 8381 UInt opc2 = ifieldOPClo10(theInstr); 8382 UChar flag_rC = ifieldBIT0(theInstr); 8383 8384 IRTemp frD = newTemp(Ity_F64); 8385 IRTemp frB = newTemp(Ity_F64); 8386 IRTemp itmpB = newTemp(Ity_F64); 8387 IRTemp frA; 8388 IRTemp signA; 8389 IRTemp hiD; 8390 8391 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) { 8392 vex_printf("dis_fp_move(ppc)(instr)\n"); 8393 return False; 8394 } 8395 8396 assign( frB, getFReg(frB_addr)); 8397 8398 switch (opc2) { 8399 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126) 8400 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr, 8401 frB_addr); 8402 signA = newTemp(Ity_I32); 8403 hiD = newTemp(Ity_I32); 8404 itmpB = newTemp(Ity_I64); 8405 frA = newTemp(Ity_F64); 8406 assign( frA, getFReg(frA_addr) ); 8407 8408 /* get A's sign bit */ 8409 assign(signA, binop(Iop_And32, 8410 unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64, 8411 mkexpr(frA))), 8412 mkU32(0x80000000)) ); 8413 8414 assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) ); 8415 8416 /* mask off B's sign bit and or in A's sign bit */ 8417 assign(hiD, binop(Iop_Or32, 8418 binop(Iop_And32, 8419 unop(Iop_64HIto32, 8420 mkexpr(itmpB)), /* frB's high 32 bits */ 8421 mkU32(0x7fffffff)), 8422 mkexpr(signA)) ); 8423 8424 /* combine hiD/loB into frD */ 8425 assign( frD, unop(Iop_ReinterpI64asF64, 8426 binop(Iop_32HLto64, 8427 mkexpr(hiD), 8428 unop(Iop_64to32, 8429 mkexpr(itmpB)))) ); /* frB's low 32 bits */ 8430 break; 8431 8432 case 0x028: // fneg (Floating Negate, PPC32 p416) 8433 DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8434 assign( frD, unop( Iop_NegF64, mkexpr(frB) )); 8435 break; 8436 8437 case 0x048: // fmr (Floating Move Register, PPC32 p410) 8438 DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8439 assign( frD, mkexpr(frB) ); 8440 break; 8441 8442 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415) 8443 DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8444 assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) ))); 8445 break; 8446 8447 case 0x108: // fabs (Floating Absolute Value, PPC32 p399) 8448 DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8449 assign( frD, unop( Iop_AbsF64, mkexpr(frB) )); 8450 break; 8451 8452 default: 8453 vex_printf("dis_fp_move(ppc)(opc2)\n"); 8454 return False; 8455 } 8456 8457 putFReg( frD_addr, mkexpr(frD) ); 8458 8459 /* None of these change FPRF. cr1 is set in the usual way though, 8460 if flag_rC is set. */ 8461 8462 if (flag_rC) { 8463 putCR321( 1, mkU8(0) ); 8464 putCR0( 1, mkU8(0) ); 8465 } 8466 8467 return True; 8468 } 8469 8470 8471 8472 /* 8473 Floating Point Status/Control Register Instructions 8474 */ 8475 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level ) 8476 { 8477 /* Many forms - see each switch case */ 8478 UChar opc1 = ifieldOPC(theInstr); 8479 UInt opc2 = ifieldOPClo10(theInstr); 8480 UChar flag_rC = ifieldBIT0(theInstr); 8481 8482 if (opc1 != 0x3F) { 8483 vex_printf("dis_fp_scr(ppc)(instr)\n"); 8484 return False; 8485 } 8486 8487 switch (opc2) { 8488 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479) 8489 // Bit crbD of the FPSCR is set. 8490 UChar crbD = ifieldRegDS(theInstr); 8491 UInt b11to20 = IFIELD(theInstr, 11, 10); 8492 8493 if (b11to20 != 0) { 8494 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n"); 8495 return False; 8496 } 8497 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD); 8498 putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ), 8499 1ULL << ( 31 - crbD ) ); 8500 break; 8501 } 8502 8503 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465) 8504 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 8505 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 8506 UChar crfS = toUChar( IFIELD( theInstr, 18, 3 ) ); 8507 UChar b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) ); 8508 IRTemp tmp = newTemp(Ity_I32); 8509 IRExpr* fpscr_all; 8510 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) { 8511 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n"); 8512 return False; 8513 } 8514 DIP("mcrfs crf%d,crf%d\n", crfD, crfS); 8515 vassert(crfD < 8); 8516 vassert(crfS < 8); 8517 fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 8518 assign( tmp, binop(Iop_And32, 8519 binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))), 8520 mkU32(0xF)) ); 8521 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD ); 8522 break; 8523 } 8524 8525 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478) 8526 // Bit crbD of the FPSCR is cleared. 8527 UChar crbD = ifieldRegDS(theInstr); 8528 UInt b11to20 = IFIELD(theInstr, 11, 10); 8529 8530 if (b11to20 != 0) { 8531 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n"); 8532 return False; 8533 } 8534 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD); 8535 putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) ); 8536 break; 8537 } 8538 8539 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481) 8540 UInt crfD = IFIELD( theInstr, 23, 3 ); 8541 UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) ); 8542 UChar IMM = toUChar( IFIELD( theInstr, 12, 4 ) ); 8543 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 8544 UChar Wbit; 8545 8546 if (b16to22 != 0 || b11 != 0) { 8547 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n"); 8548 return False; 8549 } 8550 DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM); 8551 if (GX_level) { 8552 /* This implies that Decimal Floating Point is supported, and the 8553 * FPSCR must be managed as a 64-bit register. 8554 */ 8555 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 8556 } else { 8557 Wbit = 0; 8558 } 8559 crfD = crfD + (8 * (1 - Wbit) ); 8560 putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD ); 8561 break; 8562 } 8563 8564 case 0x247: { // mffs (Move from FPSCR, PPC32 p468) 8565 UChar frD_addr = ifieldRegDS(theInstr); 8566 UInt b11to20 = IFIELD(theInstr, 11, 10); 8567 IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 8568 IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR, 8569 MASK_FPSCR_DRN ); 8570 8571 if (b11to20 != 0) { 8572 vex_printf("dis_fp_scr(ppc)(instr,mffs)\n"); 8573 return False; 8574 } 8575 DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr); 8576 putFReg( frD_addr, 8577 unop( Iop_ReinterpI64asF64, 8578 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) ); 8579 break; 8580 } 8581 8582 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480) 8583 UChar b25 = toUChar( IFIELD(theInstr, 25, 1) ); 8584 UChar FM = toUChar( IFIELD(theInstr, 17, 8) ); 8585 UChar frB_addr = ifieldRegB(theInstr); 8586 IRTemp frB = newTemp(Ity_F64); 8587 IRTemp rB_64 = newTemp( Ity_I64 ); 8588 Int i; 8589 ULong mask; 8590 UChar Wbit; 8591 #define BFP_MASK_SEED 0x3000000000000000ULL 8592 #define DFP_MASK_SEED 0x7000000000000000ULL 8593 8594 if (GX_level) { 8595 /* This implies that Decimal Floating Point is supported, and the 8596 * FPSCR must be managed as a 64-bit register. 8597 */ 8598 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 8599 } else { 8600 Wbit = 0; 8601 } 8602 8603 if (b25 == 1) { 8604 /* new 64 bit move variant for power 6. If L field (bit 25) is 8605 * a one do a full 64 bit move. Note, the FPSCR is not really 8606 * properly modeled. This instruciton only changes the value of 8607 * the rounding mode. The HW exception bits do not get set in 8608 * the simulator. 1/12/09 8609 */ 8610 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr); 8611 mask = 0xFF; 8612 8613 } else { 8614 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr); 8615 // Build 32bit mask from FM: 8616 mask = 0; 8617 for (i=0; i<8; i++) { 8618 if ((FM & (1<<(7-i))) == 1) { 8619 /* FPSCR field k is set to the contents of the corresponding 8620 * field of register FRB, where k = i+8x(1-W). In the Power 8621 * ISA, register field numbering is from left to right, so field 8622 * 15 is the least significant field in a 64-bit register. To 8623 * generate the mask, we set all the appropriate rounding mode 8624 * bits in the highest order nibble (field 0) and shift right 8625 * 'k x nibble length'. 8626 */ 8627 if (Wbit) 8628 mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 8629 else 8630 mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 8631 } 8632 } 8633 } 8634 assign( frB, getFReg(frB_addr)); 8635 assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 8636 putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask ); 8637 break; 8638 } 8639 8640 default: 8641 vex_printf("dis_fp_scr(ppc)(opc2)\n"); 8642 return False; 8643 } 8644 return True; 8645 } 8646 8647 /*------------------------------------------------------------*/ 8648 /*--- Decimal Floating Point (DFP) Helper functions ---*/ 8649 /*------------------------------------------------------------*/ 8650 #define DFP_LONG 1 8651 #define DFP_EXTND 2 8652 #define DFP_LONG_BIAS 398 8653 #define DFP_LONG_ENCODED_FIELD_MASK 0x1F00 8654 #define DFP_EXTND_BIAS 6176 8655 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000 8656 #define DFP_LONG_EXP_MSK 0XFF 8657 #define DFP_EXTND_EXP_MSK 0XFFF 8658 8659 #define DFP_G_FIELD_LONG_MASK 0x7FFC0000 // upper 32-bits only 8660 #define DFP_LONG_GFIELD_RT_SHIFT (63 - 13 - 32) // adj for upper 32-bits 8661 #define DFP_G_FIELD_EXTND_MASK 0x7FFFC000 // upper 32-bits only 8662 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits 8663 #define DFP_T_FIELD_LONG_MASK 0x3FFFF // mask for upper 32-bits 8664 #define DFP_T_FIELD_EXTND_MASK 0x03FFFF // mask for upper 32-bits 8665 #define DFP_LONG_EXP_MAX 369 // biased max 8666 #define DFP_LONG_EXP_MIN 0 // biased min 8667 #define DFP_EXTND_EXP_MAX 6111 // biased max 8668 #define DFP_EXTND_EXP_MIN 0 // biased min 8669 #define DFP_LONG_MAX_SIG_DIGITS 16 8670 #define DFP_EXTND_MAX_SIG_DIGITS 34 8671 #define MAX_DIGITS_IN_STRING 8 8672 8673 8674 #define AND(x, y) binop( Iop_And32, x, y ) 8675 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) ) 8676 #define OR(x, y) binop( Iop_Or32, x, y ) 8677 #define OR3(x, y, z) OR( x, OR( y, z ) ) 8678 #define OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) ) 8679 #define NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1, mkexpr( x ) ) ) ) 8680 8681 #define SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) ) 8682 #define SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) ) 8683 8684 #define BITS5(_b4,_b3,_b2,_b1,_b0) \ 8685 (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \ 8686 ((_b1) << 1) | ((_b0) << 0)) 8687 8688 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 ) 8689 { 8690 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 8691 IRTemp lmd_8_mask = newTemp( Ity_I32 ); 8692 IRTemp lmd_9_mask = newTemp( Ity_I32 ); 8693 IRTemp lmexp_00_mask = newTemp( Ity_I32 ); 8694 IRTemp lmexp_01_mask = newTemp( Ity_I32 ); 8695 IRTemp lmexp_10_mask = newTemp( Ity_I32 ); 8696 IRTemp lmd_07_val = newTemp( Ity_I32 ); 8697 IRTemp lmd_8_val = newTemp( Ity_I32 ); 8698 IRTemp lmd_9_val = newTemp( Ity_I32 ); 8699 8700 /* The encodig is as follows: 8701 * lmd - left most digit 8702 * lme - left most 2-bits of the exponent 8703 * 8704 * lmd 8705 * 0 - 7 (lmexp << 3) | lmd 8706 * 8 0b11000 (24 decimal) if lme=0b00; 8707 * 0b11010 (26 decimal) if lme=0b01; 8708 * 0b11100 (28 decimal) if lme=0b10; 8709 * 9 0b11001 (25 decimal) if lme=0b00; 8710 * 0b11011 (27 decimal) if lme=0b01; 8711 * 0b11101 (29 decimal) if lme=0b10; 8712 */ 8713 8714 /* Generate the masks for each condition */ 8715 assign( lmd_07_mask, 8716 unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) ); 8717 assign( lmd_8_mask, 8718 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) ); 8719 assign( lmd_9_mask, 8720 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) ); 8721 assign( lmexp_00_mask, 8722 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) ); 8723 assign( lmexp_01_mask, 8724 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) ); 8725 assign( lmexp_10_mask, 8726 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) ); 8727 8728 /* Generate the values for each LMD condition, assuming the condition 8729 * is TRUE. 8730 */ 8731 assign( lmd_07_val, 8732 binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) ); 8733 assign( lmd_8_val, 8734 binop( Iop_Or32, 8735 binop( Iop_Or32, 8736 binop( Iop_And32, 8737 mkexpr( lmexp_00_mask ), 8738 mkU32( 24 ) ), 8739 binop( Iop_And32, 8740 mkexpr( lmexp_01_mask ), 8741 mkU32( 26 ) ) ), 8742 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) ); 8743 assign( lmd_9_val, 8744 binop( Iop_Or32, 8745 binop( Iop_Or32, 8746 binop( Iop_And32, 8747 mkexpr( lmexp_00_mask ), 8748 mkU32( 25 ) ), 8749 binop( Iop_And32, 8750 mkexpr( lmexp_01_mask ), 8751 mkU32( 27 ) ) ), 8752 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) ); 8753 8754 /* generate the result from the possible LMD values */ 8755 return binop( Iop_Or32, 8756 binop( Iop_Or32, 8757 binop( Iop_And32, 8758 mkexpr( lmd_07_mask ), 8759 mkexpr( lmd_07_val ) ), 8760 binop( Iop_And32, 8761 mkexpr( lmd_8_mask ), 8762 mkexpr( lmd_8_val ) ) ), 8763 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) ); 8764 } 8765 8766 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 ) 8767 { 8768 /* Extract the exponent and the left most digit of the mantissa 8769 * from the G field bits [0:4]. 8770 */ 8771 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 8772 IRTemp lmd_8_00_mask = newTemp( Ity_I32 ); 8773 IRTemp lmd_8_01_mask = newTemp( Ity_I32 ); 8774 IRTemp lmd_8_10_mask = newTemp( Ity_I32 ); 8775 IRTemp lmd_9_00_mask = newTemp( Ity_I32 ); 8776 IRTemp lmd_9_01_mask = newTemp( Ity_I32 ); 8777 IRTemp lmd_9_10_mask = newTemp( Ity_I32 ); 8778 8779 IRTemp lmd_07_val = newTemp( Ity_I32 ); 8780 IRTemp lmd_8_val = newTemp( Ity_I32 ); 8781 IRTemp lmd_9_val = newTemp( Ity_I32 ); 8782 8783 /* The left most digit (LMD) encoding is as follows: 8784 * lmd 8785 * 0 - 7 (lmexp << 3) | lmd 8786 * 8 0b11000 (24 decimal) if lme=0b00; 8787 * 0b11010 (26 decimal) if lme=0b01; 8788 * 0b11100 (28 decimal) if lme=0b10 8789 * 9 0b11001 (25 decimal) if lme=0b00; 8790 * 0b11011 (27 decimal) if lme=0b01; 8791 * 0b11101 (29 decimal) if lme=0b10; 8792 */ 8793 8794 /* Generate the masks for each condition of LMD and exponent bits */ 8795 assign( lmd_07_mask, 8796 unop( Iop_1Sto32, binop( Iop_CmpLE32U, 8797 gfield_0_4, 8798 mkU32( BITS5(1,0,1,1,1) ) ) ) ); 8799 assign( lmd_8_00_mask, 8800 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 8801 gfield_0_4, 8802 mkU32( BITS5(1,1,0,0,0) ) ) ) ); 8803 assign( lmd_8_01_mask, 8804 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 8805 gfield_0_4, 8806 mkU32( BITS5(1,1,0,1,0) ) ) ) ); 8807 assign( lmd_8_10_mask, 8808 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 8809 gfield_0_4, 8810 mkU32( BITS5(1,1,1,0,0) ) ) ) ); 8811 assign( lmd_9_00_mask, 8812 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 8813 gfield_0_4, 8814 mkU32( BITS5(1,1,0,0,1) ) ) ) ); 8815 assign( lmd_9_01_mask, 8816 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 8817 gfield_0_4, 8818 mkU32( BITS5(1,1,0,1,1) ) ) ) ); 8819 assign( lmd_9_10_mask, 8820 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 8821 gfield_0_4, 8822 mkU32( BITS5(1,1,1,0,1) ) ) ) ); 8823 8824 /* Generate the values for each LMD condition, assuming the condition 8825 * is TRUE. 8826 */ 8827 assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) ); 8828 assign( lmd_8_val, mkU32( 0x8 ) ); 8829 assign( lmd_9_val, mkU32( 0x9 ) ); 8830 8831 assign( *lmd, 8832 OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ), 8833 AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ), 8834 AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )), 8835 OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ), 8836 AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ), 8837 AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ), 8838 AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) ) 8839 ) ) ); 8840 } 8841 8842 #define DIGIT1_SHR 4 // shift digit 1 to bottom 4 bits 8843 #define DIGIT2_SHR 8 // shift digit 2 to bottom 4 bits 8844 #define DIGIT3_SHR 12 8845 #define DIGIT4_SHR 16 8846 #define DIGIT5_SHR 20 8847 #define DIGIT6_SHR 24 8848 #define DIGIT7_SHR 28 8849 8850 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l ) 8851 { 8852 /* 60-bit BCD string stored in two 32-bit values. Check that each, 8853 * digit is a valid BCD number, i.e. less then 9. 8854 */ 8855 IRTemp valid = newTemp( Ity_I32 ); 8856 8857 assign( valid, 8858 AND4( AND4 ( unop( Iop_1Sto32, 8859 binop( Iop_CmpLE32U, 8860 binop( Iop_And32, 8861 bcd_l, 8862 mkU32 ( 0xF ) ), 8863 mkU32( 0x9 ) ) ), 8864 unop( Iop_1Sto32, 8865 binop( Iop_CmpLE32U, 8866 binop( Iop_And32, 8867 binop( Iop_Shr32, 8868 bcd_l, 8869 mkU8 ( DIGIT1_SHR ) ), 8870 mkU32 ( 0xF ) ), 8871 mkU32( 0x9 ) ) ), 8872 unop( Iop_1Sto32, 8873 binop( Iop_CmpLE32U, 8874 binop( Iop_And32, 8875 binop( Iop_Shr32, 8876 bcd_l, 8877 mkU8 ( DIGIT2_SHR ) ), 8878 mkU32 ( 0xF ) ), 8879 mkU32( 0x9 ) ) ), 8880 unop( Iop_1Sto32, 8881 binop( Iop_CmpLE32U, 8882 binop( Iop_And32, 8883 binop( Iop_Shr32, 8884 bcd_l, 8885 mkU8 ( DIGIT3_SHR ) ), 8886 mkU32 ( 0xF ) ), 8887 mkU32( 0x9 ) ) ) ), 8888 AND4 ( unop( Iop_1Sto32, 8889 binop( Iop_CmpLE32U, 8890 binop( Iop_And32, 8891 binop( Iop_Shr32, 8892 bcd_l, 8893 mkU8 ( DIGIT4_SHR ) ), 8894 mkU32 ( 0xF ) ), 8895 mkU32( 0x9 ) ) ), 8896 unop( Iop_1Sto32, 8897 binop( Iop_CmpLE32U, 8898 binop( Iop_And32, 8899 binop( Iop_Shr32, 8900 bcd_l, 8901 mkU8 ( DIGIT5_SHR ) ), 8902 mkU32 ( 0xF ) ), 8903 mkU32( 0x9 ) ) ), 8904 unop( Iop_1Sto32, 8905 binop( Iop_CmpLE32U, 8906 binop( Iop_And32, 8907 binop( Iop_Shr32, 8908 bcd_l, 8909 mkU8 ( DIGIT6_SHR ) ), 8910 mkU32 ( 0xF ) ), 8911 mkU32( 0x9 ) ) ), 8912 unop( Iop_1Sto32, 8913 binop( Iop_CmpLE32U, 8914 binop( Iop_And32, 8915 binop( Iop_Shr32, 8916 bcd_l, 8917 mkU8 ( DIGIT7_SHR ) ), 8918 mkU32 ( 0xF ) ), 8919 mkU32( 0x9 ) ) ) ), 8920 AND4( unop( Iop_1Sto32, 8921 binop( Iop_CmpLE32U, 8922 binop( Iop_And32, 8923 bcd_u, 8924 mkU32 ( 0xF ) ), 8925 mkU32( 0x9 ) ) ), 8926 unop( Iop_1Sto32, 8927 binop( Iop_CmpLE32U, 8928 binop( Iop_And32, 8929 binop( Iop_Shr32, 8930 bcd_u, 8931 mkU8 ( DIGIT1_SHR ) ), 8932 mkU32 ( 0xF ) ), 8933 mkU32( 0x9 ) ) ), 8934 unop( Iop_1Sto32, 8935 binop( Iop_CmpLE32U, 8936 binop( Iop_And32, 8937 binop( Iop_Shr32, 8938 bcd_u, 8939 mkU8 ( DIGIT2_SHR ) ), 8940 mkU32 ( 0xF ) ), 8941 mkU32( 0x9 ) ) ), 8942 unop( Iop_1Sto32, 8943 binop( Iop_CmpLE32U, 8944 binop( Iop_And32, 8945 binop( Iop_Shr32, 8946 bcd_u, 8947 mkU8 ( DIGIT3_SHR ) ), 8948 mkU32 ( 0xF ) ), 8949 mkU32( 0x9 ) ) ) ), 8950 AND4( unop( Iop_1Sto32, 8951 binop( Iop_CmpLE32U, 8952 binop( Iop_And32, 8953 binop( Iop_Shr32, 8954 bcd_u, 8955 mkU8 ( DIGIT4_SHR ) ), 8956 mkU32 ( 0xF ) ), 8957 mkU32( 0x9 ) ) ), 8958 unop( Iop_1Sto32, 8959 binop( Iop_CmpLE32U, 8960 binop( Iop_And32, 8961 binop( Iop_Shr32, 8962 bcd_u, 8963 mkU8 ( DIGIT5_SHR ) ), 8964 mkU32 ( 0xF ) ), 8965 mkU32( 0x9 ) ) ), 8966 unop( Iop_1Sto32, 8967 binop( Iop_CmpLE32U, 8968 binop( Iop_And32, 8969 binop( Iop_Shr32, 8970 bcd_u, 8971 mkU8 ( DIGIT6_SHR ) ), 8972 mkU32 ( 0xF ) ), 8973 mkU32( 0x9 ) ) ), 8974 unop( Iop_1Sto32, 8975 binop( Iop_CmpLE32U, 8976 binop( Iop_And32, 8977 binop( Iop_Shr32, 8978 bcd_u, 8979 mkU8 ( DIGIT7_SHR ) ), 8980 mkU32 ( 0xF ) ), 8981 mkU32( 0x9 ) ) ) ) ) ); 8982 8983 return unop( Iop_Not32, mkexpr( valid ) ); 8984 } 8985 #undef DIGIT1_SHR 8986 #undef DIGIT2_SHR 8987 #undef DIGIT3_SHR 8988 #undef DIGIT4_SHR 8989 #undef DIGIT5_SHR 8990 #undef DIGIT6_SHR 8991 #undef DIGIT7_SHR 8992 8993 static IRExpr * Generate_neg_sign_mask( IRExpr * sign ) 8994 { 8995 return binop( Iop_Or32, 8996 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ), 8997 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) ) 8998 ); 8999 } 9000 9001 static IRExpr * Generate_pos_sign_mask( IRExpr * sign ) 9002 { 9003 return binop( Iop_Or32, 9004 binop( Iop_Or32, 9005 unop( Iop_1Sto32, 9006 binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ), 9007 unop( Iop_1Sto32, 9008 binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ), 9009 binop( Iop_Or32, 9010 unop( Iop_1Sto32, 9011 binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ), 9012 unop( Iop_1Sto32, 9013 binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) ); 9014 } 9015 9016 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask, 9017 IRExpr * neg_sign_mask ) 9018 { 9019 return binop( Iop_Or32, 9020 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ), 9021 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) ); 9022 } 9023 9024 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask, 9025 IRExpr * pos_sign_mask, 9026 IRExpr * neg_sign_mask ) 9027 /* first argument is all 1's if the BCD string had an invalid digit in it. */ 9028 { 9029 return binop( Iop_Or32, 9030 invalid_bcd_mask, 9031 unop( Iop_1Sto32, 9032 binop( Iop_CmpEQ32, 9033 binop( Iop_Or32, pos_sign_mask, neg_sign_mask ), 9034 mkU32( 0x0 ) ) ) ); 9035 } 9036 9037 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo, 9038 IRTemp * top_12_l, IRTemp * mid_60_u, 9039 IRTemp * mid_60_l, IRTemp * low_60_u, 9040 IRTemp * low_60_l) 9041 { 9042 IRTemp tmplow60 = newTemp( Ity_I64 ); 9043 IRTemp tmpmid60 = newTemp( Ity_I64 ); 9044 IRTemp tmptop12 = newTemp( Ity_I64 ); 9045 IRTemp low_50 = newTemp( Ity_I64 ); 9046 IRTemp mid_50 = newTemp( Ity_I64 ); 9047 IRTemp top_10 = newTemp( Ity_I64 ); 9048 IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg 9049 9050 /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */ 9051 9052 /* low_50[49:0] = ((frBI64_lo[49:32] << 14) | frBI64_lo[31:0]) */ 9053 assign( low_50, 9054 binop( Iop_32HLto64, 9055 binop( Iop_And32, 9056 unop( Iop_64HIto32, frBI64_lo ), 9057 mkU32( 0x3FFFF ) ), 9058 unop( Iop_64to32, frBI64_lo ) ) ); 9059 9060 /* Convert the 50 bit densely packed BCD string to a 60 bit 9061 * BCD string. 9062 */ 9063 assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) ); 9064 assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) ); 9065 assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) ); 9066 9067 /* mid_50[49:0] = ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) | 9068 * ((frBI64_hi[17:0] << 14) | frBI64_lo[63:50]) 9069 */ 9070 assign( mid_50, 9071 binop( Iop_32HLto64, 9072 binop( Iop_Or32, 9073 binop( Iop_Shl32, 9074 binop( Iop_And32, 9075 unop( Iop_64HIto32, frBI64_hi ), 9076 mkU32( 0xF ) ), 9077 mkU8( 14 ) ), 9078 binop( Iop_Shr32, 9079 unop( Iop_64to32, frBI64_hi ), 9080 mkU8( 18 ) ) ), 9081 binop( Iop_Or32, 9082 binop( Iop_Shl32, 9083 unop( Iop_64to32, frBI64_hi ), 9084 mkU8( 14 ) ), 9085 binop( Iop_Shr32, 9086 unop( Iop_64HIto32, frBI64_lo ), 9087 mkU8( 18 ) ) ) ) ); 9088 9089 /* Convert the 50 bit densely packed BCD string to a 60 bit 9090 * BCD string. 9091 */ 9092 assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) ); 9093 assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) ); 9094 assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) ); 9095 9096 /* top_10[49:0] = frBI64_hi[45:36]) | */ 9097 assign( top_10, 9098 binop( Iop_32HLto64, 9099 mkU32( 0 ), 9100 binop( Iop_And32, 9101 binop( Iop_Shr32, 9102 unop( Iop_64HIto32, frBI64_hi ), 9103 mkU8( 4 ) ), 9104 mkU32( 0x3FF ) ) ) ); 9105 9106 /* Convert the 10 bit densely packed BCD string to a 12 bit 9107 * BCD string. 9108 */ 9109 assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) ); 9110 assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) ); 9111 assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) ); 9112 } 9113 9114 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag, 9115 IRTemp * final_cnt, IRTemp * final_flag, 9116 IRExpr * string ) 9117 { 9118 IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1]; 9119 int digits = MAX_DIGITS_IN_STRING; 9120 int i; 9121 9122 cnt[start-1] = newTemp( Ity_I8 ); 9123 flag[start-1] = newTemp( Ity_I8 ); 9124 assign( cnt[start-1], init_cnt); 9125 assign( flag[start-1], init_flag); 9126 9127 for ( i = start; i <= digits; i++) { 9128 cnt[i] = newTemp( Ity_I8 ); 9129 flag[i] = newTemp( Ity_I8 ); 9130 assign( cnt[i], 9131 binop( Iop_Add8, 9132 mkexpr( cnt[i-1] ), 9133 binop(Iop_And8, 9134 unop( Iop_1Uto8, 9135 binop(Iop_CmpEQ32, 9136 binop(Iop_And32, 9137 string, 9138 mkU32( 0xF << 9139 ( ( digits - i ) * 4) ) ), 9140 mkU32( 0 ) ) ), 9141 binop( Iop_Xor8, /* complement flag */ 9142 mkexpr( flag[i - 1] ), 9143 mkU8( 0xFF ) ) ) ) ); 9144 9145 /* set flag to 1 if digit was not a zero */ 9146 assign( flag[i], 9147 binop(Iop_Or8, 9148 unop( Iop_1Sto8, 9149 binop(Iop_CmpNE32, 9150 binop(Iop_And32, 9151 string, 9152 mkU32( 0xF << 9153 ( (digits - i) * 4) ) ), 9154 mkU32( 0 ) ) ), 9155 mkexpr( flag[i - 1] ) ) ); 9156 } 9157 9158 *final_cnt = cnt[digits]; 9159 *final_flag = flag[digits]; 9160 } 9161 9162 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28, 9163 IRExpr * low_32 ) 9164 { 9165 IRTemp num_lmd = newTemp( Ity_I8 ); 9166 IRTemp num_upper = newTemp( Ity_I8 ); 9167 IRTemp num_low = newTemp( Ity_I8 ); 9168 IRTemp lmd_flag = newTemp( Ity_I8 ); 9169 IRTemp upper_flag = newTemp( Ity_I8 ); 9170 IRTemp low_flag = newTemp( Ity_I8 ); 9171 9172 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 9173 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 9174 9175 Count_zeros( 2, 9176 mkexpr( num_lmd ), 9177 mkexpr( lmd_flag ), 9178 &num_upper, 9179 &upper_flag, 9180 upper_28 ); 9181 9182 Count_zeros( 1, 9183 mkexpr( num_upper ), 9184 mkexpr( upper_flag ), 9185 &num_low, 9186 &low_flag, 9187 low_32 ); 9188 9189 return mkexpr( num_low ); 9190 } 9191 9192 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l, 9193 IRExpr * mid_60_u, IRExpr * mid_60_l, 9194 IRExpr * low_60_u, IRExpr * low_60_l) 9195 { 9196 IRTemp num_lmd = newTemp( Ity_I8 ); 9197 IRTemp num_top = newTemp( Ity_I8 ); 9198 IRTemp num_mid_u = newTemp( Ity_I8 ); 9199 IRTemp num_mid_l = newTemp( Ity_I8 ); 9200 IRTemp num_low_u = newTemp( Ity_I8 ); 9201 IRTemp num_low_l = newTemp( Ity_I8 ); 9202 9203 IRTemp lmd_flag = newTemp( Ity_I8 ); 9204 IRTemp top_flag = newTemp( Ity_I8 ); 9205 IRTemp mid_u_flag = newTemp( Ity_I8 ); 9206 IRTemp mid_l_flag = newTemp( Ity_I8 ); 9207 IRTemp low_u_flag = newTemp( Ity_I8 ); 9208 IRTemp low_l_flag = newTemp( Ity_I8 ); 9209 9210 /* Check the LMD, digit 16, to see if it is zero. */ 9211 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 9212 9213 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 9214 9215 Count_zeros( 6, 9216 mkexpr( num_lmd ), 9217 mkexpr( lmd_flag ), 9218 &num_top, 9219 &top_flag, 9220 top_12_l ); 9221 9222 Count_zeros( 1, 9223 mkexpr( num_top ), 9224 mkexpr( top_flag ), 9225 &num_mid_u, 9226 &mid_u_flag, 9227 binop( Iop_Or32, 9228 binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ), 9229 binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) ); 9230 9231 Count_zeros( 2, 9232 mkexpr( num_mid_u ), 9233 mkexpr( mid_u_flag ), 9234 &num_mid_l, 9235 &mid_l_flag, 9236 mid_60_l ); 9237 9238 Count_zeros( 1, 9239 mkexpr( num_mid_l ), 9240 mkexpr( mid_l_flag ), 9241 &num_low_u, 9242 &low_u_flag, 9243 binop( Iop_Or32, 9244 binop( Iop_Shl32, low_60_u, mkU8( 2 ) ), 9245 binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) ); 9246 9247 Count_zeros( 2, 9248 mkexpr( num_low_u ), 9249 mkexpr( low_u_flag ), 9250 &num_low_l, 9251 &low_l_flag, 9252 low_60_l ); 9253 9254 return mkexpr( num_low_l ); 9255 } 9256 9257 static IRExpr * Check_unordered(IRExpr * val) 9258 { 9259 IRTemp gfield0to5 = newTemp( Ity_I32 ); 9260 9261 /* Extract G[0:4] */ 9262 assign( gfield0to5, 9263 binop( Iop_And32, 9264 binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ), 9265 mkU32( 0x1F ) ) ); 9266 9267 /* Check for unordered, return all 1'x if true */ 9268 return binop( Iop_Or32, /* QNaN check */ 9269 unop( Iop_1Sto32, 9270 binop( Iop_CmpEQ32, 9271 mkexpr( gfield0to5 ), 9272 mkU32( 0x1E ) ) ), 9273 unop( Iop_1Sto32, /* SNaN check */ 9274 binop( Iop_CmpEQ32, 9275 mkexpr( gfield0to5 ), 9276 mkU32( 0x1F ) ) ) ); 9277 } 9278 9279 #undef AND 9280 #undef AND4 9281 #undef OR 9282 #undef OR3 9283 #undef OR4 9284 #undef NOT 9285 #undef SHR 9286 #undef SHL 9287 #undef BITS5 9288 9289 /*------------------------------------------------------------*/ 9290 /*--- Decimal Floating Point (DFP) instruction translation ---*/ 9291 /*------------------------------------------------------------*/ 9292 9293 /* DFP Arithmetic instructions */ 9294 static Bool dis_dfp_arith(UInt theInstr) 9295 { 9296 UInt opc2 = ifieldOPClo10( theInstr ); 9297 UChar frS_addr = ifieldRegDS( theInstr ); 9298 UChar frA_addr = ifieldRegA( theInstr ); 9299 UChar frB_addr = ifieldRegB( theInstr ); 9300 UChar flag_rC = ifieldBIT0( theInstr ); 9301 9302 IRTemp frA = newTemp( Ity_D64 ); 9303 IRTemp frB = newTemp( Ity_D64 ); 9304 IRTemp frS = newTemp( Ity_D64 ); 9305 IRExpr* round = get_IR_roundingmode_DFP(); 9306 9307 /* By default, if flag_RC is set, we will clear cr1 after the 9308 * operation. In reality we should set cr1 to indicate the 9309 * exception status of the operation, but since we're not 9310 * simulating exceptions, the exception status will appear to be 9311 * zero. Hence cr1 should be cleared if this is a . form insn. 9312 */ 9313 Bool clear_CR1 = True; 9314 9315 assign( frA, getDReg( frA_addr ) ); 9316 assign( frB, getDReg( frB_addr ) ); 9317 9318 switch (opc2) { 9319 case 0x2: // dadd 9320 DIP( "dadd%s fr%u,fr%u,fr%u\n", 9321 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9322 assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 9323 break; 9324 case 0x202: // dsub 9325 DIP( "dsub%s fr%u,fr%u,fr%u\n", 9326 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9327 assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 9328 break; 9329 case 0x22: // dmul 9330 DIP( "dmul%s fr%u,fr%u,fr%u\n", 9331 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9332 assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 9333 break; 9334 case 0x222: // ddiv 9335 DIP( "ddiv%s fr%u,fr%u,fr%u\n", 9336 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9337 assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 9338 break; 9339 } 9340 9341 putDReg( frS_addr, mkexpr( frS ) ); 9342 9343 if (flag_rC && clear_CR1) { 9344 putCR321( 1, mkU8( 0 ) ); 9345 putCR0( 1, mkU8( 0 ) ); 9346 } 9347 9348 return True; 9349 } 9350 9351 /* Quad DFP Arithmetic instructions */ 9352 static Bool dis_dfp_arithq(UInt theInstr) 9353 { 9354 UInt opc2 = ifieldOPClo10( theInstr ); 9355 UChar frS_addr = ifieldRegDS( theInstr ); 9356 UChar frA_addr = ifieldRegA( theInstr ); 9357 UChar frB_addr = ifieldRegB( theInstr ); 9358 UChar flag_rC = ifieldBIT0( theInstr ); 9359 9360 IRTemp frA = newTemp( Ity_D128 ); 9361 IRTemp frB = newTemp( Ity_D128 ); 9362 IRTemp frS = newTemp( Ity_D128 ); 9363 IRExpr* round = get_IR_roundingmode_DFP(); 9364 9365 /* By default, if flag_RC is set, we will clear cr1 after the 9366 * operation. In reality we should set cr1 to indicate the 9367 * exception status of the operation, but since we're not 9368 * simulating exceptions, the exception status will appear to be 9369 * zero. Hence cr1 should be cleared if this is a . form insn. 9370 */ 9371 Bool clear_CR1 = True; 9372 9373 assign( frA, getDReg_pair( frA_addr ) ); 9374 assign( frB, getDReg_pair( frB_addr ) ); 9375 9376 switch (opc2) { 9377 case 0x2: // daddq 9378 DIP( "daddq%s fr%u,fr%u,fr%u\n", 9379 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9380 assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 9381 break; 9382 case 0x202: // dsubq 9383 DIP( "dsubq%s fr%u,fr%u,fr%u\n", 9384 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9385 assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 9386 break; 9387 case 0x22: // dmulq 9388 DIP( "dmulq%s fr%u,fr%u,fr%u\n", 9389 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9390 assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 9391 break; 9392 case 0x222: // ddivq 9393 DIP( "ddivq%s fr%u,fr%u,fr%u\n", 9394 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9395 assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 9396 break; 9397 } 9398 9399 putDReg_pair( frS_addr, mkexpr( frS ) ); 9400 9401 if (flag_rC && clear_CR1) { 9402 putCR321( 1, mkU8( 0 ) ); 9403 putCR0( 1, mkU8( 0 ) ); 9404 } 9405 9406 return True; 9407 } 9408 9409 /* DFP 64-bit logical shift instructions */ 9410 static Bool dis_dfp_shift(UInt theInstr) { 9411 UInt opc2 = ifieldOPClo9( theInstr ); 9412 UChar frS_addr = ifieldRegDS( theInstr ); 9413 UChar frA_addr = ifieldRegA( theInstr ); 9414 UChar shift_val = IFIELD(theInstr, 10, 6); 9415 UChar flag_rC = ifieldBIT0( theInstr ); 9416 9417 IRTemp frA = newTemp( Ity_D64 ); 9418 IRTemp frS = newTemp( Ity_D64 ); 9419 Bool clear_CR1 = True; 9420 9421 assign( frA, getDReg( frA_addr ) ); 9422 9423 switch (opc2) { 9424 case 0x42: // dscli 9425 DIP( "dscli%s fr%u,fr%u,%u\n", 9426 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 9427 assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) ); 9428 break; 9429 case 0x62: // dscri 9430 DIP( "dscri%s fr%u,fr%u,%u\n", 9431 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 9432 assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) ); 9433 break; 9434 } 9435 9436 putDReg( frS_addr, mkexpr( frS ) ); 9437 9438 if (flag_rC && clear_CR1) { 9439 putCR321( 1, mkU8( 0 ) ); 9440 putCR0( 1, mkU8( 0 ) ); 9441 } 9442 9443 return True; 9444 } 9445 9446 /* Quad DFP logical shift instructions */ 9447 static Bool dis_dfp_shiftq(UInt theInstr) { 9448 UInt opc2 = ifieldOPClo9( theInstr ); 9449 UChar frS_addr = ifieldRegDS( theInstr ); 9450 UChar frA_addr = ifieldRegA( theInstr ); 9451 UChar shift_val = IFIELD(theInstr, 10, 6); 9452 UChar flag_rC = ifieldBIT0( theInstr ); 9453 9454 IRTemp frA = newTemp( Ity_D128 ); 9455 IRTemp frS = newTemp( Ity_D128 ); 9456 Bool clear_CR1 = True; 9457 9458 assign( frA, getDReg_pair( frA_addr ) ); 9459 9460 switch (opc2) { 9461 case 0x42: // dscliq 9462 DIP( "dscliq%s fr%u,fr%u,%u\n", 9463 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 9464 assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) ); 9465 break; 9466 case 0x62: // dscriq 9467 DIP( "dscriq%s fr%u,fr%u,%u\n", 9468 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 9469 assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) ); 9470 break; 9471 } 9472 9473 putDReg_pair( frS_addr, mkexpr( frS ) ); 9474 9475 if (flag_rC && clear_CR1) { 9476 putCR321( 1, mkU8( 0 ) ); 9477 putCR0( 1, mkU8( 0 ) ); 9478 } 9479 9480 return True; 9481 } 9482 9483 /* DFP 64-bit format conversion instructions */ 9484 static Bool dis_dfp_fmt_conv(UInt theInstr) { 9485 UInt opc2 = ifieldOPClo10( theInstr ); 9486 UChar frS_addr = ifieldRegDS( theInstr ); 9487 UChar frB_addr = ifieldRegB( theInstr ); 9488 IRExpr* round = get_IR_roundingmode_DFP(); 9489 UChar flag_rC = ifieldBIT0( theInstr ); 9490 IRTemp frB; 9491 IRTemp frS; 9492 Bool clear_CR1 = True; 9493 9494 switch (opc2) { 9495 case 0x102: //dctdp 9496 DIP( "dctdp%s fr%u,fr%u\n", 9497 flag_rC ? ".":"", frS_addr, frB_addr ); 9498 9499 frB = newTemp( Ity_D64 ); 9500 frS = newTemp( Ity_D64 ); 9501 assign( frB, getDReg( frB_addr ) ); 9502 assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) ); 9503 putDReg( frS_addr, mkexpr( frS ) ); 9504 break; 9505 case 0x302: // drsp 9506 DIP( "drsp%s fr%u,fr%u\n", 9507 flag_rC ? ".":"", frS_addr, frB_addr ); 9508 frB = newTemp( Ity_D64 ); 9509 frS = newTemp( Ity_D64 ); 9510 assign( frB, getDReg( frB_addr ) ); 9511 assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) ); 9512 putDReg( frS_addr, mkexpr( frS ) ); 9513 break; 9514 case 0x122: // dctfix 9515 DIP( "dctfix%s fr%u,fr%u\n", 9516 flag_rC ? ".":"", frS_addr, frB_addr ); 9517 frB = newTemp( Ity_D64 ); 9518 frS = newTemp( Ity_D64 ); 9519 assign( frB, getDReg( frB_addr ) ); 9520 assign( frS, binop( Iop_D64toI64S, round, mkexpr( frB ) ) ); 9521 putDReg( frS_addr, mkexpr( frS ) ); 9522 break; 9523 case 0x322: // dcffix 9524 DIP( "dcffix%s fr%u,fr%u\n", 9525 flag_rC ? ".":"", frS_addr, frB_addr ); 9526 frB = newTemp( Ity_D64 ); 9527 frS = newTemp( Ity_D64 ); 9528 assign( frB, getDReg( frB_addr ) ); 9529 assign( frS, binop( Iop_I64StoD64, round, mkexpr( frB ) ) ); 9530 putDReg( frS_addr, mkexpr( frS ) ); 9531 break; 9532 } 9533 9534 if (flag_rC && clear_CR1) { 9535 putCR321( 1, mkU8( 0 ) ); 9536 putCR0( 1, mkU8( 0 ) ); 9537 } 9538 9539 return True; 9540 } 9541 9542 /* Quad DFP format conversion instructions */ 9543 static Bool dis_dfp_fmt_convq(UInt theInstr) { 9544 UInt opc2 = ifieldOPClo10( theInstr ); 9545 UChar frS_addr = ifieldRegDS( theInstr ); 9546 UChar frB_addr = ifieldRegB( theInstr ); 9547 IRExpr* round = get_IR_roundingmode_DFP(); 9548 IRTemp frB64 = newTemp( Ity_D64 ); 9549 IRTemp frB128 = newTemp( Ity_D128 ); 9550 IRTemp frS64 = newTemp( Ity_D64 ); 9551 IRTemp frS128 = newTemp( Ity_D128 ); 9552 UChar flag_rC = ifieldBIT0( theInstr ); 9553 Bool clear_CR1 = True; 9554 9555 switch (opc2) { 9556 case 0x102: // dctqpq 9557 DIP( "dctqpq%s fr%u,fr%u\n", 9558 flag_rC ? ".":"", frS_addr, frB_addr ); 9559 assign( frB64, getDReg( frB_addr ) ); 9560 assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) ); 9561 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 9562 break; 9563 case 0x122: // dctfixq 9564 DIP( "dctfixq%s fr%u,fr%u\n", 9565 flag_rC ? ".":"", frS_addr, frB_addr ); 9566 assign( frB128, getDReg_pair( frB_addr ) ); 9567 assign( frS64, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) ); 9568 putDReg( frS_addr, mkexpr( frS64 ) ); 9569 break; 9570 case 0x302: //drdpq 9571 DIP( "drdpq%s fr%u,fr%u\n", 9572 flag_rC ? ".":"", frS_addr, frB_addr ); 9573 assign( frB128, getDReg_pair( frB_addr ) ); 9574 assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) ); 9575 putDReg( frS_addr, mkexpr( frS64 ) ); 9576 break; 9577 case 0x322: // dcffixq 9578 /* Have to introduce an IOP for this instruction so it will work 9579 * on POWER 6 because emulating the instruction requires a POWER 7 9580 * DFP instruction in the emulation code. 9581 */ 9582 DIP( "dcffixq%s fr%u,fr%u\n", 9583 flag_rC ? ".":"", frS_addr, frB_addr ); 9584 assign( frB64, getDReg( frB_addr ) ); 9585 assign( frS128, unop( Iop_I64StoD128, mkexpr( frB64 ) ) ); 9586 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 9587 break; 9588 } 9589 9590 if (flag_rC && clear_CR1) { 9591 putCR321( 1, mkU8( 0 ) ); 9592 putCR0( 1, mkU8( 0 ) ); 9593 } 9594 9595 return True; 9596 } 9597 9598 static Bool dis_dfp_round( UInt theInstr ) { 9599 UChar frS_addr = ifieldRegDS(theInstr); 9600 UChar R = IFIELD(theInstr, 16, 1); 9601 UChar RMC = IFIELD(theInstr, 9, 2); 9602 UChar frB_addr = ifieldRegB( theInstr ); 9603 UChar flag_rC = ifieldBIT0( theInstr ); 9604 IRTemp frB = newTemp( Ity_D64 ); 9605 IRTemp frS = newTemp( Ity_D64 ); 9606 UInt opc2 = ifieldOPClo8( theInstr ); 9607 Bool clear_CR1 = True; 9608 9609 switch (opc2) { 9610 /* drintn, is the same as drintx. The only difference is this 9611 * instruction does not generate an exception for an inexact operation. 9612 * Currently not supporting inexact exceptions. 9613 */ 9614 case 0x63: // drintx 9615 case 0xE3: // drintn 9616 DIP( "drintx/drintn%s fr%u,fr%u\n", 9617 flag_rC ? ".":"", frS_addr, frB_addr ); 9618 9619 /* pass the value of R and RMC in the same field */ 9620 assign( frB, getDReg( frB_addr ) ); 9621 assign( frS, binop( Iop_RoundD64toInt, 9622 mkU32( ( R << 3 ) | RMC ), 9623 mkexpr( frB ) ) ); 9624 putDReg( frS_addr, mkexpr( frS ) ); 9625 break; 9626 default: 9627 vex_printf("dis_dfp_round(ppc)(opc2)\n"); 9628 return False; 9629 } 9630 9631 if (flag_rC && clear_CR1) { 9632 putCR321( 1, mkU8( 0 ) ); 9633 putCR0( 1, mkU8( 0 ) ); 9634 } 9635 9636 return True; 9637 } 9638 9639 static Bool dis_dfp_roundq(UInt theInstr) { 9640 UChar frS_addr = ifieldRegDS( theInstr ); 9641 UChar frB_addr = ifieldRegB( theInstr ); 9642 UChar R = IFIELD(theInstr, 16, 1); 9643 UChar RMC = IFIELD(theInstr, 9, 2); 9644 UChar flag_rC = ifieldBIT0( theInstr ); 9645 IRTemp frB = newTemp( Ity_D128 ); 9646 IRTemp frS = newTemp( Ity_D128 ); 9647 Bool clear_CR1 = True; 9648 UInt opc2 = ifieldOPClo8( theInstr ); 9649 9650 switch (opc2) { 9651 /* drintnq, is the same as drintxq. The only difference is this 9652 * instruction does not generate an exception for an inexact operation. 9653 * Currently not supporting inexact exceptions. 9654 */ 9655 case 0x63: // drintxq 9656 case 0xE3: // drintnq 9657 DIP( "drintxq/drintnq%s fr%u,fr%u\n", 9658 flag_rC ? ".":"", frS_addr, frB_addr ); 9659 9660 /* pass the value of R and RMC in the same field */ 9661 assign( frB, getDReg_pair( frB_addr ) ); 9662 assign( frS, binop( Iop_RoundD128toInt, 9663 mkU32( ( R << 3 ) | RMC ), 9664 mkexpr( frB ) ) ); 9665 putDReg_pair( frS_addr, mkexpr( frS ) ); 9666 break; 9667 default: 9668 vex_printf("dis_dfp_roundq(ppc)(opc2)\n"); 9669 return False; 9670 } 9671 9672 if (flag_rC && clear_CR1) { 9673 putCR321( 1, mkU8( 0 ) ); 9674 putCR0( 1, mkU8( 0 ) ); 9675 } 9676 9677 return True; 9678 } 9679 9680 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) { 9681 UInt opc2 = ifieldOPClo8( theInstr ); 9682 UChar frS_addr = ifieldRegDS( theInstr ); 9683 UChar frA_addr = ifieldRegA( theInstr ); 9684 UChar frB_addr = ifieldRegB( theInstr ); 9685 UChar flag_rC = ifieldBIT0( theInstr ); 9686 UInt TE_value = IFIELD(theInstr, 16, 4); 9687 UInt TE_sign = IFIELD(theInstr, 20, 1); 9688 UInt RMC = IFIELD(theInstr, 9, 2); 9689 IRTemp frA = newTemp( Ity_D64 ); 9690 IRTemp frB = newTemp( Ity_D64 ); 9691 IRTemp frS = newTemp( Ity_D64 ); 9692 Bool clear_CR1 = True; 9693 9694 assign( frB, getDReg( frB_addr ) ); 9695 9696 switch (opc2) { 9697 case 0x43: // dquai 9698 DIP( "dquai%s fr%u,fr%u,fr%u\n", 9699 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9700 IRTemp TE_D64 = newTemp( Ity_D64 ); 9701 9702 /* Generate a reference DFP value frA with the desired exponent 9703 * given by TE using significand from frB. Need to add the bias 9704 * 398 to TE. TE is stored as a 2's complement number. 9705 */ 9706 if (TE_sign == 1) { 9707 /* Take 2's complement of the 5-bit value and subtract from bias. 9708 * Bias is adjusted for the +1 required when taking 2's complement. 9709 */ 9710 assign( TE_D64, 9711 unop( Iop_ReinterpI64asD64, 9712 binop( Iop_Sub64, mkU64( 397 ), 9713 binop( Iop_And64, mkU64( 0xF ), 9714 unop( Iop_Not64, mkU64( TE_value ) ) 9715 ) ) ) ); 9716 9717 } else { 9718 assign( TE_D64, 9719 unop( Iop_ReinterpI64asD64, 9720 binop( Iop_Add64, mkU64( 398 ), mkU64( TE_value ) ) ) ); 9721 } 9722 9723 assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_D64 ), 9724 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ); 9725 9726 assign( frS, triop( Iop_QuantizeD64, 9727 mkU32( RMC ), 9728 mkexpr( frA ), 9729 mkexpr( frB ) ) ); 9730 break; 9731 9732 case 0x3: // dqua 9733 DIP( "dqua%s fr%u,fr%u,fr%u\n", 9734 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9735 assign( frA, getDReg( frA_addr ) ); 9736 assign( frS, triop( Iop_QuantizeD64, 9737 mkU32( RMC ), 9738 mkexpr( frA ), 9739 mkexpr( frB ) ) ); 9740 break; 9741 case 0x23: // drrnd 9742 DIP( "drrnd%s fr%u,fr%u,fr%u\n", 9743 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9744 assign( frA, getDReg( frA_addr ) ); 9745 assign( frS, triop( Iop_SignificanceRoundD64, 9746 mkU32( RMC ), 9747 mkexpr( frA ), 9748 mkexpr( frB ) ) ); 9749 break; 9750 default: 9751 vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n"); 9752 return False; 9753 } 9754 putDReg( frS_addr, mkexpr( frS ) ); 9755 9756 if (flag_rC && clear_CR1) { 9757 putCR321( 1, mkU8( 0 ) ); 9758 putCR0( 1, mkU8( 0 ) ); 9759 } 9760 9761 return True; 9762 } 9763 9764 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) { 9765 UInt opc2 = ifieldOPClo8( theInstr ); 9766 UChar frS_addr = ifieldRegDS( theInstr ); 9767 UChar frA_addr = ifieldRegA( theInstr ); 9768 UChar frB_addr = ifieldRegB( theInstr ); 9769 UChar flag_rC = ifieldBIT0( theInstr ); 9770 UInt TE_value = IFIELD(theInstr, 16, 4); 9771 UInt TE_sign = IFIELD(theInstr, 20, 1); 9772 UInt RMC = IFIELD(theInstr, 9, 2); 9773 IRTemp frA = newTemp( Ity_D128 ); 9774 IRTemp frB = newTemp( Ity_D128 ); 9775 IRTemp frS = newTemp( Ity_D128 ); 9776 Bool clear_CR1 = True; 9777 9778 assign( frB, getDReg_pair( frB_addr ) ); 9779 9780 switch (opc2) { 9781 case 0x43: // dquaiq 9782 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 9783 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9784 IRTemp TE_D64 = newTemp( Ity_D64 ); 9785 9786 /* Generate a reference DFP value frA with the desired exponent 9787 * given by TE using significand of 1. Need to add the bias 9788 * 6176 to TE. 9789 */ 9790 if (TE_sign == 1) { 9791 /* Take 2's complement of the 5-bit value and subtract from bias. 9792 * Bias adjusted for the +1 required when taking 2's complement. 9793 */ 9794 assign( TE_D64, 9795 unop( Iop_ReinterpI64asD64, 9796 binop( Iop_Sub64, mkU64( 6175 ), 9797 binop( Iop_And64, mkU64( 0xF ), 9798 unop( Iop_Not64, mkU64( TE_value ) ) 9799 ) ) ) ); 9800 9801 } else { 9802 assign( TE_D64, 9803 unop( Iop_ReinterpI64asD64, 9804 binop( Iop_Add64, mkU64( 6176 ), mkU64( TE_value ) ) 9805 ) ); 9806 } 9807 9808 assign( frA, 9809 binop( Iop_InsertExpD128, mkexpr( TE_D64 ), 9810 unop( Iop_D64toD128, 9811 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) ); 9812 assign( frS, triop( Iop_QuantizeD128, 9813 mkU32( RMC ), 9814 mkexpr( frA ), 9815 mkexpr( frB ) ) ); 9816 break; 9817 case 0x3: // dquaq 9818 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 9819 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9820 assign( frA, getDReg_pair( frA_addr ) ); 9821 assign( frS, triop( Iop_QuantizeD128, 9822 mkU32( RMC ), 9823 mkexpr( frA ), 9824 mkexpr( frB ) ) ); 9825 break; 9826 case 0x23: // drrndq 9827 DIP( "drrndq%s fr%u,fr%u,fr%u\n", 9828 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9829 assign( frA, getDReg_pair( frA_addr ) ); 9830 assign( frS, triop( Iop_SignificanceRoundD128, 9831 mkU32( RMC ), 9832 mkexpr( frA ), 9833 mkexpr( frB ) ) ); 9834 break; 9835 default: 9836 vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n"); 9837 return False; 9838 } 9839 putDReg_pair( frS_addr, mkexpr( frS ) ); 9840 9841 if (flag_rC && clear_CR1) { 9842 putCR321( 1, mkU8( 0 ) ); 9843 putCR0( 1, mkU8( 0 ) ); 9844 } 9845 9846 return True; 9847 } 9848 9849 static Bool dis_dfp_extract_insert(UInt theInstr) { 9850 UInt opc2 = ifieldOPClo10( theInstr ); 9851 UChar frS_addr = ifieldRegDS( theInstr ); 9852 UChar frA_addr = ifieldRegA( theInstr ); 9853 UChar frB_addr = ifieldRegB( theInstr ); 9854 UChar flag_rC = ifieldBIT0( theInstr ); 9855 Bool clear_CR1 = True; 9856 9857 IRTemp frA = newTemp( Ity_D64 ); 9858 IRTemp frB = newTemp( Ity_D64 ); 9859 IRTemp frS = newTemp( Ity_D64 ); 9860 9861 assign( frA, getDReg( frA_addr ) ); 9862 assign( frB, getDReg( frB_addr ) ); 9863 9864 switch (opc2) { 9865 case 0x162: // dxex 9866 DIP( "dxex%s fr%u,fr%u,fr%u\n", 9867 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9868 assign( frS, unop( Iop_ExtractExpD64, mkexpr( frB ) ) ); 9869 break; 9870 case 0x362: // diex 9871 DIP( "diex%s fr%u,fr%u,fr%u\n", 9872 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9873 assign( frS, binop( Iop_InsertExpD64, mkexpr( frA ), mkexpr( frB ) ) ); 9874 break; 9875 default: 9876 vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n"); 9877 return False; 9878 } 9879 9880 putDReg( frS_addr, mkexpr( frS ) ); 9881 9882 if (flag_rC && clear_CR1) { 9883 putCR321( 1, mkU8( 0 ) ); 9884 putCR0( 1, mkU8( 0 ) ); 9885 } 9886 9887 return True; 9888 } 9889 9890 static Bool dis_dfp_extract_insertq(UInt theInstr) { 9891 UInt opc2 = ifieldOPClo10( theInstr ); 9892 UChar frS_addr = ifieldRegDS( theInstr ); 9893 UChar frA_addr = ifieldRegA( theInstr ); 9894 UChar frB_addr = ifieldRegB( theInstr ); 9895 UChar flag_rC = ifieldBIT0( theInstr ); 9896 9897 IRTemp frA = newTemp( Ity_D64 ); 9898 IRTemp frB = newTemp( Ity_D128 ); 9899 IRTemp frS64 = newTemp( Ity_D64 ); 9900 IRTemp frS = newTemp( Ity_D128 ); 9901 Bool clear_CR1 = True; 9902 9903 assign( frB, getDReg_pair( frB_addr ) ); 9904 9905 switch (opc2) { 9906 case 0x162: // dxexq 9907 DIP( "dxexq%s fr%u,fr%u\n", 9908 flag_rC ? ".":"", frS_addr, frB_addr ); 9909 /* Instruction actually returns a 64-bit result. So as to be 9910 * consistent and not have to add a new struct, the emulation returns 9911 * the 64-bit result in the upper and lower register. 9912 */ 9913 assign( frS64, unop( Iop_ExtractExpD128, mkexpr( frB ) ) ); 9914 putDReg( frS_addr, mkexpr( frS64 ) ); 9915 break; 9916 case 0x362: // diexq 9917 DIP( "diexq%s fr%u,fr%u,fr%u\n", 9918 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9919 assign( frA, getDReg( frA_addr ) ); 9920 assign( frS, binop( Iop_InsertExpD128, mkexpr( frA ), mkexpr( frB ) ) ); 9921 putDReg_pair( frS_addr, mkexpr( frS ) ); 9922 break; 9923 default: 9924 vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n"); 9925 return False; 9926 } 9927 9928 if (flag_rC && clear_CR1) { 9929 putCR321( 1, mkU8( 0 ) ); 9930 putCR0( 1, mkU8( 0 ) ); 9931 } 9932 9933 return True; 9934 } 9935 9936 /* DFP 64-bit comparison instructions */ 9937 static Bool dis_dfp_compare(UInt theInstr) { 9938 /* X-Form */ 9939 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 9940 UChar frA_addr = ifieldRegA( theInstr ); 9941 UChar frB_addr = ifieldRegB( theInstr ); 9942 UInt opc1 = ifieldOPC( theInstr ); 9943 IRTemp frA; 9944 IRTemp frB; 9945 9946 IRTemp ccIR = newTemp( Ity_I32 ); 9947 IRTemp ccPPC32 = newTemp( Ity_I32 ); 9948 9949 9950 /* Note: Differences between dcmpu and dcmpo are only in exception 9951 flag settings, which aren't supported anyway. */ 9952 switch (opc1) { 9953 case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */ 9954 DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 9955 frA = newTemp( Ity_D64 ); 9956 frB = newTemp( Ity_D64 ); 9957 9958 assign( frA, getDReg( frA_addr ) ); 9959 assign( frB, getDReg( frB_addr ) ); 9960 9961 assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) ); 9962 break; 9963 case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */ 9964 DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 9965 frA = newTemp( Ity_D128 ); 9966 frB = newTemp( Ity_D128 ); 9967 9968 assign( frA, getDReg_pair( frA_addr ) ); 9969 assign( frB, getDReg_pair( frB_addr ) ); 9970 assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) ); 9971 break; 9972 default: 9973 vex_printf("dis_dfp_compare(ppc)(opc2)\n"); 9974 return False; 9975 } 9976 9977 /* Map compare result from IR to PPC32 */ 9978 /* 9979 FP cmp result | PPC | IR 9980 -------------------------- 9981 UN | 0x1 | 0x45 9982 EQ | 0x2 | 0x40 9983 GT | 0x4 | 0x00 9984 LT | 0x8 | 0x01 9985 */ 9986 9987 assign( ccPPC32, 9988 binop( Iop_Shl32, 9989 mkU32( 1 ), 9990 unop( Iop_32to8, 9991 binop( Iop_Or32, 9992 binop( Iop_And32, 9993 unop( Iop_Not32, 9994 binop( Iop_Shr32, 9995 mkexpr( ccIR ), 9996 mkU8( 5 ) ) ), 9997 mkU32( 2 ) ), 9998 binop( Iop_And32, 9999 binop( Iop_Xor32, 10000 mkexpr( ccIR ), 10001 binop( Iop_Shr32, 10002 mkexpr( ccIR ), 10003 mkU8( 6 ) ) ), 10004 mkU32( 1 ) ) ) ) ) ); 10005 10006 putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD ); 10007 return True; 10008 } 10009 10010 /* Test class/group/exponent/significance instructions. */ 10011 static Bool dis_dfp_exponent_test ( UInt theInstr ) 10012 { 10013 UChar frA_addr = ifieldRegA( theInstr ); 10014 UChar frB_addr = ifieldRegB( theInstr ); 10015 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 10016 IRTemp frA = newTemp( Ity_D64 ); 10017 IRTemp frB = newTemp( Ity_D64 ); 10018 IRTemp frA128 = newTemp( Ity_D128 ); 10019 IRTemp frB128 = newTemp( Ity_D128 ); 10020 UInt opc1 = ifieldOPC( theInstr ); 10021 IRTemp gfield_A = newTemp( Ity_I32 ); 10022 IRTemp gfield_B = newTemp( Ity_I32 ); 10023 IRTemp gfield_mask = newTemp( Ity_I32 ); 10024 IRTemp exponent_A = newTemp( Ity_I32 ); 10025 IRTemp exponent_B = newTemp( Ity_I32 ); 10026 IRTemp A_NaN_true = newTemp( Ity_I32 ); 10027 IRTemp B_NaN_true = newTemp( Ity_I32 ); 10028 IRTemp A_inf_true = newTemp( Ity_I32 ); 10029 IRTemp B_inf_true = newTemp( Ity_I32 ); 10030 IRTemp A_equals_B = newTemp( Ity_I32 ); 10031 IRTemp finite_number = newTemp( Ity_I32 ); 10032 IRTemp cc0 = newTemp( Ity_I32 ); 10033 IRTemp cc1 = newTemp( Ity_I32 ); 10034 IRTemp cc2 = newTemp( Ity_I32 ); 10035 IRTemp cc3 = newTemp( Ity_I32 ); 10036 10037 /* The dtstex and dtstexg instructions only differ in the size of the 10038 * exponent field. The following switch statement takes care of the size 10039 * specific setup. Once the value of the exponents, the G-field shift 10040 * and mask is setup the remaining code is identical. 10041 */ 10042 switch (opc1) { 10043 case 0x3b: // dtstex Extended instruction setup 10044 DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 10045 assign( frA, getDReg( frA_addr ) ); 10046 assign( frB, getDReg( frB_addr ) ); 10047 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 10048 assign(exponent_A, unop( Iop_64to32, 10049 unop( Iop_ReinterpD64asI64, 10050 unop( Iop_ExtractExpD64, 10051 mkexpr( frA ) ) ) ) ); 10052 assign(exponent_B, unop( Iop_64to32, 10053 unop( Iop_ReinterpD64asI64, 10054 unop( Iop_ExtractExpD64, 10055 mkexpr( frB ) ) ) ) ); 10056 break; 10057 10058 case 0x3F: // dtstexq Quad instruction setup 10059 DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 10060 assign( frA128, getDReg_pair( frA_addr ) ); 10061 assign( frB128, getDReg_pair( frB_addr ) ); 10062 assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) ); 10063 assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) ); 10064 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 10065 assign( exponent_A, unop( Iop_64to32, 10066 unop( Iop_ReinterpD64asI64, 10067 unop( Iop_ExtractExpD128, 10068 mkexpr( frA128 ) ) ) ) ); 10069 assign( exponent_B, unop( Iop_64to32, 10070 unop( Iop_ReinterpD64asI64, 10071 unop( Iop_ExtractExpD128, 10072 mkexpr( frB128 ) ) ) ) ); 10073 break; 10074 default: 10075 vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n"); 10076 return False; 10077 } 10078 10079 /* Extract the Gfield */ 10080 assign( gfield_A, binop( Iop_And32, 10081 mkexpr( gfield_mask ), 10082 unop( Iop_64HIto32, 10083 unop( Iop_ReinterpD64asI64, 10084 mkexpr(frA) ) ) ) ); 10085 10086 assign( gfield_B, binop( Iop_And32, 10087 mkexpr( gfield_mask ), 10088 unop( Iop_64HIto32, 10089 unop( Iop_ReinterpD64asI64, 10090 mkexpr(frB) ) ) ) ); 10091 10092 /* check for NAN */ 10093 assign( A_NaN_true, binop(Iop_Or32, 10094 unop( Iop_1Sto32, 10095 binop( Iop_CmpEQ32, 10096 mkexpr( gfield_A ), 10097 mkU32( 0x7C000000 ) ) ), 10098 unop( Iop_1Sto32, 10099 binop( Iop_CmpEQ32, 10100 mkexpr( gfield_A ), 10101 mkU32( 0x7E000000 ) ) 10102 ) ) ); 10103 assign( B_NaN_true, binop(Iop_Or32, 10104 unop( Iop_1Sto32, 10105 binop( Iop_CmpEQ32, 10106 mkexpr( gfield_B ), 10107 mkU32( 0x7C000000 ) ) ), 10108 unop( Iop_1Sto32, 10109 binop( Iop_CmpEQ32, 10110 mkexpr( gfield_B ), 10111 mkU32( 0x7E000000 ) ) 10112 ) ) ); 10113 10114 /* check for infinity */ 10115 assign( A_inf_true, 10116 unop( Iop_1Sto32, 10117 binop( Iop_CmpEQ32, 10118 mkexpr( gfield_A ), 10119 mkU32( 0x78000000 ) ) ) ); 10120 10121 assign( B_inf_true, 10122 unop( Iop_1Sto32, 10123 binop( Iop_CmpEQ32, 10124 mkexpr( gfield_B ), 10125 mkU32( 0x78000000 ) ) ) ); 10126 10127 assign( finite_number, 10128 unop( Iop_Not32, 10129 binop( Iop_Or32, 10130 binop( Iop_Or32, 10131 mkexpr( A_NaN_true ), 10132 mkexpr( B_NaN_true ) ), 10133 binop( Iop_Or32, 10134 mkexpr( A_inf_true ), 10135 mkexpr( B_inf_true ) ) ) ) ); 10136 10137 /* Calculate the condition code bits 10138 * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero 10139 * regardless of the value of the comparisons and cc3 is 1. Otherwise, 10140 * cc0, cc1 and cc0 reflect the results of the comparisons. 10141 */ 10142 assign( A_equals_B, 10143 binop( Iop_Or32, 10144 unop( Iop_1Uto32, 10145 binop( Iop_CmpEQ32, 10146 mkexpr( exponent_A ), 10147 mkexpr( exponent_B ) ) ), 10148 binop( Iop_Or32, 10149 binop( Iop_And32, 10150 mkexpr( A_inf_true ), 10151 mkexpr( B_inf_true ) ), 10152 binop( Iop_And32, 10153 mkexpr( A_NaN_true ), 10154 mkexpr( B_NaN_true ) ) ) ) ); 10155 10156 assign( cc0, binop( Iop_And32, 10157 mkexpr( finite_number ), 10158 binop( Iop_Shl32, 10159 unop( Iop_1Uto32, 10160 binop( Iop_CmpLT32U, 10161 mkexpr( exponent_A ), 10162 mkexpr( exponent_B ) ) ), 10163 mkU8( 3 ) ) ) ); 10164 10165 assign( cc1, binop( Iop_And32, 10166 mkexpr( finite_number ), 10167 binop( Iop_Shl32, 10168 unop( Iop_1Uto32, 10169 binop( Iop_CmpLT32U, 10170 mkexpr( exponent_B ), 10171 mkexpr( exponent_A ) ) ), 10172 mkU8( 2 ) ) ) ); 10173 10174 assign( cc2, binop( Iop_Shl32, 10175 binop( Iop_And32, 10176 mkexpr( A_equals_B ), 10177 mkU32( 1 ) ), 10178 mkU8( 1 ) ) ); 10179 10180 assign( cc3, binop( Iop_And32, 10181 unop( Iop_Not32, mkexpr( A_equals_B ) ), 10182 binop( Iop_And32, 10183 mkU32( 0x1 ), 10184 binop( Iop_Or32, 10185 binop( Iop_Or32, 10186 mkexpr ( A_inf_true ), 10187 mkexpr ( B_inf_true ) ), 10188 binop( Iop_Or32, 10189 mkexpr ( A_NaN_true ), 10190 mkexpr ( B_NaN_true ) ) ) 10191 ) ) ); 10192 10193 /* store the condition code */ 10194 putGST_field( PPC_GST_CR, 10195 binop( Iop_Or32, 10196 mkexpr( cc0 ), 10197 binop( Iop_Or32, 10198 mkexpr( cc1 ), 10199 binop( Iop_Or32, 10200 mkexpr( cc2 ), 10201 mkexpr( cc3 ) ) ) ), 10202 crfD ); 10203 return True; 10204 } 10205 10206 /* Test class/group/exponent/significance instructions. */ 10207 static Bool dis_dfp_class_test ( UInt theInstr ) 10208 { 10209 UChar frA_addr = ifieldRegA( theInstr ); 10210 IRTemp frA = newTemp( Ity_D64 ); 10211 IRTemp abs_frA = newTemp( Ity_D64 ); 10212 IRTemp frAI64_hi = newTemp( Ity_I64 ); 10213 IRTemp frAI64_lo = newTemp( Ity_I64 ); 10214 UInt opc1 = ifieldOPC( theInstr ); 10215 UInt opc2 = ifieldOPClo9( theInstr ); 10216 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 10217 UInt DCM = IFIELD( theInstr, 10, 6 ); 10218 IRTemp DCM_calc = newTemp( Ity_I32 ); 10219 UInt max_exp = 0; 10220 UInt min_exp = 0; 10221 IRTemp min_subnormalD64 = newTemp( Ity_D64 ); 10222 IRTemp min_subnormalD128 = newTemp( Ity_D128 ); 10223 IRTemp significand64 = newTemp( Ity_D64 ); 10224 IRTemp significand128 = newTemp( Ity_D128 ); 10225 IRTemp exp_min_normal = newTemp( Ity_D64 ); 10226 IRTemp exponent = newTemp( Ity_I32 ); 10227 10228 IRTemp infinity_true = newTemp( Ity_I32 ); 10229 IRTemp SNaN_true = newTemp( Ity_I32 ); 10230 IRTemp QNaN_true = newTemp( Ity_I32 ); 10231 IRTemp subnormal_true = newTemp( Ity_I32 ); 10232 IRTemp normal_true = newTemp( Ity_I32 ); 10233 IRTemp extreme_true = newTemp( Ity_I32 ); 10234 IRTemp lmd = newTemp( Ity_I32 ); 10235 IRTemp lmd_zero_true = newTemp( Ity_I32 ); 10236 IRTemp zero_true = newTemp( Ity_I32 ); 10237 IRTemp sign = newTemp( Ity_I32 ); 10238 IRTemp field = newTemp( Ity_I32 ); 10239 IRTemp ccIR_zero = newTemp( Ity_I32 ); 10240 IRTemp ccIR_subnormal = newTemp( Ity_I32 ); 10241 10242 /* UInt size = DFP_LONG; JRS:unused */ 10243 IRTemp gfield = newTemp( Ity_I32 ); 10244 IRTemp gfield_0_4_shift = newTemp( Ity_I8 ); 10245 IRTemp gfield_mask = newTemp( Ity_I32 ); 10246 IRTemp dcm0 = newTemp( Ity_I32 ); 10247 IRTemp dcm1 = newTemp( Ity_I32 ); 10248 IRTemp dcm2 = newTemp( Ity_I32 ); 10249 IRTemp dcm3 = newTemp( Ity_I32 ); 10250 IRTemp dcm4 = newTemp( Ity_I32 ); 10251 IRTemp dcm5 = newTemp( Ity_I32 ); 10252 10253 /* The only difference between the dtstdc and dtstdcq instructions is 10254 * size of the T and G fields. The calculation of the 4 bit field 10255 * is the same. Setup the parameters and values that are DFP size 10256 * specific. The rest of the code is independent of the DFP size. 10257 * 10258 * The Io_CmpD64 is used below. The instruction sets the ccIR values. 10259 * The interpretation of the ccIR values is as follows: 10260 * 10261 * DFP cmp result | IR 10262 * -------------------------- 10263 * UN | 0x45 10264 * EQ | 0x40 10265 * GT | 0x00 10266 * LT | 0x01 10267 */ 10268 10269 assign( frA, getDReg( frA_addr ) ); 10270 assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) ); 10271 10272 assign( abs_frA, unop( Iop_ReinterpI64asD64, 10273 binop( Iop_And64, 10274 unop( Iop_ReinterpD64asI64, 10275 mkexpr( frA ) ), 10276 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) ); 10277 assign( gfield_0_4_shift, mkU8( 31 - 5 ) ); // G-field[0:4] 10278 switch (opc1) { 10279 case 0x3b: // dtstdc, dtstdg 10280 DIP("dtstd%s %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g", 10281 crfD, frA_addr, DCM); 10282 /* setup the parameters for the long format of the two instructions */ 10283 assign( frAI64_lo, mkU64( 0 ) ); 10284 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 10285 max_exp = DFP_LONG_EXP_MAX; 10286 min_exp = DFP_LONG_EXP_MIN; 10287 10288 assign( exponent, unop( Iop_64to32, 10289 unop( Iop_ReinterpD64asI64, 10290 unop( Iop_ExtractExpD64, 10291 mkexpr( frA ) ) ) ) ); 10292 assign( significand64, 10293 unop( Iop_ReinterpI64asD64, 10294 mkU64( 0x2234000000000001ULL ) ) ); // dfp 1.0 10295 assign( exp_min_normal, 10296 unop( Iop_ReinterpI64asD64, mkU64( 398 - 383 ) ) ); 10297 assign( min_subnormalD64, 10298 binop( Iop_InsertExpD64, 10299 mkexpr( exp_min_normal ), 10300 mkexpr( significand64 ) ) ); 10301 10302 assign( ccIR_subnormal, 10303 binop( Iop_CmpD64, 10304 mkexpr( abs_frA ), 10305 mkexpr( min_subnormalD64 ) ) ); 10306 10307 /* compare absolute value of frA with zero */ 10308 assign( ccIR_zero, 10309 binop( Iop_CmpD64, 10310 mkexpr( abs_frA ), 10311 unop( Iop_ReinterpI64asD64, 10312 mkU64( 0x2238000000000000ULL ) ) ) ); 10313 10314 /* size = DFP_LONG; JRS: unused */ 10315 break; 10316 10317 case 0x3F: // dtstdcq, dtstdgq 10318 DIP("dtstd%sq %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g", 10319 crfD, frA_addr, DCM); 10320 /* setup the parameters for the extended format of the 10321 * two instructions 10322 */ 10323 assign( frAI64_lo, unop( Iop_ReinterpD64asI64, 10324 getDReg( frA_addr+1 ) ) ); 10325 10326 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 10327 max_exp = DFP_EXTND_EXP_MAX; 10328 min_exp = DFP_EXTND_EXP_MIN; 10329 assign( exponent, unop( Iop_64to32, 10330 unop( Iop_ReinterpD64asI64, 10331 unop( Iop_ExtractExpD128, 10332 getDReg_pair( frA_addr) ) ) ) ); 10333 10334 /* create quand exponent for minimum normal number */ 10335 assign( exp_min_normal, 10336 unop( Iop_ReinterpI64asD64, mkU64( 6176 - 6143 ) ) ); 10337 assign( significand128, 10338 unop( Iop_D64toD128, 10339 unop( Iop_ReinterpI64asD64, 10340 mkU64( 0x2234000000000001ULL ) ) ) ); // dfp 1.0 10341 10342 assign( min_subnormalD128, 10343 binop( Iop_InsertExpD128, 10344 mkexpr( exp_min_normal ), 10345 mkexpr( significand128 ) ) ); 10346 10347 assign( ccIR_subnormal, 10348 binop( Iop_CmpD128, 10349 binop( Iop_D64HLtoD128, 10350 unop( Iop_ReinterpI64asD64, 10351 binop( Iop_And64, 10352 unop( Iop_ReinterpD64asI64, 10353 mkexpr( frA ) ), 10354 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ), 10355 getDReg( frA_addr+1 ) ), 10356 mkexpr( min_subnormalD128 ) ) ); 10357 assign( ccIR_zero, 10358 binop( Iop_CmpD128, 10359 binop( Iop_D64HLtoD128, 10360 mkexpr( abs_frA ), 10361 getDReg( frA_addr+1 ) ), 10362 unop( Iop_D64toD128, 10363 unop( Iop_ReinterpI64asD64, 10364 mkU64( 0x0ULL ) ) ) ) ); 10365 10366 /* size = DFP_EXTND; JRS:unused */ 10367 break; 10368 default: 10369 vex_printf("dis_dfp_class_test(ppc)(opc2)\n"); 10370 return False; 10371 } 10372 10373 /* The G-field is in the upper 32-bits. The I64 logical operations 10374 * do not seem to be supported in 32-bit mode so keep things as 32-bit 10375 * operations. 10376 */ 10377 assign( gfield, binop( Iop_And32, 10378 mkexpr( gfield_mask ), 10379 unop( Iop_64HIto32, 10380 mkexpr(frAI64_hi) ) ) ); 10381 10382 /* There is a lot of code that is the same to do the class and group 10383 * instructions. Later there is an if statement to handle the specific 10384 * instruction. 10385 * 10386 * Will be using I32 values, compares, shifts and logical operations for 10387 * this code as the 64-bit compare, shifts, logical operations are not 10388 * supported in 32-bit mode. 10389 */ 10390 10391 /* Check the bits for Infinity, QNaN or Signaling NaN */ 10392 assign( infinity_true, 10393 unop( Iop_1Sto32, 10394 binop( Iop_CmpEQ32, 10395 binop( Iop_And32, 10396 mkU32( 0x7C000000 ), 10397 mkexpr( gfield ) ), 10398 mkU32( 0x78000000 ) ) ) ); 10399 10400 assign( SNaN_true, 10401 unop( Iop_1Sto32, 10402 binop( Iop_CmpEQ32, 10403 binop( Iop_And32, 10404 mkU32( 0x7E000000 ), 10405 mkexpr( gfield ) ), 10406 mkU32( 0x7E000000 ) ) ) ); 10407 10408 assign( QNaN_true, 10409 binop( Iop_And32, 10410 unop( Iop_1Sto32, 10411 binop( Iop_CmpEQ32, 10412 binop( Iop_And32, 10413 mkU32( 0x7E000000 ), 10414 mkexpr( gfield ) ), 10415 mkU32( 0x7C000000 ) ) ), 10416 unop( Iop_Not32, 10417 mkexpr( SNaN_true ) ) ) ); 10418 10419 assign( zero_true, 10420 binop( Iop_And32, 10421 unop(Iop_1Sto32, 10422 binop( Iop_CmpEQ32, 10423 mkexpr( ccIR_zero ), 10424 mkU32( 0x40 ) ) ), // ccIR code for Equal 10425 unop( Iop_Not32, 10426 binop( Iop_Or32, 10427 mkexpr( infinity_true ), 10428 binop( Iop_Or32, 10429 mkexpr( QNaN_true ), 10430 mkexpr( SNaN_true ) ) ) ) ) ); 10431 10432 /* Do compare of frA the minimum normal value. Comparison is size 10433 * depenent and was done above to get the ccIR value. 10434 */ 10435 assign( subnormal_true, 10436 binop( Iop_And32, 10437 binop( Iop_Or32, 10438 unop( Iop_1Sto32, 10439 binop( Iop_CmpEQ32, 10440 mkexpr( ccIR_subnormal ), 10441 mkU32( 0x40 ) ) ), // ccIR code for Equal 10442 unop( Iop_1Sto32, 10443 binop( Iop_CmpEQ32, 10444 mkexpr( ccIR_subnormal ), 10445 mkU32( 0x1 ) ) ) ), // ccIR code for LT 10446 unop( Iop_Not32, 10447 binop( Iop_Or32, 10448 binop( Iop_Or32, 10449 mkexpr( infinity_true ), 10450 mkexpr( zero_true) ), 10451 binop( Iop_Or32, 10452 mkexpr( QNaN_true ), 10453 mkexpr( SNaN_true ) ) ) ) ) ); 10454 10455 /* Normal number is not subnormal, infinity, NaN or Zero */ 10456 assign( normal_true, 10457 unop( Iop_Not32, 10458 binop( Iop_Or32, 10459 binop( Iop_Or32, 10460 mkexpr( infinity_true ), 10461 mkexpr( zero_true ) ), 10462 binop( Iop_Or32, 10463 mkexpr( subnormal_true ), 10464 binop( Iop_Or32, 10465 mkexpr( QNaN_true ), 10466 mkexpr( SNaN_true ) ) ) ) ) ); 10467 10468 /* Calculate the DCM bit field based on the tests for the specific 10469 * instruction 10470 */ 10471 if (opc2 == 0xC2) { // dtstdc, dtstdcq 10472 /* DCM[0:5] Bit Data Class definition 10473 * 0 Zero 10474 * 1 Subnormal 10475 * 2 Normal 10476 * 3 Infinity 10477 * 4 Quiet NaN 10478 * 5 Signaling NaN 10479 */ 10480 10481 assign( dcm0, binop( Iop_Shl32, 10482 mkexpr( zero_true ), 10483 mkU8( 5 ) ) ); 10484 assign( dcm1, binop( Iop_Shl32, 10485 binop( Iop_And32, 10486 mkexpr( subnormal_true ), 10487 mkU32( 1 ) ), 10488 mkU8( 4 ) ) ); 10489 assign( dcm2, binop( Iop_Shl32, 10490 binop( Iop_And32, 10491 mkexpr( normal_true ), 10492 mkU32( 1 ) ), 10493 mkU8( 3 ) ) ); 10494 assign( dcm3, binop( Iop_Shl32, 10495 binop( Iop_And32, 10496 mkexpr( infinity_true), 10497 mkU32( 1 ) ), 10498 mkU8( 2 ) ) ); 10499 assign( dcm4, binop( Iop_Shl32, 10500 binop( Iop_And32, 10501 mkexpr( QNaN_true ), 10502 mkU32( 1 ) ), 10503 mkU8( 1 ) ) ); 10504 assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) ); 10505 10506 } else if (opc2 == 0xE2) { // dtstdg, dtstdgq 10507 /* check if the exponent is extreme */ 10508 assign( extreme_true, binop( Iop_Or32, 10509 unop( Iop_1Sto32, 10510 binop( Iop_CmpEQ32, 10511 mkexpr( exponent ), 10512 mkU32( max_exp ) ) ), 10513 unop( Iop_1Sto32, 10514 binop( Iop_CmpEQ32, 10515 mkexpr( exponent ), 10516 mkU32( min_exp ) ) ) ) ); 10517 10518 /* Check if LMD is zero */ 10519 Get_lmd( &lmd, binop( Iop_Shr32, 10520 mkexpr( gfield ), mkU8( 31 - 5 ) ) ); 10521 10522 assign( lmd_zero_true, unop( Iop_1Sto32, 10523 binop( Iop_CmpEQ32, 10524 mkexpr( lmd ), 10525 mkU32( 0 ) ) ) ); 10526 10527 /* DCM[0:5] Bit Data Class definition 10528 * 0 Zero with non-extreme exponent 10529 * 1 Zero with extreme exponent 10530 * 2 Subnormal or (Normal with extreme exponent) 10531 * 3 Normal with non-extreme exponent and 10532 * leftmost zero digit in significand 10533 * 4 Normal with non-extreme exponent and 10534 * leftmost nonzero digit in significand 10535 * 5 Special symbol (Infinity, QNaN, or SNaN) 10536 */ 10537 assign( dcm0, binop( Iop_Shl32, 10538 binop( Iop_And32, 10539 binop( Iop_And32, 10540 unop( Iop_Not32, 10541 mkexpr( extreme_true ) ), 10542 mkexpr( zero_true ) ), 10543 mkU32( 0x1 ) ), 10544 mkU8( 5 ) ) ); 10545 10546 assign( dcm1, binop( Iop_Shl32, 10547 binop( Iop_And32, 10548 binop( Iop_And32, 10549 mkexpr( extreme_true ), 10550 mkexpr( zero_true ) ), 10551 mkU32( 0x1 ) ), 10552 mkU8( 4 ) ) ); 10553 10554 assign( dcm2, binop( Iop_Shl32, 10555 binop( Iop_And32, 10556 binop( Iop_Or32, 10557 binop( Iop_And32, 10558 mkexpr( extreme_true ), 10559 mkexpr( normal_true ) ), 10560 mkexpr( subnormal_true ) ), 10561 mkU32( 0x1 ) ), 10562 mkU8( 3 ) ) ); 10563 10564 assign( dcm3, binop( Iop_Shl32, 10565 binop( Iop_And32, 10566 binop( Iop_And32, 10567 binop( Iop_And32, 10568 unop( Iop_Not32, 10569 mkexpr( extreme_true ) ), 10570 mkexpr( normal_true ) ), 10571 unop( Iop_1Sto32, 10572 binop( Iop_CmpEQ32, 10573 mkexpr( lmd ), 10574 mkU32( 0 ) ) ) ), 10575 mkU32( 0x1 ) ), 10576 mkU8( 2 ) ) ); 10577 10578 assign( dcm4, binop( Iop_Shl32, 10579 binop( Iop_And32, 10580 binop( Iop_And32, 10581 binop( Iop_And32, 10582 unop( Iop_Not32, 10583 mkexpr( extreme_true ) ), 10584 mkexpr( normal_true ) ), 10585 unop( Iop_1Sto32, 10586 binop( Iop_CmpNE32, 10587 mkexpr( lmd ), 10588 mkU32( 0 ) ) ) ), 10589 mkU32( 0x1 ) ), 10590 mkU8( 1 ) ) ); 10591 10592 assign( dcm5, binop( Iop_And32, 10593 binop( Iop_Or32, 10594 mkexpr( SNaN_true), 10595 binop( Iop_Or32, 10596 mkexpr( QNaN_true), 10597 mkexpr( infinity_true) ) ), 10598 mkU32( 0x1 ) ) ); 10599 } 10600 10601 /* create DCM field */ 10602 assign( DCM_calc, 10603 binop( Iop_Or32, 10604 mkexpr( dcm0 ), 10605 binop( Iop_Or32, 10606 mkexpr( dcm1 ), 10607 binop( Iop_Or32, 10608 mkexpr( dcm2 ), 10609 binop( Iop_Or32, 10610 mkexpr( dcm3 ), 10611 binop( Iop_Or32, 10612 mkexpr( dcm4 ), 10613 mkexpr( dcm5 ) ) ) ) ) ) ); 10614 10615 /* Get the sign of the DFP number, ignore sign for QNaN */ 10616 assign( sign, 10617 unop( Iop_1Uto32, 10618 binop( Iop_CmpEQ32, 10619 binop( Iop_Shr32, 10620 unop( Iop_64HIto32, mkexpr( frAI64_hi ) ), 10621 mkU8( 63 - 32 ) ), 10622 mkU32( 1 ) ) ) ); 10623 10624 /* This instruction generates a four bit field to be stored in the 10625 * condition code register. The condition code register consists of 7 10626 * fields. The field to be written to is specified by the BF (AKA crfD) 10627 * field. 10628 * 10629 * The field layout is as follows: 10630 * 10631 * Field Meaning 10632 * 0000 Operand positive with no match 10633 * 0100 Operand positive with at least one match 10634 * 0001 Operand negative with no match 10635 * 0101 Operand negative with at least one match 10636 */ 10637 assign( field, binop( Iop_Or32, 10638 binop( Iop_Shl32, 10639 mkexpr( sign ), 10640 mkU8( 3 ) ), 10641 binop( Iop_Shl32, 10642 unop( Iop_1Uto32, 10643 binop( Iop_CmpNE32, 10644 binop( Iop_And32, 10645 mkU32( DCM ), 10646 mkexpr( DCM_calc ) ), 10647 mkU32( 0 ) ) ), 10648 mkU8( 1 ) ) ) ); 10649 10650 putGST_field( PPC_GST_CR, mkexpr( field ), crfD ); 10651 return True; 10652 } 10653 10654 static Bool dis_dfp_bcd(UInt theInstr) { 10655 UInt opc2 = ifieldOPClo10( theInstr ); 10656 ULong sp = IFIELD(theInstr, 19, 2); 10657 ULong s = IFIELD(theInstr, 20, 1); 10658 UChar frT_addr = ifieldRegDS( theInstr ); 10659 UChar frB_addr = ifieldRegB( theInstr ); 10660 IRTemp frB = newTemp( Ity_D64 ); 10661 IRTemp frBI64 = newTemp( Ity_I64 ); 10662 IRTemp result = newTemp( Ity_I64 ); 10663 IRTemp resultD64 = newTemp( Ity_D64 ); 10664 IRTemp bcd64 = newTemp( Ity_I64 ); 10665 IRTemp bcd_u = newTemp( Ity_I32 ); 10666 IRTemp bcd_l = newTemp( Ity_I32 ); 10667 IRTemp dbcd_u = newTemp( Ity_I32 ); 10668 IRTemp dbcd_l = newTemp( Ity_I32 ); 10669 IRTemp lmd = newTemp( Ity_I32 ); 10670 10671 assign( frB, getDReg( frB_addr ) ); 10672 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 10673 10674 switch ( opc2 ) { 10675 case 0x142: // ddedpd DFP Decode DPD to BCD 10676 DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 10677 10678 assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 10679 assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) ); 10680 assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) ); 10681 10682 if ( ( sp == 0 ) || ( sp == 1 ) ) { 10683 /* Unsigned BCD string */ 10684 Get_lmd( &lmd, 10685 binop( Iop_Shr32, 10686 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 10687 mkU8( 31 - 5 ) ) ); // G-field[0:4] 10688 10689 assign( result, 10690 binop( Iop_32HLto64, 10691 binop( Iop_Or32, 10692 binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ), 10693 mkexpr( bcd_u ) ), 10694 mkexpr( bcd_l ) ) ); 10695 10696 } else { 10697 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 10698 * the positive and negative values are encoded in the least 10699 * significant bits. 10700 */ 10701 IRTemp sign = newTemp( Ity_I32 ); 10702 10703 if (sp == 2) { 10704 /* Positive sign = 0xC, negative sign = 0xD */ 10705 10706 assign( sign, 10707 binop( Iop_Or32, 10708 binop( Iop_Shr32, 10709 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 10710 mkU8( 31 ) ), 10711 mkU32( 0xC ) ) ); 10712 10713 } else if ( sp == 3 ) { 10714 /* Positive sign = 0xF, negative sign = 0xD */ 10715 IRTemp tmp32 = newTemp( Ity_I32 ); 10716 10717 /* Complement sign bit then OR into bit position 1 */ 10718 assign( tmp32, 10719 binop( Iop_Xor32, 10720 binop( Iop_Shr32, 10721 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 10722 mkU8( 30 ) ), 10723 mkU32( 0x2 ) ) ); 10724 10725 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 10726 10727 } else { 10728 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 10729 } 10730 10731 /* Put sign in bottom 4 bits, move most significant 4-bits from 10732 * bcd_l to bcd_u. 10733 */ 10734 assign( result, 10735 binop( Iop_32HLto64, 10736 binop( Iop_Or32, 10737 binop( Iop_Shr32, 10738 mkexpr( bcd_l ), 10739 mkU8( 28 ) ), 10740 binop( Iop_Shl32, 10741 mkexpr( bcd_u ), 10742 mkU8( 4 ) ) ), 10743 binop( Iop_Or32, 10744 mkexpr( sign ), 10745 binop( Iop_Shl32, 10746 mkexpr( bcd_l ), 10747 mkU8( 4 ) ) ) ) ); 10748 } 10749 10750 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) ); 10751 break; 10752 10753 case 0x342: // denbcd DFP Encode BCD to DPD 10754 { 10755 IRTemp valid_mask = newTemp( Ity_I32 ); 10756 IRTemp invalid_mask = newTemp( Ity_I32 ); 10757 IRTemp without_lmd = newTemp( Ity_I64 ); 10758 IRTemp tmp64 = newTemp( Ity_I64 ); 10759 IRTemp dbcd64 = newTemp( Ity_I64 ); 10760 IRTemp left_exp = newTemp( Ity_I32 ); 10761 IRTemp g0_4 = newTemp( Ity_I32 ); 10762 10763 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 10764 10765 if ( s == 0 ) { 10766 /* Unsigned BCD string */ 10767 assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) ); 10768 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) ); 10769 assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) ); 10770 10771 assign( lmd, 10772 binop( Iop_Shr32, 10773 binop( Iop_And32, 10774 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 10775 mkU32( 0xF0000000 ) ), 10776 mkU8( 28 ) ) ); 10777 10778 assign( invalid_mask, 10779 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ), 10780 unop( Iop_64to32, mkexpr( frBI64 ) ) ) ); 10781 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 10782 10783 assign( without_lmd, 10784 unop( Iop_ReinterpD64asI64, 10785 binop( Iop_InsertExpD64, 10786 unop( Iop_ReinterpI64asD64, 10787 mkU64( DFP_LONG_BIAS ) ), 10788 unop( Iop_ReinterpI64asD64, 10789 binop( Iop_32HLto64, 10790 mkexpr( dbcd_u ), 10791 mkexpr( dbcd_l ) ) ) ) ) ); 10792 assign( left_exp, 10793 binop( Iop_Shr32, 10794 binop( Iop_And32, 10795 unop( Iop_64HIto32, mkexpr( without_lmd ) ), 10796 mkU32( 0x60000000 ) ), 10797 mkU8( 29 ) ) ); 10798 10799 assign( g0_4, 10800 binop( Iop_Shl32, 10801 Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ), 10802 mkU8( 26 ) ) ); 10803 10804 assign( tmp64, 10805 binop( Iop_32HLto64, 10806 binop( Iop_Or32, 10807 binop( Iop_And32, 10808 unop( Iop_64HIto32, 10809 mkexpr( without_lmd ) ), 10810 mkU32( 0x83FFFFFF ) ), 10811 mkexpr( g0_4 ) ), 10812 unop( Iop_64to32, mkexpr( without_lmd ) ) ) ); 10813 10814 } else if ( s == 1 ) { 10815 IRTemp sign = newTemp( Ity_I32 ); 10816 IRTemp sign_bit = newTemp( Ity_I32 ); 10817 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 10818 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 10819 IRTemp tmp = newTemp( Ity_I64 ); 10820 10821 /* Signed BCD string, least significant 4 bits are sign bits 10822 * positive sign = 0xC, negative sign = 0xD 10823 */ 10824 assign( tmp, unop( Iop_BCDtoDPB, 10825 binop( Iop_32HLto64, 10826 binop( Iop_Shr32, 10827 unop( Iop_64HIto32, 10828 mkexpr( frBI64 ) ), 10829 mkU8( 4 ) ), 10830 binop( Iop_Or32, 10831 binop( Iop_Shr32, 10832 unop( Iop_64to32, 10833 mkexpr( frBI64 ) ), 10834 mkU8( 4 ) ), 10835 binop( Iop_Shl32, 10836 unop( Iop_64HIto32, 10837 mkexpr( frBI64 ) ), 10838 mkU8( 28 ) ) ) ) ) ); 10839 10840 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) ); 10841 assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) ); 10842 10843 /* Get the sign of the BCD string. */ 10844 assign( sign, 10845 binop( Iop_And32, 10846 unop( Iop_64to32, mkexpr( frBI64 ) ), 10847 mkU32( 0xF ) ) ); 10848 10849 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 10850 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 10851 assign( sign_bit, 10852 Generate_sign_bit( mkexpr( pos_sign_mask ), 10853 mkexpr( neg_sign_mask ) ) ); 10854 10855 /* Check for invalid sign and BCD digit. Don't check the bottom 10856 * four bits of bcd_l as that is the sign value. 10857 */ 10858 assign( invalid_mask, 10859 Generate_inv_mask( 10860 bcd_digit_inval( unop( Iop_64HIto32, 10861 mkexpr( frBI64 ) ), 10862 binop( Iop_Shr32, 10863 unop( Iop_64to32, 10864 mkexpr( frBI64 ) ), 10865 mkU8( 4 ) ) ), 10866 mkexpr( pos_sign_mask ), 10867 mkexpr( neg_sign_mask ) ) ); 10868 10869 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 10870 10871 /* Generate the result assuming the sign value was valid. */ 10872 assign( tmp64, 10873 unop( Iop_ReinterpD64asI64, 10874 binop( Iop_InsertExpD64, 10875 unop( Iop_ReinterpI64asD64, 10876 mkU64( DFP_LONG_BIAS ) ), 10877 unop( Iop_ReinterpI64asD64, 10878 binop( Iop_32HLto64, 10879 binop( Iop_Or32, 10880 mkexpr( dbcd_u ), 10881 mkexpr( sign_bit ) ), 10882 mkexpr( dbcd_l ) ) ) ) ) ); 10883 } 10884 10885 /* Generate the value to store depending on the validity of the 10886 * sign value and the validity of the BCD digits. 10887 */ 10888 assign( resultD64, 10889 unop( Iop_ReinterpI64asD64, 10890 binop( Iop_32HLto64, 10891 binop( Iop_Or32, 10892 binop( Iop_And32, 10893 mkexpr( valid_mask ), 10894 unop( Iop_64HIto32, 10895 mkexpr( tmp64 ) ) ), 10896 binop( Iop_And32, 10897 mkU32( 0x7C000000 ), 10898 mkexpr( invalid_mask ) ) ), 10899 binop( Iop_Or32, 10900 binop( Iop_And32, 10901 mkexpr( valid_mask ), 10902 unop( Iop_64to32, mkexpr( tmp64 ) ) ), 10903 binop( Iop_And32, 10904 mkU32( 0x0 ), 10905 mkexpr( invalid_mask ) ) ) ) ) ); 10906 putDReg( frT_addr, mkexpr( resultD64 ) ); 10907 } 10908 break; 10909 default: 10910 vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " ); 10911 return False; 10912 } 10913 return True; 10914 } 10915 10916 static Bool dis_dfp_bcdq( UInt theInstr ) 10917 { 10918 UInt opc2 = ifieldOPClo10( theInstr ); 10919 ULong sp = IFIELD(theInstr, 19, 2); 10920 ULong s = IFIELD(theInstr, 20, 1); 10921 IRTemp frB_hi = newTemp( Ity_D64 ); 10922 IRTemp frB_lo = newTemp( Ity_D64 ); 10923 IRTemp frBI64_hi = newTemp( Ity_I64 ); 10924 IRTemp frBI64_lo = newTemp( Ity_I64 ); 10925 UChar frT_addr = ifieldRegDS( theInstr ); 10926 UChar frB_addr = ifieldRegB( theInstr ); 10927 10928 IRTemp lmd = newTemp( Ity_I32 ); 10929 IRTemp result_hi = newTemp( Ity_I64 ); 10930 IRTemp result_lo = newTemp( Ity_I64 ); 10931 10932 assign( frB_hi, getDReg( frB_addr ) ); 10933 assign( frB_lo, getDReg( frB_addr + 1 ) ); 10934 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 10935 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 10936 10937 switch ( opc2 ) { 10938 case 0x142: // ddedpdq DFP Decode DPD to BCD 10939 { 10940 IRTemp low_60_u = newTemp( Ity_I32 ); 10941 IRTemp low_60_l = newTemp( Ity_I32 ); 10942 IRTemp mid_60_u = newTemp( Ity_I32 ); 10943 IRTemp mid_60_l = newTemp( Ity_I32 ); 10944 IRTemp top_12_l = newTemp( Ity_I32 ); 10945 10946 DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 10947 10948 /* Note, instruction only stores the lower 32 BCD digits in 10949 * the result 10950 */ 10951 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 10952 mkexpr( frBI64_lo ), 10953 &top_12_l, 10954 &mid_60_u, 10955 &mid_60_l, 10956 &low_60_u, 10957 &low_60_l ); 10958 10959 if ( ( sp == 0 ) || ( sp == 1 ) ) { 10960 /* Unsigned BCD string */ 10961 assign( result_hi, 10962 binop( Iop_32HLto64, 10963 binop( Iop_Or32, 10964 binop( Iop_Shl32, 10965 mkexpr( top_12_l ), 10966 mkU8( 24 ) ), 10967 binop( Iop_Shr32, 10968 mkexpr( mid_60_u ), 10969 mkU8( 4 ) ) ), 10970 binop( Iop_Or32, 10971 binop( Iop_Shl32, 10972 mkexpr( mid_60_u ), 10973 mkU8( 28 ) ), 10974 binop( Iop_Shr32, 10975 mkexpr( mid_60_l ), 10976 mkU8( 4 ) ) ) ) ); 10977 10978 assign( result_lo, 10979 binop( Iop_32HLto64, 10980 binop( Iop_Or32, 10981 binop( Iop_Shl32, 10982 mkexpr( mid_60_l ), 10983 mkU8( 28 ) ), 10984 mkexpr( low_60_u ) ), 10985 mkexpr( low_60_l ) ) ); 10986 10987 } else { 10988 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 10989 * the positive and negative values are encoded in the least 10990 * significant bits. 10991 */ 10992 IRTemp sign = newTemp( Ity_I32 ); 10993 10994 if ( sp == 2 ) { 10995 /* Positive sign = 0xC, negative sign = 0xD */ 10996 assign( sign, 10997 binop( Iop_Or32, 10998 binop( Iop_Shr32, 10999 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 11000 mkU8( 31 ) ), 11001 mkU32( 0xC ) ) ); 11002 11003 } else if ( sp == 3 ) { 11004 IRTemp tmp32 = newTemp( Ity_I32 ); 11005 11006 /* Positive sign = 0xF, negative sign = 0xD. 11007 * Need to complement sign bit then OR into bit position 1. 11008 */ 11009 assign( tmp32, 11010 binop( Iop_Xor32, 11011 binop( Iop_Shr32, 11012 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 11013 mkU8( 30 ) ), 11014 mkU32( 0x2 ) ) ); 11015 11016 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 11017 11018 } else { 11019 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 11020 } 11021 11022 assign( result_hi, 11023 binop( Iop_32HLto64, 11024 binop( Iop_Or32, 11025 binop( Iop_Shl32, 11026 mkexpr( top_12_l ), 11027 mkU8( 28 ) ), 11028 mkexpr( mid_60_u ) ), 11029 mkexpr( mid_60_l ) ) ); 11030 11031 assign( result_lo, 11032 binop( Iop_32HLto64, 11033 binop( Iop_Or32, 11034 binop( Iop_Shl32, 11035 mkexpr( low_60_u ), 11036 mkU8( 4 ) ), 11037 binop( Iop_Shr32, 11038 mkexpr( low_60_l ), 11039 mkU8( 28 ) ) ), 11040 binop( Iop_Or32, 11041 binop( Iop_Shl32, 11042 mkexpr( low_60_l ), 11043 mkU8( 4 ) ), 11044 mkexpr( sign ) ) ) ); 11045 } 11046 11047 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 11048 putDReg( frT_addr + 1, 11049 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 11050 } 11051 break; 11052 case 0x342: // denbcdq DFP Encode BCD to DPD 11053 { 11054 IRTemp valid_mask = newTemp( Ity_I32 ); 11055 IRTemp invalid_mask = newTemp( Ity_I32 ); 11056 IRTemp result128 = newTemp( Ity_D128 ); 11057 IRTemp dfp_significand = newTemp( Ity_D128 ); 11058 IRTemp tmp_hi = newTemp( Ity_I64 ); 11059 IRTemp tmp_lo = newTemp( Ity_I64 ); 11060 IRTemp dbcd_top_l = newTemp( Ity_I32 ); 11061 IRTemp dbcd_mid_u = newTemp( Ity_I32 ); 11062 IRTemp dbcd_mid_l = newTemp( Ity_I32 ); 11063 IRTemp dbcd_low_u = newTemp( Ity_I32 ); 11064 IRTemp dbcd_low_l = newTemp( Ity_I32 ); 11065 IRTemp bcd_top_8 = newTemp( Ity_I64 ); 11066 IRTemp bcd_mid_60 = newTemp( Ity_I64 ); 11067 IRTemp bcd_low_60 = newTemp( Ity_I64 ); 11068 IRTemp sign_bit = newTemp( Ity_I32 ); 11069 IRTemp tmptop10 = newTemp( Ity_I64 ); 11070 IRTemp tmpmid50 = newTemp( Ity_I64 ); 11071 IRTemp tmplow50 = newTemp( Ity_I64 ); 11072 IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 ); 11073 11074 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 11075 11076 if ( s == 0 ) { 11077 /* Unsigned BCD string */ 11078 assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string 11079 11080 assign( bcd_top_8, 11081 binop( Iop_32HLto64, 11082 mkU32( 0 ), 11083 binop( Iop_And32, 11084 binop( Iop_Shr32, 11085 unop( Iop_64HIto32, 11086 mkexpr( frBI64_hi ) ), 11087 mkU8( 24 ) ), 11088 mkU32( 0xFF ) ) ) ); 11089 assign( bcd_mid_60, 11090 binop( Iop_32HLto64, 11091 binop( Iop_Or32, 11092 binop( Iop_Shr32, 11093 unop( Iop_64to32, 11094 mkexpr( frBI64_hi ) ), 11095 mkU8( 28 ) ), 11096 binop( Iop_Shl32, 11097 unop( Iop_64HIto32, 11098 mkexpr( frBI64_hi ) ), 11099 mkU8( 4 ) ) ), 11100 binop( Iop_Or32, 11101 binop( Iop_Shl32, 11102 unop( Iop_64to32, 11103 mkexpr( frBI64_hi ) ), 11104 mkU8( 4 ) ), 11105 binop( Iop_Shr32, 11106 unop( Iop_64HIto32, 11107 mkexpr( frBI64_lo ) ), 11108 mkU8( 28 ) ) ) ) ); 11109 11110 /* Note, the various helper functions ignores top 4-bits */ 11111 assign( bcd_low_60, mkexpr( frBI64_lo ) ); 11112 11113 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) ); 11114 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 11115 11116 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) ); 11117 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 11118 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 11119 11120 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 11121 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 11122 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 11123 11124 /* The entire BCD string fits in lower 110-bits. The LMD = 0, 11125 * value is not part of the final result. Only the right most 11126 * BCD digits are stored. 11127 */ 11128 assign( lmd, mkU32( 0 ) ); 11129 11130 assign( invalid_mask, 11131 binop( Iop_Or32, 11132 bcd_digit_inval( mkU32( 0 ), 11133 unop( Iop_64to32, 11134 mkexpr( bcd_top_8 ) ) ), 11135 binop( Iop_Or32, 11136 bcd_digit_inval( unop( Iop_64HIto32, 11137 mkexpr( bcd_mid_60 ) ), 11138 unop( Iop_64to32, 11139 mkexpr( bcd_mid_60 ) ) ), 11140 bcd_digit_inval( unop( Iop_64HIto32, 11141 mkexpr( bcd_low_60 ) ), 11142 unop( Iop_64to32, 11143 mkexpr( bcd_low_60 ) ) 11144 ) ) ) ); 11145 11146 } else if ( s == 1 ) { 11147 IRTemp sign = newTemp( Ity_I32 ); 11148 IRTemp zero = newTemp( Ity_I32 ); 11149 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 11150 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 11151 11152 /* The sign of the BCD string is stored in lower 4 bits */ 11153 assign( sign, 11154 binop( Iop_And32, 11155 unop( Iop_64to32, mkexpr( frBI64_lo ) ), 11156 mkU32( 0xF ) ) ); 11157 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 11158 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 11159 assign( sign_bit, 11160 Generate_sign_bit( mkexpr( pos_sign_mask ), 11161 mkexpr( neg_sign_mask ) ) ); 11162 11163 /* Generate the value assuminig the sign and BCD digits are vaild */ 11164 assign( bcd_top_8, 11165 binop( Iop_32HLto64, 11166 mkU32( 0x0 ), 11167 binop( Iop_Shr32, 11168 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 11169 mkU8( 28 ) ) ) ); 11170 11171 /* The various helper routines ignore the upper 4-bits */ 11172 assign( bcd_mid_60, mkexpr( frBI64_hi ) ); 11173 11174 /* Remove bottom four sign bits */ 11175 assign( bcd_low_60, 11176 binop( Iop_32HLto64, 11177 binop( Iop_Shr32, 11178 unop( Iop_64HIto32, 11179 mkexpr( frBI64_lo ) ), 11180 mkU8( 4 ) ), 11181 binop( Iop_Or32, 11182 binop( Iop_Shl32, 11183 unop( Iop_64HIto32, 11184 mkexpr( frBI64_lo ) ), 11185 mkU8( 28 ) ), 11186 binop( Iop_Shr32, 11187 unop( Iop_64to32, 11188 mkexpr( frBI64_lo ) ), 11189 mkU8( 4 ) ) ) ) ); 11190 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) ); 11191 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 11192 11193 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) ); 11194 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 11195 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 11196 11197 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 11198 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 11199 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 11200 11201 /* The entire BCD string fits in lower 110-bits. The LMD value 11202 * is not stored in the final result for the DFP Long instruction. 11203 */ 11204 assign( lmd, mkU32( 0 ) ); 11205 11206 /* Check for invalid sign and invalid BCD digit. Don't check the 11207 * bottom four bits of frBI64_lo as that is the sign value. 11208 */ 11209 assign( zero, mkU32( 0 ) ); 11210 assign( inval_bcd_digit_mask, 11211 binop( Iop_Or32, 11212 bcd_digit_inval( mkexpr( zero ), 11213 unop( Iop_64to32, 11214 mkexpr( bcd_top_8 ) ) ), 11215 binop( Iop_Or32, 11216 bcd_digit_inval( unop( Iop_64HIto32, 11217 mkexpr( bcd_mid_60 ) ), 11218 unop( Iop_64to32, 11219 mkexpr( bcd_mid_60 ) ) ), 11220 bcd_digit_inval( unop( Iop_64HIto32, 11221 mkexpr( frBI64_lo ) ), 11222 binop( Iop_Shr32, 11223 unop( Iop_64to32, 11224 mkexpr( frBI64_lo ) ), 11225 mkU8( 4 ) ) ) ) ) ); 11226 assign( invalid_mask, 11227 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ), 11228 mkexpr( pos_sign_mask ), 11229 mkexpr( neg_sign_mask ) ) ); 11230 11231 } 11232 11233 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 11234 11235 /* Calculate the value of the result assuming sign and BCD digits 11236 * are all valid. 11237 */ 11238 assign( dfp_significand, 11239 binop( Iop_D64HLtoD128, 11240 unop( Iop_ReinterpI64asD64, 11241 binop( Iop_32HLto64, 11242 binop( Iop_Or32, 11243 mkexpr( sign_bit ), 11244 mkexpr( dbcd_top_l ) ), 11245 binop( Iop_Or32, 11246 binop( Iop_Shl32, 11247 mkexpr( dbcd_mid_u ), 11248 mkU8( 18 ) ), 11249 binop( Iop_Shr32, 11250 mkexpr( dbcd_mid_l ), 11251 mkU8( 14 ) ) ) ) ), 11252 unop( Iop_ReinterpI64asD64, 11253 binop( Iop_32HLto64, 11254 binop( Iop_Or32, 11255 mkexpr( dbcd_low_u ), 11256 binop( Iop_Shl32, 11257 mkexpr( dbcd_mid_l ), 11258 mkU8( 18 ) ) ), 11259 mkexpr( dbcd_low_l ) ) ) ) ); 11260 11261 /* Break the result back down to 32-bit chunks and replace chunks. 11262 * If there was an invalid BCD digit or invalid sign value, replace 11263 * the calculated result with the invalid bit string. 11264 */ 11265 assign( result128, 11266 binop( Iop_InsertExpD128, 11267 unop( Iop_ReinterpI64asD64, mkU64( DFP_EXTND_BIAS ) ), 11268 mkexpr( dfp_significand ) ) ); 11269 11270 assign( tmp_hi, 11271 unop( Iop_ReinterpD64asI64, 11272 unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) ); 11273 11274 assign( tmp_lo, 11275 unop( Iop_ReinterpD64asI64, 11276 unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) ); 11277 11278 assign( result_hi, 11279 binop( Iop_32HLto64, 11280 binop( Iop_Or32, 11281 binop( Iop_And32, 11282 mkexpr( valid_mask ), 11283 unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ), 11284 binop( Iop_And32, 11285 mkU32( 0x7C000000 ), 11286 mkexpr( invalid_mask ) ) ), 11287 binop( Iop_Or32, 11288 binop( Iop_And32, 11289 mkexpr( valid_mask ), 11290 unop( Iop_64to32, mkexpr( tmp_hi ) ) ), 11291 binop( Iop_And32, 11292 mkU32( 0x0 ), 11293 mkexpr( invalid_mask ) ) ) ) ); 11294 11295 assign( result_lo, 11296 binop( Iop_32HLto64, 11297 binop( Iop_Or32, 11298 binop( Iop_And32, 11299 mkexpr( valid_mask ), 11300 unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ), 11301 binop( Iop_And32, 11302 mkU32( 0x0 ), 11303 mkexpr( invalid_mask ) ) ), 11304 binop( Iop_Or32, 11305 binop( Iop_And32, 11306 mkexpr( valid_mask ), 11307 unop( Iop_64to32, mkexpr( tmp_lo ) ) ), 11308 binop( Iop_And32, 11309 mkU32( 0x0 ), 11310 mkexpr( invalid_mask ) ) ) ) ); 11311 11312 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 11313 putDReg( frT_addr + 1, 11314 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 11315 11316 } 11317 break; 11318 default: 11319 vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " ); 11320 break; 11321 } 11322 return True; 11323 } 11324 11325 static Bool dis_dfp_significant_digits( UInt theInstr ) 11326 { 11327 UChar frA_addr = ifieldRegA( theInstr ); 11328 UChar frB_addr = ifieldRegB( theInstr ); 11329 IRTemp frA = newTemp( Ity_D64 ); 11330 UInt opc1 = ifieldOPC( theInstr ); 11331 IRTemp B_sig = newTemp( Ity_I8 ); 11332 IRTemp K = newTemp( Ity_I8 ); 11333 IRTemp lmd_B = newTemp( Ity_I32 ); 11334 IRTemp field = newTemp( Ity_I32 ); 11335 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 11336 IRTemp Unordered_true = newTemp( Ity_I32 ); 11337 IRTemp Eq_true_mask = newTemp( Ity_I32 ); 11338 IRTemp Lt_true_mask = newTemp( Ity_I32 ); 11339 IRTemp Gt_true_mask = newTemp( Ity_I32 ); 11340 IRTemp KisZero_true_mask = newTemp( Ity_I32 ); 11341 IRTemp KisZero_false_mask = newTemp( Ity_I32 ); 11342 11343 /* Get the reference singificance stored in frA */ 11344 assign( frA, getDReg( frA_addr ) ); 11345 11346 /* Convert from 64 bit to 8 bits in two steps. The Iop_64to8 is not 11347 * supported in 32-bit mode. 11348 */ 11349 assign( K, unop( Iop_32to8, 11350 binop( Iop_And32, 11351 unop( Iop_64to32, 11352 unop( Iop_ReinterpD64asI64, 11353 mkexpr( frA ) ) ), 11354 mkU32( 0x3F ) ) ) ); 11355 11356 switch ( opc1 ) { 11357 case 0x3b: // dtstsf DFP Test Significance 11358 { 11359 IRTemp frB = newTemp( Ity_D64 ); 11360 IRTemp frBI64 = newTemp( Ity_I64 ); 11361 IRTemp B_bcd_u = newTemp( Ity_I32 ); 11362 IRTemp B_bcd_l = newTemp( Ity_I32 ); 11363 IRTemp tmp64 = newTemp( Ity_I64 ); 11364 11365 DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 11366 11367 assign( frB, getDReg( frB_addr ) ); 11368 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 11369 11370 /* Get the BCD string for the value stored in a series of I32 values. 11371 * Count the number of leading zeros. Subtract the number of leading 11372 * zeros from 16 (maximum number of significant digits in DFP 11373 * Long). 11374 */ 11375 Get_lmd( &lmd_B, 11376 binop( Iop_Shr32, 11377 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11378 mkU8( 31 - 5 ) ) ); // G-field[0:4] 11379 11380 assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 11381 assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) ); 11382 assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) ); 11383 11384 assign( B_sig, 11385 binop( Iop_Sub8, 11386 mkU8( DFP_LONG_MAX_SIG_DIGITS ), 11387 Count_leading_zeros_60( mkexpr( lmd_B ), 11388 mkexpr( B_bcd_u ), 11389 mkexpr( B_bcd_l ) ) ) ); 11390 assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) ); 11391 } 11392 break; 11393 case 0x3F: // dtstsfq DFP Test Significance 11394 { 11395 IRTemp frB_hi = newTemp( Ity_D64 ); 11396 IRTemp frB_lo = newTemp( Ity_D64 ); 11397 IRTemp frBI64_hi = newTemp( Ity_I64 ); 11398 IRTemp frBI64_lo = newTemp( Ity_I64 ); 11399 IRTemp B_low_60_u = newTemp( Ity_I32 ); 11400 IRTemp B_low_60_l = newTemp( Ity_I32 ); 11401 IRTemp B_mid_60_u = newTemp( Ity_I32 ); 11402 IRTemp B_mid_60_l = newTemp( Ity_I32 ); 11403 IRTemp B_top_12_l = newTemp( Ity_I32 ); 11404 11405 DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 11406 11407 assign( frB_hi, getDReg( frB_addr ) ); 11408 assign( frB_lo, getDReg( frB_addr + 1 ) ); 11409 11410 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 11411 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 11412 11413 /* Get the BCD string for the value stored in a series of I32 values. 11414 * Count the number of leading zeros. Subtract the number of leading 11415 * zeros from 32 (maximum number of significant digits in DFP 11416 * extended). 11417 */ 11418 Get_lmd( &lmd_B, 11419 binop( Iop_Shr32, 11420 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 11421 mkU8( 31 - 5 ) ) ); // G-field[0:4] 11422 11423 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 11424 mkexpr( frBI64_lo ), 11425 &B_top_12_l, 11426 &B_mid_60_u, 11427 &B_mid_60_l, 11428 &B_low_60_u, 11429 &B_low_60_l ); 11430 11431 assign( B_sig, 11432 binop( Iop_Sub8, 11433 mkU8( DFP_EXTND_MAX_SIG_DIGITS ), 11434 Count_leading_zeros_128( mkexpr( lmd_B ), 11435 mkexpr( B_top_12_l ), 11436 mkexpr( B_mid_60_u ), 11437 mkexpr( B_mid_60_l ), 11438 mkexpr( B_low_60_u ), 11439 mkexpr( B_low_60_l ) ) ) ); 11440 11441 assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) ); 11442 } 11443 break; 11444 } 11445 11446 /* Compare (16 - cnt[0]) against K and set the condition code field 11447 * accordingly. 11448 * 11449 * The field layout is as follows: 11450 * 11451 * bit[3:0] Description 11452 * 3 K != 0 and K < Number of significant digits if FRB 11453 * 2 K != 0 and K > Number of significant digits if FRB OR K = 0 11454 * 1 K != 0 and K = Number of significant digits if FRB 11455 * 0 K ? Number of significant digits if FRB 11456 */ 11457 assign( Eq_true_mask, 11458 unop( Iop_1Sto32, 11459 binop( Iop_CmpEQ32, 11460 unop( Iop_8Uto32, mkexpr( K ) ), 11461 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 11462 assign( Lt_true_mask, 11463 unop( Iop_1Sto32, 11464 binop( Iop_CmpLT32U, 11465 unop( Iop_8Uto32, mkexpr( K ) ), 11466 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 11467 assign( Gt_true_mask, 11468 unop( Iop_1Sto32, 11469 binop( Iop_CmpLT32U, 11470 unop( Iop_8Uto32, mkexpr( B_sig ) ), 11471 unop( Iop_8Uto32, mkexpr( K ) ) ) ) ); 11472 11473 assign( KisZero_true_mask, 11474 unop( Iop_1Sto32, 11475 binop( Iop_CmpEQ32, 11476 unop( Iop_8Uto32, mkexpr( K ) ), 11477 mkU32( 0 ) ) ) ); 11478 assign( KisZero_false_mask, 11479 unop( Iop_1Sto32, 11480 binop( Iop_CmpNE32, 11481 unop( Iop_8Uto32, mkexpr( K ) ), 11482 mkU32( 0 ) ) ) ); 11483 11484 assign( field, 11485 binop( Iop_Or32, 11486 binop( Iop_And32, 11487 mkexpr( KisZero_false_mask ), 11488 binop( Iop_Or32, 11489 binop( Iop_And32, 11490 mkexpr( Lt_true_mask ), 11491 mkU32( 0x8 ) ), 11492 binop( Iop_Or32, 11493 binop( Iop_And32, 11494 mkexpr( Gt_true_mask ), 11495 mkU32( 0x4 ) ), 11496 binop( Iop_And32, 11497 mkexpr( Eq_true_mask ), 11498 mkU32( 0x2 ) ) ) ) ), 11499 binop( Iop_And32, 11500 mkexpr( KisZero_true_mask ), 11501 mkU32( 0x4 ) ) ) ); 11502 11503 putGST_field( PPC_GST_CR, 11504 binop( Iop_Or32, 11505 binop( Iop_And32, 11506 mkexpr( Unordered_true ), 11507 mkU32( 0x1 ) ), 11508 binop( Iop_And32, 11509 unop( Iop_Not32, mkexpr( Unordered_true ) ), 11510 mkexpr( field ) ) ), 11511 crfD ); 11512 11513 return True; 11514 } 11515 11516 /*------------------------------------------------------------*/ 11517 /*--- AltiVec Instruction Translation ---*/ 11518 /*------------------------------------------------------------*/ 11519 11520 /* 11521 Altivec Cache Control Instructions (Data Streams) 11522 */ 11523 static Bool dis_av_datastream ( UInt theInstr ) 11524 { 11525 /* X-Form */ 11526 UChar opc1 = ifieldOPC(theInstr); 11527 UChar flag_T = toUChar( IFIELD( theInstr, 25, 1 ) ); 11528 UChar flag_A = flag_T; 11529 UChar b23to24 = toUChar( IFIELD( theInstr, 23, 2 ) ); 11530 UChar STRM = toUChar( IFIELD( theInstr, 21, 2 ) ); 11531 UChar rA_addr = ifieldRegA(theInstr); 11532 UChar rB_addr = ifieldRegB(theInstr); 11533 UInt opc2 = ifieldOPClo10(theInstr); 11534 UChar b0 = ifieldBIT0(theInstr); 11535 11536 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) { 11537 vex_printf("dis_av_datastream(ppc)(instr)\n"); 11538 return False; 11539 } 11540 11541 switch (opc2) { 11542 case 0x156: // dst (Data Stream Touch, AV p115) 11543 DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "", 11544 rA_addr, rB_addr, STRM); 11545 break; 11546 11547 case 0x176: // dstst (Data Stream Touch for Store, AV p117) 11548 DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "", 11549 rA_addr, rB_addr, STRM); 11550 break; 11551 11552 case 0x336: // dss (Data Stream Stop, AV p114) 11553 if (rA_addr != 0 || rB_addr != 0) { 11554 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n"); 11555 return False; 11556 } 11557 if (flag_A == 0) { 11558 DIP("dss %d\n", STRM); 11559 } else { 11560 DIP("dssall\n"); 11561 } 11562 break; 11563 11564 default: 11565 vex_printf("dis_av_datastream(ppc)(opc2)\n"); 11566 return False; 11567 } 11568 return True; 11569 } 11570 11571 /* 11572 AltiVec Processor Control Instructions 11573 */ 11574 static Bool dis_av_procctl ( UInt theInstr ) 11575 { 11576 /* VX-Form */ 11577 UChar opc1 = ifieldOPC(theInstr); 11578 UChar vD_addr = ifieldRegDS(theInstr); 11579 UChar vA_addr = ifieldRegA(theInstr); 11580 UChar vB_addr = ifieldRegB(theInstr); 11581 UInt opc2 = IFIELD( theInstr, 0, 11 ); 11582 11583 if (opc1 != 0x4) { 11584 vex_printf("dis_av_procctl(ppc)(instr)\n"); 11585 return False; 11586 } 11587 11588 switch (opc2) { 11589 case 0x604: // mfvscr (Move from VSCR, AV p129) 11590 if (vA_addr != 0 || vB_addr != 0) { 11591 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 11592 return False; 11593 } 11594 DIP("mfvscr v%d\n", vD_addr); 11595 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) ); 11596 break; 11597 11598 case 0x644: { // mtvscr (Move to VSCR, AV p130) 11599 IRTemp vB = newTemp(Ity_V128); 11600 if (vD_addr != 0 || vA_addr != 0) { 11601 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 11602 return False; 11603 } 11604 DIP("mtvscr v%d\n", vB_addr); 11605 assign( vB, getVReg(vB_addr)); 11606 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) ); 11607 break; 11608 } 11609 default: 11610 vex_printf("dis_av_procctl(ppc)(opc2)\n"); 11611 return False; 11612 } 11613 return True; 11614 } 11615 11616 /* 11617 * VSX scalar and vector convert instructions 11618 */ 11619 static Bool 11620 dis_vx_conv ( UInt theInstr, UInt opc2 ) 11621 { 11622 /* XX2-Form */ 11623 UChar opc1 = ifieldOPC( theInstr ); 11624 UChar XT = ifieldRegXT( theInstr ); 11625 UChar XB = ifieldRegXB( theInstr ); 11626 IRTemp xB, xB2; 11627 IRTemp b3, b2, b1, b0; 11628 xB = xB2 = IRTemp_INVALID; 11629 11630 if (opc1 != 0x3C) { 11631 vex_printf( "dis_vx_conv(ppc)(instr)\n" ); 11632 return False; 11633 } 11634 11635 /* Create and assign temps only as needed for the given instruction. */ 11636 switch (opc2) { 11637 // scalar double-precision floating point argument 11638 case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x090: 11639 xB = newTemp(Ity_F64); 11640 assign( xB, 11641 unop( Iop_ReinterpI64asF64, 11642 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 11643 break; 11644 // vector double-precision floating point arguments 11645 case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0: 11646 11647 xB = newTemp(Ity_F64); 11648 xB2 = newTemp(Ity_F64); 11649 assign( xB, 11650 unop( Iop_ReinterpI64asF64, 11651 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 11652 assign( xB2, 11653 unop( Iop_ReinterpI64asF64, 11654 unop( Iop_V128to64, getVSReg( XB ) ) ) ); 11655 break; 11656 // vector single precision or [un]signed integer word arguments 11657 case 0x130: case 0x392: case 0x330: case 0x310: case 0x110: 11658 case 0x1f0: case 0x1d0: 11659 b3 = b2 = b1 = b0 = IRTemp_INVALID; 11660 breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0); 11661 break; 11662 // vector [un]signed integer doubleword argument 11663 case 0x3f0: case 0x370: case 0x3d0: case 0x350: 11664 xB = newTemp(Ity_I64); 11665 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 11666 xB2 = newTemp(Ity_I64); 11667 assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) ); 11668 break; 11669 // scalar [un]signed integer doubleword argument 11670 case 0x2F0: case 0x2D0: 11671 xB = newTemp(Ity_I64); 11672 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 11673 break; 11674 // scalar single precision argument 11675 case 0x292: // xscvspdp 11676 xB = newTemp(Ity_I32); 11677 assign( xB, 11678 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 11679 break; 11680 11681 /* Certain instructions have their complete implementation in the main switch statement 11682 * that follows this one; thus we have a "do nothing" case for those instructions here. 11683 */ 11684 case 0x170: case 0x150: 11685 break; // do nothing 11686 11687 default: 11688 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 11689 return False; 11690 } 11691 11692 11693 switch (opc2) { 11694 case 0x2B0: 11695 // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert 11696 // to Signed Integer Doubleword format with Saturate) 11697 DIP("xscvdpsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 11698 putVSReg( XT, 11699 binop( Iop_64HLtoV128, binop( Iop_F64toI64S, 11700 mkU32( Irrm_ZERO ), 11701 mkexpr( xB ) ), mkU64( 0 ) ) ); 11702 break; 11703 case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and 11704 // Convert to Signed Integer Word format with Saturate) 11705 DIP("xscvdpsxws v%u,v%u\n", (UInt)XT, (UInt)XB); 11706 putVSReg( XT, 11707 binop( Iop_64HLtoV128, 11708 unop( Iop_32Sto64, 11709 binop( Iop_F64toI32S, 11710 mkU32( Irrm_ZERO ), 11711 mkexpr( xB ) ) ), 11712 mkU64( 0ULL ) ) ); 11713 break; 11714 case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert 11715 // to Unsigned Integer Doubleword format with Saturate) 11716 DIP("xscvdpuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 11717 putVSReg( XT, 11718 binop( Iop_64HLtoV128, 11719 binop( Iop_F64toI64U, 11720 mkU32( Irrm_ZERO ), 11721 mkexpr( xB ) ), 11722 mkU64( 0ULL ) ) ); 11723 break; 11724 case 0x2F0: 11725 // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to 11726 // Double-Precision format) 11727 DIP("xscvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 11728 putVSReg( XT, 11729 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 11730 binop( Iop_I64StoF64, get_IR_roundingmode(), 11731 mkexpr( xB ) ) ), 11732 mkU64( 0 ) ) ); 11733 break; 11734 case 0x2D0: 11735 // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to 11736 // Double-Precision format) 11737 DIP("xscvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 11738 putVSReg( XT, 11739 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 11740 binop( Iop_I64UtoF64, get_IR_roundingmode(), 11741 mkexpr( xB ) ) ), 11742 mkU64( 0 ) ) ); 11743 break; 11744 case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert 11745 // to Signed Integer Word format with Saturate) 11746 { 11747 IRTemp hiResult_32 = newTemp(Ity_I32); 11748 IRTemp loResult_32 = newTemp(Ity_I32); 11749 IRExpr* rmZero = mkU32(Irrm_ZERO); 11750 11751 DIP("xvcvdpsxws v%u,v%u\n", (UInt)XT, (UInt)XB); 11752 assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB))); 11753 assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2))); 11754 putVSReg( XT, 11755 binop( Iop_64HLtoV128, 11756 unop( Iop_32Sto64, mkexpr( hiResult_32 ) ), 11757 unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) ); 11758 break; 11759 } 11760 case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws 11761 // (VSX Vector truncate Single-Precision to integer and 11762 // Convert to [Un]signed Integer Word format with Saturate) 11763 { 11764 IRExpr * b0_result, * b1_result, * b2_result, * b3_result; 11765 IRTemp tempResult = newTemp(Ity_V128); 11766 IRTemp res0 = newTemp(Ity_I32); 11767 IRTemp res1 = newTemp(Ity_I32); 11768 IRTemp res2 = newTemp(Ity_I32); 11769 IRTemp res3 = newTemp(Ity_I32); 11770 IRTemp hi64 = newTemp(Ity_I64); 11771 IRTemp lo64 = newTemp(Ity_I64); 11772 Bool un_signed = (opc2 == 0x110); 11773 IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ; 11774 11775 DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB); 11776 /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN, 11777 * then result is set to 0x80000000. */ 11778 assign(tempResult, unop(op, getVSReg(XB))); 11779 assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) ); 11780 assign( lo64, unop(Iop_V128to64, mkexpr(tempResult)) ); 11781 assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) ); 11782 assign( res2, unop(Iop_64to32, mkexpr(hi64)) ); 11783 assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) ); 11784 assign( res0, unop(Iop_64to32, mkexpr(lo64)) ); 11785 11786 b3_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b3)), 11787 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 11788 mkexpr(res3), 11789 // then: result is 0x{8|0}80000000 11790 mkU32(un_signed ? 0x00000000 : 0x80000000)); 11791 b2_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b2)), 11792 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 11793 mkexpr(res2), 11794 // then: result is 0x{8|0}80000000 11795 mkU32(un_signed ? 0x00000000 : 0x80000000)); 11796 b1_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b1)), 11797 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 11798 mkexpr(res1), 11799 // then: result is 0x{8|0}80000000 11800 mkU32(un_signed ? 0x00000000 : 0x80000000)); 11801 b0_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b0)), 11802 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 11803 mkexpr(res0), 11804 // then: result is 0x{8|0}80000000 11805 mkU32(un_signed ? 0x00000000 : 0x80000000)); 11806 11807 putVSReg( XT, 11808 binop( Iop_64HLtoV128, 11809 binop( Iop_32HLto64, b3_result, b2_result ), 11810 binop( Iop_32HLto64, b1_result, b0_result ) ) ); 11811 break; 11812 } 11813 case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and 11814 // Convert to Single-Precision format 11815 DIP("xscvdpsp v%u,v%u\n", (UInt)XT, (UInt)XB); 11816 putVSReg( XT, 11817 binop( Iop_64HLtoV128, 11818 binop( Iop_32HLto64, 11819 unop( Iop_ReinterpF32asI32, 11820 unop( Iop_TruncF64asF32, 11821 binop( Iop_RoundF64toF32, 11822 get_IR_roundingmode(), 11823 mkexpr( xB ) ) ) ), 11824 mkU32( 0 ) ), 11825 mkU64( 0ULL ) ) ); 11826 break; 11827 case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer 11828 // and Convert to Unsigned Integer Word format with Saturate) 11829 DIP("xscvdpuxws v%u,v%u\n", (UInt)XT, (UInt)XB); 11830 putVSReg( XT, 11831 binop( Iop_64HLtoV128, 11832 binop( Iop_32HLto64, 11833 mkU32( 0 ), 11834 binop( Iop_F64toI32U, 11835 mkU32( Irrm_ZERO ), 11836 mkexpr( xB ) ) ), 11837 mkU64( 0ULL ) ) ); 11838 break; 11839 case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format) 11840 DIP("xscvspdp v%u,v%u\n", (UInt)XT, (UInt)XB); 11841 putVSReg( XT, 11842 binop( Iop_64HLtoV128, 11843 unop( Iop_ReinterpF64asI64, 11844 unop( Iop_F32toF64, 11845 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 11846 mkU64( 0ULL ) ) ); 11847 break; 11848 case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision 11849 // and Convert to Single-Precision format) 11850 DIP("xvcvdpsp v%u,v%u\n", (UInt)XT, (UInt)XB); 11851 putVSReg( XT, 11852 binop( Iop_64HLtoV128, 11853 binop( Iop_32HLto64, 11854 unop( Iop_ReinterpF32asI32, 11855 unop( Iop_TruncF64asF32, 11856 binop( Iop_RoundF64toF32, 11857 get_IR_roundingmode(), 11858 mkexpr( xB ) ) ) ), 11859 mkU32( 0 ) ), 11860 binop( Iop_32HLto64, 11861 unop( Iop_ReinterpF32asI32, 11862 unop( Iop_TruncF64asF32, 11863 binop( Iop_RoundF64toF32, 11864 get_IR_roundingmode(), 11865 mkexpr( xB2 ) ) ) ), 11866 mkU32( 0 ) ) ) ); 11867 break; 11868 case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer 11869 // and Convert to Unsigned Integer Doubleword format 11870 // with Saturate) 11871 DIP("xvcvdpuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 11872 putVSReg( XT, 11873 binop( Iop_64HLtoV128, 11874 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 11875 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 11876 break; 11877 case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and 11878 // Convert to Unsigned Integer Word format with Saturate) 11879 DIP("xvcvdpuxws v%u,v%u\n", (UInt)XT, (UInt)XB); 11880 putVSReg( XT, 11881 binop( Iop_64HLtoV128, 11882 binop( Iop_32HLto64, 11883 binop( Iop_F64toI32U, 11884 mkU32( Irrm_ZERO ), 11885 mkexpr( xB ) ), 11886 mkU32( 0 ) ), 11887 binop( Iop_32HLto64, 11888 binop( Iop_F64toI32U, 11889 mkU32( Irrm_ZERO ), 11890 mkexpr( xB2 ) ), 11891 mkU32( 0 ) ) ) ); 11892 break; 11893 case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format) 11894 DIP("xvcvspdp v%u,v%u\n", (UInt)XT, (UInt)XB); 11895 putVSReg( XT, 11896 binop( Iop_64HLtoV128, 11897 unop( Iop_ReinterpF64asI64, 11898 unop( Iop_F32toF64, 11899 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 11900 unop( Iop_ReinterpF64asI64, 11901 unop( Iop_F32toF64, 11902 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 11903 break; 11904 case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and 11905 // Convert to Signed Integer Doubleword format with Saturate) 11906 DIP("xvcvspsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 11907 putVSReg( XT, 11908 binop( Iop_64HLtoV128, 11909 binop( Iop_F64toI64S, 11910 mkU32( Irrm_ZERO ), 11911 unop( Iop_F32toF64, 11912 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 11913 binop( Iop_F64toI64S, 11914 mkU32( Irrm_ZERO ), 11915 unop( Iop_F32toF64, 11916 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 11917 break; 11918 case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and 11919 // Convert to Unsigned Integer Doubleword format with Saturate) 11920 DIP("xvcvspuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 11921 putVSReg( XT, 11922 binop( Iop_64HLtoV128, 11923 binop( Iop_F64toI64U, 11924 mkU32( Irrm_ZERO ), 11925 unop( Iop_F32toF64, 11926 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 11927 binop( Iop_F64toI64U, 11928 mkU32( Irrm_ZERO ), 11929 unop( Iop_F32toF64, 11930 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 11931 break; 11932 case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and 11933 // Convert to Signed Integer Doubleword format with Saturate) 11934 DIP("xvcvdpsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 11935 putVSReg( XT, 11936 binop( Iop_64HLtoV128, 11937 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 11938 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 11939 break; 11940 case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword 11941 // to Double-Precision format) 11942 DIP("xvcvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 11943 putVSReg( XT, 11944 binop( Iop_64HLtoV128, 11945 unop( Iop_ReinterpF64asI64, 11946 binop( Iop_I64StoF64, 11947 get_IR_roundingmode(), 11948 mkexpr( xB ) ) ), 11949 unop( Iop_ReinterpF64asI64, 11950 binop( Iop_I64StoF64, 11951 get_IR_roundingmode(), 11952 mkexpr( xB2 ) ) ) ) ); 11953 break; 11954 case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword 11955 // to Double-Precision format) 11956 DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 11957 putVSReg( XT, 11958 binop( Iop_64HLtoV128, 11959 unop( Iop_ReinterpF64asI64, 11960 binop( Iop_I64UtoF64, 11961 get_IR_roundingmode(), 11962 mkexpr( xB ) ) ), 11963 unop( Iop_ReinterpF64asI64, 11964 binop( Iop_I64UtoF64, 11965 get_IR_roundingmode(), 11966 mkexpr( xB2 ) ) ) ) ); 11967 11968 break; 11969 case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword 11970 // to Single-Precision format) 11971 DIP("xvcvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 11972 putVSReg( XT, 11973 binop( Iop_64HLtoV128, 11974 binop( Iop_32HLto64, 11975 unop( Iop_ReinterpF32asI32, 11976 unop( Iop_TruncF64asF32, 11977 binop( Iop_RoundF64toF32, 11978 get_IR_roundingmode(), 11979 binop( Iop_I64StoF64, 11980 get_IR_roundingmode(), 11981 mkexpr( xB ) ) ) ) ), 11982 mkU32( 0 ) ), 11983 binop( Iop_32HLto64, 11984 unop( Iop_ReinterpF32asI32, 11985 unop( Iop_TruncF64asF32, 11986 binop( Iop_RoundF64toF32, 11987 get_IR_roundingmode(), 11988 binop( Iop_I64StoF64, 11989 get_IR_roundingmode(), 11990 mkexpr( xB2 ) ) ) ) ), 11991 mkU32( 0 ) ) ) ); 11992 break; 11993 case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword 11994 // to Single-Precision format) 11995 DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 11996 putVSReg( XT, 11997 binop( Iop_64HLtoV128, 11998 binop( Iop_32HLto64, 11999 unop( Iop_ReinterpF32asI32, 12000 unop( Iop_TruncF64asF32, 12001 binop( Iop_RoundF64toF32, 12002 get_IR_roundingmode(), 12003 binop( Iop_I64UtoF64, 12004 get_IR_roundingmode(), 12005 mkexpr( xB ) ) ) ) ), 12006 mkU32( 0 ) ), 12007 binop( Iop_32HLto64, 12008 unop( Iop_ReinterpF32asI32, 12009 unop( Iop_TruncF64asF32, 12010 binop( Iop_RoundF64toF32, 12011 get_IR_roundingmode(), 12012 binop( Iop_I64UtoF64, 12013 get_IR_roundingmode(), 12014 mkexpr( xB2 ) ) ) ) ), 12015 mkU32( 0 ) ) ) ); 12016 break; 12017 12018 case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format) 12019 DIP("xvcvsxwdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12020 putVSReg( XT, 12021 binop( Iop_64HLtoV128, 12022 unop( Iop_ReinterpF64asI64, 12023 binop( Iop_I64StoF64, get_IR_roundingmode(), 12024 unop( Iop_32Sto64, mkexpr( b3 ) ) ) ), 12025 unop( Iop_ReinterpF64asI64, 12026 binop( Iop_I64StoF64, get_IR_roundingmode(), 12027 unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) ); 12028 break; 12029 case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format) 12030 DIP("xvcvuxwdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12031 putVSReg( XT, 12032 binop( Iop_64HLtoV128, 12033 unop( Iop_ReinterpF64asI64, 12034 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12035 unop( Iop_32Uto64, mkexpr( b3 ) ) ) ), 12036 unop( Iop_ReinterpF64asI64, 12037 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12038 unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) ); 12039 break; 12040 case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format) 12041 DIP("xvcvsxwsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12042 putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) ); 12043 break; 12044 case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format) 12045 DIP("xvcvuxwsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12046 putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) ); 12047 break; 12048 12049 default: 12050 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 12051 return False; 12052 } 12053 return True; 12054 } 12055 12056 /* 12057 * VSX vector Double Precision Floating Point Arithmetic Instructions 12058 */ 12059 static Bool 12060 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 ) 12061 { 12062 /* XX3-Form */ 12063 UChar opc1 = ifieldOPC( theInstr ); 12064 UChar XT = ifieldRegXT( theInstr ); 12065 UChar XA = ifieldRegXA( theInstr ); 12066 UChar XB = ifieldRegXB( theInstr ); 12067 IRExpr* rm = get_IR_roundingmode(); 12068 IRTemp frA = newTemp(Ity_F64); 12069 IRTemp frB = newTemp(Ity_F64); 12070 IRTemp frA2 = newTemp(Ity_F64); 12071 IRTemp frB2 = newTemp(Ity_F64); 12072 12073 if (opc1 != 0x3C) { 12074 vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" ); 12075 return False; 12076 } 12077 12078 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 12079 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 12080 assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA )))); 12081 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB )))); 12082 12083 switch (opc2) { 12084 case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision) 12085 case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision) 12086 case 0x180: // xvadddp (VSX Vector Add Double-Precision) 12087 case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision) 12088 { 12089 IROp mOp; 12090 Char * oper_name; 12091 switch (opc2) { 12092 case 0x1E0: 12093 mOp = Iop_DivF64; 12094 oper_name = "div"; 12095 break; 12096 case 0x1C0: 12097 mOp = Iop_MulF64; 12098 oper_name = "mul"; 12099 break; 12100 case 0x180: 12101 mOp = Iop_AddF64; 12102 oper_name = "add"; 12103 break; 12104 case 0x1A0: 12105 mOp = Iop_SubF64; 12106 oper_name = "sub"; 12107 break; 12108 12109 default: 12110 vpanic("The impossible happened: dis_vxv_dp_arith(ppc)"); 12111 } 12112 IRTemp hiResult = newTemp(Ity_I64); 12113 IRTemp loResult = newTemp(Ity_I64); 12114 DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB); 12115 12116 assign( hiResult, 12117 unop( Iop_ReinterpF64asI64, 12118 triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) ); 12119 assign( loResult, 12120 unop( Iop_ReinterpF64asI64, 12121 triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) ); 12122 putVSReg( XT, 12123 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 12124 break; 12125 } 12126 case 0x196: // xvsqrtdp 12127 { 12128 IRTemp hiResult = newTemp(Ity_I64); 12129 IRTemp loResult = newTemp(Ity_I64); 12130 DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 12131 12132 assign( hiResult, 12133 unop( Iop_ReinterpF64asI64, 12134 binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) ); 12135 assign( loResult, 12136 unop( Iop_ReinterpF64asI64, 12137 binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) ); 12138 putVSReg( XT, 12139 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 12140 break; 12141 } 12142 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision) 12143 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision) 12144 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision) 12145 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision) 12146 { 12147 /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . . 12148 * XT == FRC 12149 * XA == FRA 12150 * XB == FRB 12151 * 12152 * and for xvm{add|sub}adp . . . 12153 * XT == FRB 12154 * XA == FRA 12155 * XB == FRC 12156 */ 12157 Bool negate; 12158 IROp mOp = Iop_INVALID; 12159 Char * oper_name = NULL; 12160 Bool mdp = False; 12161 12162 switch (opc2) { 12163 case 0x184: case 0x1A4: 12164 case 0x384: case 0x3A4: 12165 mOp = Iop_MAddF64; 12166 oper_name = "add"; 12167 mdp = (opc2 & 0x0FF) == 0x0A4; 12168 break; 12169 12170 case 0x1C4: case 0x1E4: 12171 case 0x3C4: case 0x3E4: 12172 mOp = Iop_MSubF64; 12173 oper_name = "sub"; 12174 mdp = (opc2 & 0x0FF) == 0x0E4; 12175 break; 12176 12177 default: 12178 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 12179 } 12180 12181 switch (opc2) { 12182 case 0x384: case 0x3A4: 12183 case 0x3C4: case 0x3E4: 12184 negate = True; 12185 break; 12186 default: 12187 negate = False; 12188 } 12189 IRTemp hiResult = newTemp(Ity_I64); 12190 IRTemp loResult = newTemp(Ity_I64); 12191 IRTemp frT = newTemp(Ity_F64); 12192 IRTemp frT2 = newTemp(Ity_F64); 12193 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp", 12194 (UInt)XT, (UInt)XA, (UInt)XB); 12195 assign(frT, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) ); 12196 assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) ); 12197 12198 assign( hiResult, 12199 unop( Iop_ReinterpF64asI64, 12200 qop( mOp, 12201 rm, 12202 mkexpr( frA ), 12203 mkexpr( mdp ? frT : frB ), 12204 mkexpr( mdp ? frB : frT ) ) ) ); 12205 assign( loResult, 12206 unop( Iop_ReinterpF64asI64, 12207 qop( mOp, 12208 rm, 12209 mkexpr( frA2 ), 12210 mkexpr( mdp ? frT2 : frB2 ), 12211 mkexpr( mdp ? frB2 : frT2 ) ) ) ); 12212 putVSReg( XT, 12213 binop( Iop_64HLtoV128, 12214 mkexpr( negate ? getNegatedResult( hiResult ) 12215 : hiResult ), 12216 mkexpr( negate ? getNegatedResult( loResult ) 12217 : loResult ) ) ); 12218 break; 12219 } 12220 case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision) 12221 { 12222 IRTemp frBHi_I64 = newTemp(Ity_I64); 12223 IRTemp frBLo_I64 = newTemp(Ity_I64); 12224 IRTemp flagsHi = newTemp(Ity_I32); 12225 IRTemp flagsLo = newTemp(Ity_I32); 12226 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 12227 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 12228 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 12229 12230 DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB); 12231 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 12232 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 12233 do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi); 12234 do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo); 12235 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 12236 * where fl_flag == 1 on ppc64. 12237 */ 12238 assign( flagsHi, 12239 binop( Iop_Or32, 12240 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12241 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 12242 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 12243 assign( flagsLo, 12244 binop( Iop_Or32, 12245 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12246 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 12247 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 12248 putGST_field( PPC_GST_CR, 12249 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 12250 crfD ); 12251 break; 12252 } 12253 case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision) 12254 { 12255 IRTemp frBHi_I64 = newTemp(Ity_I64); 12256 IRTemp frBLo_I64 = newTemp(Ity_I64); 12257 IRTemp frAHi_I64 = newTemp(Ity_I64); 12258 IRTemp frALo_I64 = newTemp(Ity_I64); 12259 IRTemp flagsHi = newTemp(Ity_I32); 12260 IRTemp flagsLo = newTemp(Ity_I32); 12261 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 12262 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 12263 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 12264 12265 DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB); 12266 assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) ); 12267 assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) ); 12268 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 12269 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 12270 12271 _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi); 12272 _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo); 12273 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 12274 * where fl_flag == 1 on ppc64. 12275 */ 12276 assign( flagsHi, 12277 binop( Iop_Or32, 12278 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12279 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 12280 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 12281 assign( flagsLo, 12282 binop( Iop_Or32, 12283 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12284 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 12285 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 12286 putGST_field( PPC_GST_CR, 12287 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 12288 crfD ); 12289 break; 12290 } 12291 12292 default: 12293 vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" ); 12294 return False; 12295 } 12296 return True; 12297 } 12298 12299 /* 12300 * VSX vector Single Precision Floating Point Arithmetic Instructions 12301 */ 12302 static Bool 12303 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 ) 12304 { 12305 /* XX3-Form */ 12306 UChar opc1 = ifieldOPC( theInstr ); 12307 UChar XT = ifieldRegXT( theInstr ); 12308 UChar XA = ifieldRegXA( theInstr ); 12309 UChar XB = ifieldRegXB( theInstr ); 12310 IRExpr* rm = get_IR_roundingmode(); 12311 IRTemp a3, a2, a1, a0; 12312 IRTemp b3, b2, b1, b0; 12313 IRTemp res0 = newTemp(Ity_I32); 12314 IRTemp res1 = newTemp(Ity_I32); 12315 IRTemp res2 = newTemp(Ity_I32); 12316 IRTemp res3 = newTemp(Ity_I32); 12317 12318 a3 = a2 = a1 = a0 = IRTemp_INVALID; 12319 b3 = b2 = b1 = b0 = IRTemp_INVALID; 12320 12321 if (opc1 != 0x3C) { 12322 vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" ); 12323 return False; 12324 } 12325 12326 switch (opc2) { 12327 case 0x100: // xvaddsp (VSX Vector Add Single-Precision) 12328 DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 12329 putVSReg( XT, binop(Iop_Add32Fx4, getVSReg( XA ), getVSReg( XB )) ); 12330 break; 12331 12332 case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision) 12333 DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 12334 putVSReg( XT, binop(Iop_Mul32Fx4, getVSReg( XA ), getVSReg( XB )) ); 12335 break; 12336 12337 case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision) 12338 DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 12339 putVSReg( XT, binop(Iop_Sub32Fx4, getVSReg( XA ), getVSReg( XB )) ); 12340 break; 12341 12342 case 0x160: // xvdivsp (VSX Vector Divide Single-Precision) 12343 { 12344 /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c. 12345 * So there are two choices: 12346 * 1. Implement the xvdivsp with a native insn; or 12347 * 2. Extract the 4 single precision floats from each vector 12348 * register inputs and perform fdivs on each pair 12349 * I will do the latter, due to the general philosophy of 12350 * reusing existing implementations when practical. 12351 */ 12352 DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 12353 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 12354 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 12355 12356 assign( res0, 12357 unop( Iop_ReinterpF32asI32, 12358 unop( Iop_TruncF64asF32, 12359 triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) ); 12360 assign( res1, 12361 unop( Iop_ReinterpF32asI32, 12362 unop( Iop_TruncF64asF32, 12363 triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) ); 12364 assign( res2, 12365 unop( Iop_ReinterpF32asI32, 12366 unop( Iop_TruncF64asF32, 12367 triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) ); 12368 assign( res3, 12369 unop( Iop_ReinterpF32asI32, 12370 unop( Iop_TruncF64asF32, 12371 triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) ); 12372 12373 putVSReg( XT, 12374 binop( Iop_64HLtoV128, 12375 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 12376 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 12377 break; 12378 } 12379 case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision) 12380 { 12381 DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB); 12382 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 12383 /* Note: The native xvsqrtsp insruction does not always give the same precision 12384 * as what we get with Iop_SqrtF64. But it doesn't seem worthwhile to implement 12385 * an Iop_SqrtF32 that would give us a lower precision result, albeit more true 12386 * to the actual instruction. 12387 */ 12388 12389 assign( res0, 12390 unop( Iop_ReinterpF32asI32, 12391 unop( Iop_TruncF64asF32, 12392 binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) ); 12393 assign( res1, 12394 unop( Iop_ReinterpF32asI32, 12395 unop( Iop_TruncF64asF32, 12396 binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) ); 12397 assign( res2, 12398 unop( Iop_ReinterpF32asI32, 12399 unop( Iop_TruncF64asF32, 12400 binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) ); 12401 assign( res3, 12402 unop( Iop_ReinterpF32asI32, 12403 unop( Iop_TruncF64asF32, 12404 binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) ); 12405 12406 putVSReg( XT, 12407 binop( Iop_64HLtoV128, 12408 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 12409 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 12410 break; 12411 } 12412 12413 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision) 12414 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision) 12415 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision) 12416 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision) 12417 { 12418 IRTemp t3, t2, t1, t0; 12419 Bool msp = False; 12420 Bool negate; 12421 Char * oper_name = NULL; 12422 IROp mOp = Iop_INVALID; 12423 switch (opc2) { 12424 case 0x104: case 0x124: 12425 case 0x304: case 0x324: 12426 msp = (opc2 & 0x0FF) == 0x024; 12427 mOp = Iop_MAddF64r32; 12428 oper_name = "madd"; 12429 break; 12430 12431 case 0x144: case 0x164: 12432 case 0x344: case 0x364: 12433 msp = (opc2 & 0x0FF) == 0x064; 12434 mOp = Iop_MSubF64r32; 12435 oper_name = "sub"; 12436 break; 12437 12438 default: 12439 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 12440 } 12441 12442 switch (opc2) { 12443 case 0x304: case 0x324: 12444 case 0x344: case 0x364: 12445 negate = True; 12446 break; 12447 12448 default: 12449 negate = False; 12450 } 12451 12452 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp", 12453 (UInt)XT, (UInt)XA, (UInt)XB); 12454 12455 t3 = t2 = t1 = t0 = IRTemp_INVALID; 12456 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 12457 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 12458 breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 ); 12459 12460 assign( res0, 12461 unop( Iop_ReinterpF32asI32, 12462 unop( Iop_TruncF64asF32, 12463 qop( mOp, 12464 rm, 12465 mkexpr( a0 ), 12466 mkexpr( msp ? t0 : b0 ), 12467 mkexpr( msp ? b0 : t0 ) ) ) ) ); 12468 assign( res1, 12469 unop( Iop_ReinterpF32asI32, 12470 unop( Iop_TruncF64asF32, 12471 qop( mOp, 12472 rm, 12473 mkexpr( a1 ), 12474 mkexpr( msp ? t1 : b1 ), 12475 mkexpr( msp ? b1 : t1 ) ) ) ) ); 12476 assign( res2, 12477 unop( Iop_ReinterpF32asI32, 12478 unop( Iop_TruncF64asF32, 12479 qop( mOp, 12480 rm, 12481 mkexpr( a2 ), 12482 mkexpr( msp ? t2 : b2 ), 12483 mkexpr( msp ? b2 : t2 ) ) ) ) ); 12484 assign( res3, 12485 unop( Iop_ReinterpF32asI32, 12486 unop( Iop_TruncF64asF32, 12487 qop( mOp, 12488 rm, 12489 mkexpr( a3 ), 12490 mkexpr( msp ? t3 : b3 ), 12491 mkexpr( msp ? b3 : t3 ) ) ) ) ); 12492 12493 putVSReg( XT, 12494 binop( Iop_64HLtoV128, 12495 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ), 12496 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ), 12497 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ), 12498 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) ); 12499 12500 break; 12501 } 12502 case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision) 12503 { 12504 IRTemp flags0 = newTemp(Ity_I32); 12505 IRTemp flags1 = newTemp(Ity_I32); 12506 IRTemp flags2 = newTemp(Ity_I32); 12507 IRTemp flags3 = newTemp(Ity_I32); 12508 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 12509 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 12510 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 12511 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 12512 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 12513 DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB); 12514 12515 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 12516 do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0); 12517 do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1); 12518 do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2); 12519 do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3); 12520 12521 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 12522 * where fl_flag == 1 on ppc64. 12523 */ 12524 assign( flags0, 12525 binop( Iop_Or32, 12526 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12527 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 12528 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 12529 assign( flags1, 12530 binop( Iop_Or32, 12531 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12532 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 12533 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 12534 assign( flags2, 12535 binop( Iop_Or32, 12536 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12537 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 12538 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 12539 assign( flags3, 12540 binop( Iop_Or32, 12541 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12542 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 12543 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 12544 putGST_field( PPC_GST_CR, 12545 binop( Iop_Or32, 12546 mkexpr( flags0 ), 12547 binop( Iop_Or32, 12548 mkexpr( flags1 ), 12549 binop( Iop_Or32, 12550 mkexpr( flags2 ), 12551 mkexpr( flags3 ) ) ) ), 12552 crfD ); 12553 12554 break; 12555 } 12556 case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision) 12557 { 12558 IRTemp flags0 = newTemp(Ity_I32); 12559 IRTemp flags1 = newTemp(Ity_I32); 12560 IRTemp flags2 = newTemp(Ity_I32); 12561 IRTemp flags3 = newTemp(Ity_I32); 12562 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 12563 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 12564 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 12565 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 12566 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 12567 DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB); 12568 12569 breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 12570 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 12571 _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0); 12572 _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1); 12573 _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2); 12574 _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3); 12575 12576 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 12577 * where fl_flag == 1 on ppc64. 12578 */ 12579 assign( flags0, 12580 binop( Iop_Or32, 12581 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12582 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 12583 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 12584 assign( flags1, 12585 binop( Iop_Or32, 12586 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12587 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 12588 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 12589 assign( flags2, 12590 binop( Iop_Or32, 12591 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12592 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 12593 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 12594 assign( flags3, 12595 binop( Iop_Or32, 12596 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12597 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 12598 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 12599 putGST_field( PPC_GST_CR, 12600 binop( Iop_Or32, 12601 mkexpr( flags0 ), 12602 binop( Iop_Or32, 12603 mkexpr( flags1 ), 12604 binop( Iop_Or32, 12605 mkexpr( flags2 ), 12606 mkexpr( flags3 ) ) ) ), 12607 crfD ); 12608 12609 break; 12610 } 12611 12612 default: 12613 vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" ); 12614 return False; 12615 } 12616 return True; 12617 } 12618 12619 typedef enum { 12620 PPC_CMP_EQ = 2, 12621 PPC_CMP_GT = 4, 12622 PPC_CMP_GE = 6, 12623 PPC_CMP_LT = 8 12624 } ppc_cmp_t; 12625 12626 12627 /* 12628 This helper function takes as input the IRExpr returned 12629 from a binop( Iop_CmpF64, fpA, fpB), whose result is returned 12630 in IR form. This helper function converts it to PPC form. 12631 12632 Map compare result from IR to PPC 12633 12634 FP cmp result | PPC | IR 12635 -------------------------- 12636 UN | 0x1 | 0x45 12637 EQ | 0x2 | 0x40 12638 GT | 0x4 | 0x00 12639 LT | 0x8 | 0x01 12640 12641 condcode = Shl(1, (~(ccIR>>5) & 2) 12642 | ((ccIR ^ (ccIR>>6)) & 1) 12643 */ 12644 static IRTemp 12645 get_fp_cmp_CR_val (IRExpr * ccIR_expr) 12646 { 12647 IRTemp condcode = newTemp( Ity_I32 ); 12648 IRTemp ccIR = newTemp( Ity_I32 ); 12649 12650 assign(ccIR, ccIR_expr); 12651 assign( condcode, 12652 binop( Iop_Shl32, 12653 mkU32( 1 ), 12654 unop( Iop_32to8, 12655 binop( Iop_Or32, 12656 binop( Iop_And32, 12657 unop( Iop_Not32, 12658 binop( Iop_Shr32, 12659 mkexpr( ccIR ), 12660 mkU8( 5 ) ) ), 12661 mkU32( 2 ) ), 12662 binop( Iop_And32, 12663 binop( Iop_Xor32, 12664 mkexpr( ccIR ), 12665 binop( Iop_Shr32, 12666 mkexpr( ccIR ), 12667 mkU8( 6 ) ) ), 12668 mkU32( 1 ) ) ) ) ) ); 12669 return condcode; 12670 } 12671 12672 /* 12673 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles 12674 * following these special rules: 12675 * - The max/min of a QNaN and any value is that value 12676 * (When two QNaNs are being compared, the frA QNaN is the return value.) 12677 * - The max/min of any value and an SNaN is that SNaN converted to a QNaN 12678 * (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.) 12679 */ 12680 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64) 12681 { 12682 IRTemp frA_isNaN = newTemp(Ity_I1); 12683 IRTemp frB_isNaN = newTemp(Ity_I1); 12684 IRTemp frA_isSNaN = newTemp(Ity_I1); 12685 IRTemp frB_isSNaN = newTemp(Ity_I1); 12686 IRTemp frA_isQNaN = newTemp(Ity_I1); 12687 IRTemp frB_isQNaN = newTemp(Ity_I1); 12688 12689 assign( frA_isNaN, is_NaN( frA_I64 ) ); 12690 assign( frB_isNaN, is_NaN( frB_I64 ) ); 12691 // If operand is a NAN and bit 12 is '0', then it's an SNaN 12692 assign( frA_isSNaN, 12693 mkAND1( mkexpr(frA_isNaN), 12694 binop( Iop_CmpEQ32, 12695 binop( Iop_And32, 12696 unop( Iop_64HIto32, mkexpr( frA_I64 ) ), 12697 mkU32( 0x00080000 ) ), 12698 mkU32( 0 ) ) ) ); 12699 assign( frB_isSNaN, 12700 mkAND1( mkexpr(frB_isNaN), 12701 binop( Iop_CmpEQ32, 12702 binop( Iop_And32, 12703 unop( Iop_64HIto32, mkexpr( frB_I64 ) ), 12704 mkU32( 0x00080000 ) ), 12705 mkU32( 0 ) ) ) ); 12706 assign( frA_isQNaN, 12707 mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) ); 12708 assign( frB_isQNaN, 12709 mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) ); 12710 12711 /* Based on the rules specified in the function prologue, the algorithm is as follows: 12712 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 12713 * if frA is a SNaN 12714 * result = frA converted to QNaN 12715 * else if frB is a SNaN 12716 * result = frB converted to QNaN 12717 * else if frB is a QNaN 12718 * result = frA 12719 * // One of frA or frB was a NaN in order for this function to be called, so 12720 * // if we get to this point, we KNOW that frA must be a QNaN. 12721 * else // frA is a QNaN 12722 * result = frB 12723 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 12724 */ 12725 12726 #define SNAN_MASK 0x0008000000000000ULL 12727 return 12728 IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frA_isSNaN)), 12729 /* else: if frB is a SNaN */ 12730 IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isSNaN)), 12731 /* else: if frB is a QNaN */ 12732 IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isQNaN)), 12733 /* else: frA is a QNaN, so result = frB */ 12734 mkexpr(frB_I64), 12735 /* then: result = frA */ 12736 mkexpr(frA_I64)), 12737 /* then: result = frB converted to QNaN */ 12738 binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK))), 12739 /* then: result = frA converted to QNaN */ 12740 binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK))); 12741 } 12742 12743 /* 12744 * Helper function for get_max_min_fp. 12745 */ 12746 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin) 12747 { 12748 IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64, 12749 unop( Iop_ReinterpI64asF64, 12750 mkexpr( src1 ) ), 12751 unop( Iop_ReinterpI64asF64, 12752 mkexpr( src2 ) ) ) ); 12753 12754 return IRExpr_Mux0X( unop( Iop_1Uto8, 12755 binop( Iop_CmpEQ32, 12756 mkexpr( src1cmpsrc2 ), 12757 mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ) ), 12758 /* else: use src2 */ 12759 mkexpr( src2 ), 12760 /* then: use src1 */ 12761 mkexpr( src1 ) ); 12762 } 12763 12764 /* 12765 * Helper function for "Maximum/Minimum Double Precision" operations. 12766 * Arguments: frA and frb are Ity_I64 12767 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question 12768 */ 12769 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin) 12770 { 12771 /* There are three special cases where get_fp_cmp_CR_val is not helpful 12772 * for ascertaining the maximum between two doubles: 12773 * 1. The max/min of +0 and -0 is +0. 12774 * 2. The max/min of a QNaN and any value is that value. 12775 * 3. The max/min of any value and an SNaN is that SNaN converted to a QNaN. 12776 * We perform the check for [+/-]0 here in this function and use the 12777 * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp 12778 * to do the standard comparison function. 12779 */ 12780 IRTemp anyNaN = newTemp(Ity_I1); 12781 IRTemp frA_isZero = newTemp(Ity_I1); 12782 IRTemp frB_isZero = newTemp(Ity_I1); 12783 assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ )); 12784 assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ )); 12785 assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64))); 12786 #define MINUS_ZERO 0x8000000000000000ULL 12787 12788 return IRExpr_Mux0X( unop( Iop_1Uto8, 12789 /* If both arguments are zero . . . */ 12790 mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ) ), 12791 /* else: check if either input is a NaN*/ 12792 IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( anyNaN ) ), 12793 /* else: use "comparison helper" */ 12794 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ), 12795 /* then: use "NaN helper" */ 12796 _get_maxmin_fp_NaN( frA_I64, frB_I64 ) ), 12797 /* then: if frA is -0 and isMin==True, return -0; 12798 * else if frA is +0 and isMin==False; return +0; 12799 * otherwise, simply return frB. */ 12800 IRExpr_Mux0X( unop( Iop_1Uto8, 12801 binop( Iop_CmpEQ32, 12802 unop( Iop_64HIto32, 12803 mkexpr( frA_I64 ) ), 12804 mkU32( isMin ? 0x80000000 : 0 ) ) ), 12805 mkexpr( frB_I64 ), 12806 mkU64( isMin ? MINUS_ZERO : 0ULL ) ) ); 12807 } 12808 12809 /* 12810 * Helper function for vector/scalar double precision fp round to integer instructions. 12811 */ 12812 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2, UChar * insn_suffix) 12813 { 12814 12815 /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */ 12816 IRTemp frB = newTemp(Ity_F64); 12817 IRTemp frD = newTemp(Ity_F64); 12818 IRTemp intermediateResult = newTemp(Ity_I64); 12819 IRTemp is_SNAN = newTemp(Ity_I1); 12820 IRExpr * hi32; 12821 IRExpr * rxpi_rm; 12822 switch (opc2 & 0x7F) { 12823 case 0x72: 12824 insn_suffix = "m"; 12825 rxpi_rm = mkU32(Irrm_NegINF); 12826 break; 12827 case 0x52: 12828 insn_suffix = "p"; 12829 rxpi_rm = mkU32(Irrm_PosINF); 12830 break; 12831 case 0x56: 12832 insn_suffix = "c"; 12833 rxpi_rm = get_IR_roundingmode(); 12834 break; 12835 case 0x32: 12836 insn_suffix = "z"; 12837 rxpi_rm = mkU32(Irrm_ZERO); 12838 break; 12839 case 0x12: 12840 insn_suffix = ""; 12841 rxpi_rm = mkU32(Irrm_NEAREST); 12842 break; 12843 12844 default: // Impossible to get here 12845 vex_printf( "_do_vsx_fp_roundToInt(ppc)(opc2)\n" ); 12846 return NULL; 12847 } 12848 assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64))); 12849 assign( intermediateResult, 12850 binop( Iop_F64toI64S, rxpi_rm, 12851 mkexpr( frB ) ) ); 12852 12853 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 12854 /* F64 has only log10(2**52) significant digits anyway */ 12855 /* need to preserve sign of zero */ 12856 /* frD = (fabs(frB) > 9e18) ? frB : 12857 (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult */ 12858 assign( frD, 12859 IRExpr_Mux0X( unop( Iop_32to8, 12860 binop( Iop_CmpF64, 12861 IRExpr_Const( IRConst_F64( 9e18 ) ), 12862 unop( Iop_AbsF64, mkexpr( frB ) ) ) ), 12863 IRExpr_Mux0X( unop( Iop_32to8, 12864 binop( Iop_Shr32, 12865 unop( Iop_64HIto32, 12866 mkexpr( frB_I64 ) ), 12867 mkU8( 31 ) ) ), 12868 binop( Iop_I64StoF64, 12869 mkU32( 0 ), 12870 mkexpr( intermediateResult ) ), 12871 unop( Iop_NegF64, 12872 unop( Iop_AbsF64, 12873 binop( Iop_I64StoF64, 12874 mkU32( 0 ), 12875 mkexpr( intermediateResult ) ) ) ) ), 12876 mkexpr( frB ) ) ); 12877 12878 /* See Appendix "Floating-Point Round to Integer Model" in ISA doc. 12879 * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'. 12880 */ 12881 #define SNAN_MASK 0x0008000000000000ULL 12882 hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) ); 12883 assign( is_SNAN, 12884 mkAND1( is_NaN( frB_I64 ), 12885 binop( Iop_CmpEQ32, 12886 binop( Iop_And32, hi32, mkU32( 0x00080000 ) ), 12887 mkU32( 0 ) ) ) ); 12888 12889 return IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( is_SNAN ) ), 12890 mkexpr( frD ), 12891 unop( Iop_ReinterpI64asF64, 12892 binop( Iop_Xor64, 12893 mkU64( SNAN_MASK ), 12894 mkexpr( frB_I64 ) ) ) ); 12895 } 12896 12897 /* 12898 * Miscellaneous VSX vector instructions 12899 */ 12900 static Bool 12901 dis_vxv_misc ( UInt theInstr, UInt opc2 ) 12902 { 12903 /* XX3-Form */ 12904 UChar opc1 = ifieldOPC( theInstr ); 12905 UChar XT = ifieldRegXT( theInstr ); 12906 UChar XB = ifieldRegXB( theInstr ); 12907 12908 if (opc1 != 0x3C) { 12909 vex_printf( "dis_vxv_misc(ppc)(instr)\n" ); 12910 return False; 12911 } 12912 12913 switch (opc2) { 12914 case 0x1B4: // xvredp (VSX Vector Reciprocal Estimate Double-Precision) 12915 case 0x194: // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate 12916 // Double-Precision) 12917 { 12918 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 12919 IRExpr* rm = get_IR_roundingmode(); 12920 IRTemp frB = newTemp(Ity_I64); 12921 IRTemp frB2 = newTemp(Ity_I64); 12922 Bool redp = opc2 == 0x1B4; 12923 IRTemp sqrtHi = newTemp(Ity_F64); 12924 IRTemp sqrtLo = newTemp(Ity_F64); 12925 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 12926 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 12927 12928 DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB); 12929 if (!redp) { 12930 assign( sqrtHi, 12931 binop( Iop_SqrtF64, 12932 rm, 12933 unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) ); 12934 assign( sqrtLo, 12935 binop( Iop_SqrtF64, 12936 rm, 12937 unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) ); 12938 } 12939 putVSReg( XT, 12940 binop( Iop_64HLtoV128, 12941 unop( Iop_ReinterpF64asI64, 12942 triop( Iop_DivF64, 12943 rm, 12944 ieee_one, 12945 redp ? unop( Iop_ReinterpI64asF64, 12946 mkexpr( frB ) ) 12947 : mkexpr( sqrtHi ) ) ), 12948 unop( Iop_ReinterpF64asI64, 12949 triop( Iop_DivF64, 12950 rm, 12951 ieee_one, 12952 redp ? unop( Iop_ReinterpI64asF64, 12953 mkexpr( frB2 ) ) 12954 : mkexpr( sqrtLo ) ) ) ) ); 12955 break; 12956 12957 } 12958 case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision) 12959 case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision) 12960 { 12961 IRTemp b3, b2, b1, b0; 12962 IRTemp res0 = newTemp(Ity_I32); 12963 IRTemp res1 = newTemp(Ity_I32); 12964 IRTemp res2 = newTemp(Ity_I32); 12965 IRTemp res3 = newTemp(Ity_I32); 12966 IRTemp sqrt3 = newTemp(Ity_F64); 12967 IRTemp sqrt2 = newTemp(Ity_F64); 12968 IRTemp sqrt1 = newTemp(Ity_F64); 12969 IRTemp sqrt0 = newTemp(Ity_F64); 12970 IRExpr* rm = get_IR_roundingmode(); 12971 Bool resp = opc2 == 0x134; 12972 12973 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 12974 12975 b3 = b2 = b1 = b0 = IRTemp_INVALID; 12976 DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB); 12977 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 12978 12979 if (!resp) { 12980 assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) ); 12981 assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) ); 12982 assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) ); 12983 assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) ); 12984 } 12985 12986 assign( res0, 12987 unop( Iop_ReinterpF32asI32, 12988 unop( Iop_TruncF64asF32, 12989 triop( Iop_DivF64r32, 12990 rm, 12991 ieee_one, 12992 resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) ); 12993 assign( res1, 12994 unop( Iop_ReinterpF32asI32, 12995 unop( Iop_TruncF64asF32, 12996 triop( Iop_DivF64r32, 12997 rm, 12998 ieee_one, 12999 resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) ); 13000 assign( res2, 13001 unop( Iop_ReinterpF32asI32, 13002 unop( Iop_TruncF64asF32, 13003 triop( Iop_DivF64r32, 13004 rm, 13005 ieee_one, 13006 resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) ); 13007 assign( res3, 13008 unop( Iop_ReinterpF32asI32, 13009 unop( Iop_TruncF64asF32, 13010 triop( Iop_DivF64r32, 13011 rm, 13012 ieee_one, 13013 resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) ); 13014 putVSReg( XT, 13015 binop( Iop_64HLtoV128, 13016 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13017 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13018 break; 13019 } 13020 case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision) 13021 case 0x320: // xvminsp (VSX Vector Minimum Single-Precision) 13022 { 13023 UChar XA = ifieldRegXA( theInstr ); 13024 IRTemp a3, a2, a1, a0; 13025 IRTemp b3, b2, b1, b0; 13026 IRTemp res0 = newTemp( Ity_I32 ); 13027 IRTemp res1 = newTemp( Ity_I32 ); 13028 IRTemp res2 = newTemp( Ity_I32 ); 13029 IRTemp res3 = newTemp( Ity_I32 ); 13030 IRTemp a0_I64 = newTemp( Ity_I64 ); 13031 IRTemp a1_I64 = newTemp( Ity_I64 ); 13032 IRTemp a2_I64 = newTemp( Ity_I64 ); 13033 IRTemp a3_I64 = newTemp( Ity_I64 ); 13034 IRTemp b0_I64 = newTemp( Ity_I64 ); 13035 IRTemp b1_I64 = newTemp( Ity_I64 ); 13036 IRTemp b2_I64 = newTemp( Ity_I64 ); 13037 IRTemp b3_I64 = newTemp( Ity_I64 ); 13038 13039 Bool isMin = opc2 == 0x320 ? True : False; 13040 13041 a3 = a2 = a1 = a0 = IRTemp_INVALID; 13042 b3 = b2 = b1 = b0 = IRTemp_INVALID; 13043 DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB); 13044 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13045 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13046 assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) ); 13047 assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) ); 13048 assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) ); 13049 assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) ); 13050 assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) ); 13051 assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) ); 13052 assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) ); 13053 assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) ); 13054 assign( res0, 13055 unop( Iop_ReinterpF32asI32, 13056 unop( Iop_TruncF64asF32, 13057 unop( Iop_ReinterpI64asF64, 13058 get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) ); 13059 assign( res1, 13060 unop( Iop_ReinterpF32asI32, 13061 unop( Iop_TruncF64asF32, 13062 unop( Iop_ReinterpI64asF64, 13063 get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) ); 13064 assign( res2, 13065 unop( Iop_ReinterpF32asI32, 13066 unop( Iop_TruncF64asF32, 13067 unop( Iop_ReinterpI64asF64, 13068 get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) ); 13069 assign( res3, 13070 unop( Iop_ReinterpF32asI32, 13071 unop( Iop_TruncF64asF32, 13072 unop( Iop_ReinterpI64asF64, 13073 get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) ); 13074 putVSReg( XT, 13075 binop( Iop_64HLtoV128, 13076 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13077 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13078 break; 13079 } 13080 case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision) 13081 case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision) 13082 { 13083 UChar XA = ifieldRegXA( theInstr ); 13084 IRTemp frA = newTemp(Ity_I64); 13085 IRTemp frB = newTemp(Ity_I64); 13086 IRTemp frA2 = newTemp(Ity_I64); 13087 IRTemp frB2 = newTemp(Ity_I64); 13088 Bool isMin = opc2 == 0x3A0 ? True : False; 13089 13090 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 13091 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 13092 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 13093 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 13094 DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB); 13095 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) ); 13096 13097 break; 13098 } 13099 case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision) 13100 { 13101 UChar XA = ifieldRegXA( theInstr ); 13102 IRTemp frA = newTemp(Ity_I64); 13103 IRTemp frB = newTemp(Ity_I64); 13104 IRTemp frA2 = newTemp(Ity_I64); 13105 IRTemp frB2 = newTemp(Ity_I64); 13106 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 13107 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 13108 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 13109 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 13110 13111 DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13112 putVSReg( XT, 13113 binop( Iop_64HLtoV128, 13114 binop( Iop_Or64, 13115 binop( Iop_And64, 13116 mkexpr( frA ), 13117 mkU64( SIGN_BIT ) ), 13118 binop( Iop_And64, 13119 mkexpr( frB ), 13120 mkU64( SIGN_MASK ) ) ), 13121 binop( Iop_Or64, 13122 binop( Iop_And64, 13123 mkexpr( frA2 ), 13124 mkU64( SIGN_BIT ) ), 13125 binop( Iop_And64, 13126 mkexpr( frB2 ), 13127 mkU64( SIGN_MASK ) ) ) ) ); 13128 break; 13129 } 13130 case 0x340: // xvcpsgnsp 13131 { 13132 UChar XA = ifieldRegXA( theInstr ); 13133 IRTemp a3_I64, a2_I64, a1_I64, a0_I64; 13134 IRTemp b3_I64, b2_I64, b1_I64, b0_I64; 13135 IRTemp resHi = newTemp(Ity_I64); 13136 IRTemp resLo = newTemp(Ity_I64); 13137 13138 a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID; 13139 b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID; 13140 DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB); 13141 breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 ); 13142 breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 ); 13143 13144 assign( resHi, 13145 binop( Iop_32HLto64, 13146 binop( Iop_Or32, 13147 binop( Iop_And32, 13148 unop(Iop_64to32, mkexpr( a3_I64 ) ), 13149 mkU32( SIGN_BIT32 ) ), 13150 binop( Iop_And32, 13151 unop(Iop_64to32, mkexpr( b3_I64 ) ), 13152 mkU32( SIGN_MASK32) ) ), 13153 13154 binop( Iop_Or32, 13155 binop( Iop_And32, 13156 unop(Iop_64to32, mkexpr( a2_I64 ) ), 13157 mkU32( SIGN_BIT32 ) ), 13158 binop( Iop_And32, 13159 unop(Iop_64to32, mkexpr( b2_I64 ) ), 13160 mkU32( SIGN_MASK32 ) ) ) ) ); 13161 assign( resLo, 13162 binop( Iop_32HLto64, 13163 binop( Iop_Or32, 13164 binop( Iop_And32, 13165 unop(Iop_64to32, mkexpr( a1_I64 ) ), 13166 mkU32( SIGN_BIT32 ) ), 13167 binop( Iop_And32, 13168 unop(Iop_64to32, mkexpr( b1_I64 ) ), 13169 mkU32( SIGN_MASK32 ) ) ), 13170 13171 binop( Iop_Or32, 13172 binop( Iop_And32, 13173 unop(Iop_64to32, mkexpr( a0_I64 ) ), 13174 mkU32( SIGN_BIT32 ) ), 13175 binop( Iop_And32, 13176 unop(Iop_64to32, mkexpr( b0_I64 ) ), 13177 mkU32( SIGN_MASK32 ) ) ) ) ); 13178 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) ); 13179 break; 13180 } 13181 case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision) 13182 case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision) 13183 { 13184 IRTemp frB = newTemp(Ity_F64); 13185 IRTemp frB2 = newTemp(Ity_F64); 13186 IRTemp abs_resultHi = newTemp(Ity_F64); 13187 IRTemp abs_resultLo = newTemp(Ity_F64); 13188 Bool make_negative = (opc2 == 0x3D2) ? True : False; 13189 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 13190 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 13191 13192 DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB); 13193 if (make_negative) { 13194 assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) ); 13195 assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) ); 13196 13197 } else { 13198 assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) ); 13199 assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) ); 13200 } 13201 putVSReg( XT, binop( Iop_64HLtoV128, 13202 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ), 13203 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) ); 13204 break; 13205 } 13206 case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision) 13207 case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision) 13208 { 13209 /* 13210 * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction 13211 * of xvabssp, there has not been an abs(sp) type of instruction. But since emulation 13212 * of this function is so easy using shifts, I choose to emulate this instruction that 13213 * way versus a native instruction method of implementation. 13214 */ 13215 Bool make_negative = (opc2 == 0x352) ? True : False; 13216 IRTemp shiftVector = newTemp(Ity_V128); 13217 IRTemp absVal_vector = newTemp(Ity_V128); 13218 assign( shiftVector, 13219 binop( Iop_64HLtoV128, 13220 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ), 13221 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) ); 13222 assign( absVal_vector, 13223 binop( Iop_Shr32x4, 13224 binop( Iop_Shl32x4, 13225 getVSReg( XB ), 13226 mkexpr( shiftVector ) ), 13227 mkexpr( shiftVector ) ) ); 13228 if (make_negative) { 13229 IRTemp signBit_vector = newTemp(Ity_V128); 13230 assign( signBit_vector, 13231 binop( Iop_64HLtoV128, 13232 binop( Iop_32HLto64, 13233 mkU32( 0x80000000 ), 13234 mkU32( 0x80000000 ) ), 13235 binop( Iop_32HLto64, 13236 mkU32( 0x80000000 ), 13237 mkU32( 0x80000000 ) ) ) ); 13238 putVSReg( XT, 13239 binop( Iop_OrV128, 13240 mkexpr( absVal_vector ), 13241 mkexpr( signBit_vector ) ) ); 13242 } else { 13243 putVSReg( XT, mkexpr( absVal_vector ) ); 13244 } 13245 break; 13246 } 13247 case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision) 13248 { 13249 IRTemp frB = newTemp(Ity_F64); 13250 IRTemp frB2 = newTemp(Ity_F64); 13251 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 13252 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 13253 DIP("xvnegdp v%d,v%d\n", (UInt)XT, (UInt)XB); 13254 putVSReg( XT, 13255 binop( Iop_64HLtoV128, 13256 unop( Iop_ReinterpF64asI64, 13257 unop( Iop_NegF64, mkexpr( frB ) ) ), 13258 unop( Iop_ReinterpF64asI64, 13259 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) ); 13260 break; 13261 } 13262 case 0x192: // xvrdpi (VSX Vector Round to Double-Precision Integer using round toward Nearest Away) 13263 case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode) 13264 case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity) 13265 case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity) 13266 case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero) 13267 { 13268 IRTemp frBHi_I64 = newTemp(Ity_I64); 13269 IRTemp frBLo_I64 = newTemp(Ity_I64); 13270 IRExpr * frD_fp_roundHi = NULL; 13271 IRExpr * frD_fp_roundLo = NULL; 13272 UChar * insn_suffix = NULL; 13273 13274 assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 13275 frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2, insn_suffix); 13276 assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) ); 13277 frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2, insn_suffix); 13278 13279 DIP("xvrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB); 13280 putVSReg( XT, 13281 binop( Iop_64HLtoV128, 13282 unop( Iop_ReinterpF64asI64, frD_fp_roundHi ), 13283 unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) ); 13284 break; 13285 } 13286 case 0x112: // xvrspi (VSX Vector Round to Single-Precision Integer using round toward Nearest Away) 13287 case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode) 13288 case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity) 13289 case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity) 13290 case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero) 13291 { 13292 UChar * insn_suffix = NULL; 13293 IROp op; 13294 if (opc2 != 0x156) { 13295 // Use pre-defined IRop's for vrfi{m|n|p|z} 13296 switch (opc2) { 13297 case 0x112: 13298 insn_suffix = ""; 13299 op = Iop_RoundF32x4_RN; 13300 break; 13301 case 0x172: 13302 insn_suffix = "m"; 13303 op = Iop_RoundF32x4_RM; 13304 break; 13305 case 0x152: 13306 insn_suffix = "p"; 13307 op = Iop_RoundF32x4_RP; 13308 break; 13309 case 0x132: 13310 insn_suffix = "z"; 13311 op = Iop_RoundF32x4_RZ; 13312 break; 13313 13314 default: 13315 vex_printf( "dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n" ); 13316 return False; 13317 } 13318 DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB); 13319 putVSReg( XT, unop( op, getVSReg(XB) ) ); 13320 } else { 13321 // Handle xvrspic. Unfortunately there is no corresponding "vfric" instruction. 13322 IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0; 13323 IRTemp b3_F64, b2_F64, b1_F64, b0_F64; 13324 IRTemp b3_I64 = newTemp(Ity_I64); 13325 IRTemp b2_I64 = newTemp(Ity_I64); 13326 IRTemp b1_I64 = newTemp(Ity_I64); 13327 IRTemp b0_I64 = newTemp(Ity_I64); 13328 13329 b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID; 13330 frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL; 13331 breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64); 13332 assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64))); 13333 assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64))); 13334 assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64))); 13335 assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64))); 13336 frD_fp_roundb3 = unop(Iop_TruncF64asF32, 13337 _do_vsx_fp_roundToInt(b3_I64, opc2, insn_suffix)); 13338 frD_fp_roundb2 = unop(Iop_TruncF64asF32, 13339 _do_vsx_fp_roundToInt(b2_I64, opc2, insn_suffix)); 13340 frD_fp_roundb1 = unop(Iop_TruncF64asF32, 13341 _do_vsx_fp_roundToInt(b1_I64, opc2, insn_suffix)); 13342 frD_fp_roundb0 = unop(Iop_TruncF64asF32, 13343 _do_vsx_fp_roundToInt(b0_I64, opc2, insn_suffix)); 13344 DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB); 13345 putVSReg( XT, 13346 binop( Iop_64HLtoV128, 13347 binop( Iop_32HLto64, 13348 unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ), 13349 unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ), 13350 binop( Iop_32HLto64, 13351 unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ), 13352 unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) ); 13353 } 13354 break; 13355 } 13356 13357 default: 13358 vex_printf( "dis_vxv_misc(ppc)(opc2)\n" ); 13359 return False; 13360 } 13361 return True; 13362 } 13363 13364 13365 /* 13366 * VSX Scalar Floating Point Arithmetic Instructions 13367 */ 13368 static Bool 13369 dis_vxs_arith ( UInt theInstr, UInt opc2 ) 13370 { 13371 /* XX3-Form */ 13372 UChar opc1 = ifieldOPC( theInstr ); 13373 UChar XT = ifieldRegXT( theInstr ); 13374 UChar XA = ifieldRegXA( theInstr ); 13375 UChar XB = ifieldRegXB( theInstr ); 13376 IRExpr* rm = get_IR_roundingmode(); 13377 IRTemp frA = newTemp(Ity_F64); 13378 IRTemp frB = newTemp(Ity_F64); 13379 13380 if (opc1 != 0x3C) { 13381 vex_printf( "dis_vxs_arith(ppc)(instr)\n" ); 13382 return False; 13383 } 13384 13385 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 13386 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 13387 13388 /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1 13389 * of VSX[XT] are undefined after the operation; therefore, we can simply set 13390 * element to zero where it makes sense to do so. 13391 */ 13392 switch (opc2) { 13393 case 0x080: // xsadddp (VSX scalar add double-precision) 13394 DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13395 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 13396 triop( Iop_AddF64, rm, 13397 mkexpr( frA ), 13398 mkexpr( frB ) ) ), 13399 mkU64( 0 ) ) ); 13400 break; 13401 case 0x0E0: // xsdivdp (VSX scalar divide double-precision) 13402 DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13403 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 13404 triop( Iop_DivF64, rm, 13405 mkexpr( frA ), 13406 mkexpr( frB ) ) ), 13407 mkU64( 0 ) ) ); 13408 break; 13409 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision) 13410 { 13411 IRTemp frT = newTemp(Ity_F64); 13412 Bool mdp = opc2 == 0x0A4; 13413 DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 13414 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 13415 getVSReg( XT ) ) ) ); 13416 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 13417 qop( Iop_MAddF64, rm, 13418 mkexpr( frA ), 13419 mkexpr( mdp ? frT : frB ), 13420 mkexpr( mdp ? frB : frT ) ) ), 13421 mkU64( 0 ) ) ); 13422 break; 13423 } 13424 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision) 13425 { 13426 IRTemp frT = newTemp(Ity_F64); 13427 Bool mdp = opc2 == 0x0E4; 13428 DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 13429 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 13430 getVSReg( XT ) ) ) ); 13431 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 13432 qop( Iop_MSubF64, rm, 13433 mkexpr( frA ), 13434 mkexpr( mdp ? frT : frB ), 13435 mkexpr( mdp ? frB : frT ) ) ), 13436 mkU64( 0 ) ) ); 13437 break; 13438 } 13439 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision) 13440 { 13441 /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation 13442 * of fnmadd and use pretty much the same code. However, that code has a bug in the 13443 * way it blindly negates the signbit, even if the floating point result is a NaN. 13444 * So, the TODO is to fix fnmadd (which I'll do in a different patch). 13445 * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign 13446 * bit for NaN result. 13447 */ 13448 Bool mdp = opc2 == 0x2A4; 13449 IRTemp frT = newTemp(Ity_F64); 13450 IRTemp maddResult = newTemp(Ity_I64); 13451 13452 DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 13453 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 13454 getVSReg( XT ) ) ) ); 13455 assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm, 13456 mkexpr( frA ), 13457 mkexpr( mdp ? frT : frB ), 13458 mkexpr( mdp ? frB : frT ) ) ) ); 13459 13460 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ), 13461 mkU64( 0 ) ) ); 13462 break; 13463 } 13464 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision) 13465 { 13466 IRTemp frT = newTemp(Ity_F64); 13467 Bool mdp = opc2 == 0x2E4; 13468 IRTemp msubResult = newTemp(Ity_I64); 13469 13470 DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 13471 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 13472 getVSReg( XT ) ) ) ); 13473 assign(msubResult, unop( Iop_ReinterpF64asI64, 13474 qop( Iop_MSubF64, 13475 rm, 13476 mkexpr( frA ), 13477 mkexpr( mdp ? frT : frB ), 13478 mkexpr( mdp ? frB : frT ) ) )); 13479 13480 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) ); 13481 13482 break; 13483 } 13484 13485 case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision) 13486 DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13487 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 13488 triop( Iop_MulF64, rm, 13489 mkexpr( frA ), 13490 mkexpr( frB ) ) ), 13491 mkU64( 0 ) ) ); 13492 break; 13493 case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision) 13494 DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13495 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 13496 triop( Iop_SubF64, rm, 13497 mkexpr( frA ), 13498 mkexpr( frB ) ) ), 13499 mkU64( 0 ) ) ); 13500 break; 13501 13502 case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision) 13503 DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 13504 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 13505 binop( Iop_SqrtF64, rm, 13506 mkexpr( frB ) ) ), 13507 mkU64( 0 ) ) ); 13508 break; 13509 13510 case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision) 13511 { 13512 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13513 IRTemp frA_I64 = newTemp(Ity_I64); 13514 IRTemp frB_I64 = newTemp(Ity_I64); 13515 DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB); 13516 assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) ); 13517 assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 13518 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 13519 break; 13520 } 13521 case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision) 13522 { 13523 IRTemp frB_I64 = newTemp(Ity_I64); 13524 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13525 IRTemp flags = newTemp(Ity_I32); 13526 IRTemp fe_flag, fg_flag; 13527 fe_flag = fg_flag = IRTemp_INVALID; 13528 DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 13529 assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 13530 do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag); 13531 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13532 * where fl_flag == 1 on ppc64. 13533 */ 13534 assign( flags, 13535 binop( Iop_Or32, 13536 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13537 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 13538 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 13539 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 13540 break; 13541 } 13542 13543 default: 13544 vex_printf( "dis_vxs_arith(ppc)(opc2)\n" ); 13545 return False; 13546 } 13547 13548 return True; 13549 } 13550 13551 13552 /* 13553 * VSX Floating Point Compare Instructions 13554 */ 13555 static Bool 13556 dis_vx_cmp( UInt theInstr, UInt opc2 ) 13557 { 13558 /* XX3-Form and XX2-Form */ 13559 UChar opc1 = ifieldOPC( theInstr ); 13560 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13561 IRTemp ccPPC32; 13562 UChar XA = ifieldRegXA ( theInstr ); 13563 UChar XB = ifieldRegXB ( theInstr ); 13564 IRTemp frA = newTemp(Ity_F64); 13565 IRTemp frB = newTemp(Ity_F64); 13566 13567 if (opc1 != 0x3C) { 13568 vex_printf( "dis_vx_cmp(ppc)(instr)\n" ); 13569 return False; 13570 } 13571 13572 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 13573 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 13574 switch (opc2) { 13575 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 13576 /* Note: Differences between xscmpudp and xscmpodp are only in 13577 * exception flag settings, which aren't supported anyway. */ 13578 DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o", 13579 crfD, (UInt)XA, (UInt)XB); 13580 ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB))); 13581 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 13582 break; 13583 13584 default: 13585 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" ); 13586 return False; 13587 } 13588 return True; 13589 } 13590 13591 static void 13592 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC, 13593 ppc_cmp_t cmp_type ) 13594 { 13595 IRTemp frA_hi = newTemp(Ity_F64); 13596 IRTemp frB_hi = newTemp(Ity_F64); 13597 IRTemp frA_lo = newTemp(Ity_F64); 13598 IRTemp frB_lo = newTemp(Ity_F64); 13599 IRTemp ccPPC32 = newTemp(Ity_I32); 13600 IRTemp ccIR_hi; 13601 IRTemp ccIR_lo; 13602 13603 IRTemp hiResult = newTemp(Ity_I64); 13604 IRTemp loResult = newTemp(Ity_I64); 13605 IRTemp hiEQlo = newTemp(Ity_I1); 13606 IRTemp all_elem_true = newTemp(Ity_I32); 13607 IRTemp all_elem_false = newTemp(Ity_I32); 13608 13609 assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA )))); 13610 assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB )))); 13611 assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA )))); 13612 assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB )))); 13613 13614 ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64, 13615 mkexpr( frA_hi ), 13616 mkexpr( frB_hi ) ) ); 13617 ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64, 13618 mkexpr( frA_lo ), 13619 mkexpr( frB_lo ) ) ); 13620 13621 if (cmp_type != PPC_CMP_GE) { 13622 assign( hiResult, 13623 unop( Iop_1Sto64, 13624 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) ); 13625 assign( loResult, 13626 unop( Iop_1Sto64, 13627 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) ); 13628 } else { 13629 // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and 13630 // the other element compare may return "2" (for "equal to"). 13631 IRTemp lo_GE = newTemp(Ity_I1); 13632 IRTemp hi_GE = newTemp(Ity_I1); 13633 13634 assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ), 13635 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) ); 13636 assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) ); 13637 13638 assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ), 13639 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) ); 13640 assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) ); 13641 } 13642 13643 // The [hi/lo]Result will be all 1's or all 0's. We just look at the lower word. 13644 assign( hiEQlo, 13645 binop( Iop_CmpEQ32, 13646 unop( Iop_64to32, mkexpr( hiResult ) ), 13647 unop( Iop_64to32, mkexpr( loResult ) ) ) ); 13648 putVSReg( XT, 13649 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 13650 13651 assign( all_elem_true, 13652 unop( Iop_1Uto32, 13653 mkAND1( mkexpr( hiEQlo ), 13654 binop( Iop_CmpEQ32, 13655 mkU32( 0xffffffff ), 13656 unop( Iop_64to32, 13657 mkexpr( hiResult ) ) ) ) ) ); 13658 13659 assign( all_elem_false, 13660 unop( Iop_1Uto32, 13661 mkAND1( mkexpr( hiEQlo ), 13662 binop( Iop_CmpEQ32, 13663 mkU32( 0 ), 13664 unop( Iop_64to32, 13665 mkexpr( hiResult ) ) ) ) ) ); 13666 assign( ccPPC32, 13667 binop( Iop_Or32, 13668 binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ), 13669 binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) ); 13670 13671 if (flag_rC) { 13672 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 ); 13673 } 13674 } 13675 13676 /* 13677 * VSX Vector Compare Instructions 13678 */ 13679 static Bool 13680 dis_vvec_cmp( UInt theInstr, UInt opc2 ) 13681 { 13682 /* XX3-Form */ 13683 UChar opc1 = ifieldOPC( theInstr ); 13684 UChar XT = ifieldRegXT ( theInstr ); 13685 UChar XA = ifieldRegXA ( theInstr ); 13686 UChar XB = ifieldRegXB ( theInstr ); 13687 UChar flag_rC = ifieldBIT10(theInstr); 13688 IRTemp vA = newTemp( Ity_V128 ); 13689 IRTemp vB = newTemp( Ity_V128 ); 13690 13691 if (opc1 != 0x3C) { 13692 vex_printf( "dis_vvec_cmp(ppc)(instr)\n" ); 13693 return False; 13694 } 13695 13696 assign( vA, getVSReg( XA ) ); 13697 assign( vB, getVSReg( XB ) ); 13698 13699 switch (opc2) { 13700 case 0x18C: case 0x38C: // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ]) 13701 { 13702 DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 13703 (UInt)XT, (UInt)XA, (UInt)XB); 13704 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ); 13705 break; 13706 } 13707 13708 case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ]) 13709 { 13710 DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 13711 (UInt)XT, (UInt)XA, (UInt)XB); 13712 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE); 13713 break; 13714 } 13715 13716 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ]) 13717 { 13718 DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 13719 (UInt)XT, (UInt)XA, (UInt)XB); 13720 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT); 13721 break; 13722 } 13723 13724 case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ]) 13725 { 13726 IRTemp vD = newTemp(Ity_V128); 13727 13728 DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 13729 (UInt)XT, (UInt)XA, (UInt)XB); 13730 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 13731 putVSReg( XT, mkexpr(vD) ); 13732 if (flag_rC) { 13733 set_AV_CR6( mkexpr(vD), True ); 13734 } 13735 break; 13736 } 13737 13738 case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ]) 13739 { 13740 IRTemp vD = newTemp(Ity_V128); 13741 13742 DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 13743 (UInt)XT, (UInt)XA, (UInt)XB); 13744 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 13745 putVSReg( XT, mkexpr(vD) ); 13746 if (flag_rC) { 13747 set_AV_CR6( mkexpr(vD), True ); 13748 } 13749 break; 13750 } 13751 13752 case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ]) 13753 { 13754 IRTemp vD = newTemp(Ity_V128); 13755 13756 DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 13757 (UInt)XT, (UInt)XA, (UInt)XB); 13758 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 13759 putVSReg( XT, mkexpr(vD) ); 13760 if (flag_rC) { 13761 set_AV_CR6( mkexpr(vD), True ); 13762 } 13763 break; 13764 } 13765 13766 default: 13767 vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" ); 13768 return False; 13769 } 13770 return True; 13771 } 13772 /* 13773 * Miscellaneous VSX Scalar Instructions 13774 */ 13775 static Bool 13776 dis_vxs_misc( UInt theInstr, UInt opc2 ) 13777 { 13778 /* XX3-Form and XX2-Form */ 13779 UChar opc1 = ifieldOPC( theInstr ); 13780 UChar XT = ifieldRegXT ( theInstr ); 13781 UChar XA = ifieldRegXA ( theInstr ); 13782 UChar XB = ifieldRegXB ( theInstr ); 13783 IRTemp vA = newTemp( Ity_V128 ); 13784 IRTemp vB = newTemp( Ity_V128 ); 13785 13786 if (opc1 != 0x3C) { 13787 vex_printf( "dis_vxs_misc(ppc)(instr)\n" ); 13788 return False; 13789 } 13790 13791 assign( vA, getVSReg( XA ) ); 13792 assign( vB, getVSReg( XB ) ); 13793 13794 /* For all the VSX move instructions, the contents of doubleword element 1 13795 * of VSX[XT] are undefined after the operation; therefore, we can simply 13796 * move the entire array element where it makes sense to do so. 13797 */ 13798 13799 switch (opc2) { 13800 case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision 13801 { 13802 /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */ 13803 IRTemp absVal = newTemp(Ity_V128); 13804 assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1))); 13805 DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 13806 putVSReg(XT, mkexpr(absVal)); 13807 break; 13808 } 13809 case 0x2C0: // xscpsgndp 13810 { 13811 /* Scalar copy sign double-precision */ 13812 IRTemp vecA_signbit = newTemp(Ity_V128); 13813 IRTemp vecB_no_signbit = newTemp(Ity_V128); 13814 IRTemp vec_result = newTemp(Ity_V128); 13815 DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13816 assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128, 13817 mkexpr( vB ), 13818 mkU8( 1 ) ), 13819 mkU8( 1 ) ) ); 13820 assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128, 13821 mkexpr( vA ), 13822 mkU8( 127 ) ), 13823 mkU8( 127 ) ) ); 13824 assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) ); 13825 putVSReg(XT, mkexpr(vec_result)); 13826 break; 13827 } 13828 case 0x2D2: // xsnabsdp 13829 { 13830 /* Scalar negative absolute value double-precision */ 13831 IRTemp vec_neg_signbit = newTemp(Ity_V128); 13832 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 13833 assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128, 13834 mkV128( 0xffff ), 13835 mkU8( 1 ) ) ) ); 13836 putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB))); 13837 break; 13838 } 13839 case 0x2F2: // xsnegdp 13840 { 13841 /* Scalar negate double-precision */ 13842 IRTemp vecB_no_signbit = newTemp(Ity_V128); 13843 IRTemp vecB_signbit_comp = newTemp(Ity_V128); 13844 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 13845 assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128, 13846 mkexpr( vB ), 13847 mkU8( 1 ) ), 13848 mkU8( 1 ) ) ); 13849 assign( vecB_signbit_comp, binop( Iop_ShlV128, 13850 unop( Iop_NotV128, 13851 binop( Iop_ShrV128, 13852 mkexpr( vB ), 13853 mkU8( 127 ) ) ), 13854 mkU8( 127 ) ) ); 13855 putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ), 13856 mkexpr( vecB_signbit_comp ) ) ); 13857 break; 13858 } 13859 case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision) 13860 case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision) 13861 { 13862 IRTemp frA = newTemp(Ity_I64); 13863 IRTemp frB = newTemp(Ity_I64); 13864 Bool isMin = opc2 == 0x2A0 ? True : False; 13865 DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB); 13866 13867 assign(frA, unop(Iop_V128HIto64, mkexpr( vA ))); 13868 assign(frB, unop(Iop_V128HIto64, mkexpr( vB ))); 13869 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) ); 13870 13871 break; 13872 } 13873 case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity) 13874 case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity) 13875 case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode) 13876 case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero) 13877 case 0x092: // xsrdpi (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away) 13878 { 13879 IRTemp frB_I64 = newTemp(Ity_I64); 13880 IRExpr * frD_fp_round = NULL; 13881 UChar * insn_suffix = NULL; 13882 13883 assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB ))); 13884 frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2, insn_suffix); 13885 13886 DIP("xsrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB); 13887 putVSReg( XT, 13888 binop( Iop_64HLtoV128, 13889 unop( Iop_ReinterpF64asI64, frD_fp_round), 13890 mkU64( 0 ) ) ); 13891 break; 13892 } 13893 case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision) 13894 case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision) 13895 13896 { 13897 IRTemp frB = newTemp(Ity_F64); 13898 IRTemp sqrt = newTemp(Ity_F64); 13899 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 13900 IRExpr* rm = get_IR_roundingmode(); 13901 Bool redp = opc2 == 0x0B4; 13902 DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB); 13903 assign( frB, 13904 unop( Iop_ReinterpI64asF64, 13905 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 13906 13907 if (!redp) 13908 assign( sqrt, 13909 binop( Iop_SqrtF64, 13910 rm, 13911 mkexpr(frB) ) ); 13912 putVSReg( XT, 13913 binop( Iop_64HLtoV128, 13914 unop( Iop_ReinterpF64asI64, 13915 triop( Iop_DivF64, 13916 rm, 13917 ieee_one, 13918 redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ), 13919 mkU64( 0 ) ) ); 13920 break; 13921 } 13922 13923 default: 13924 vex_printf( "dis_vxs_misc(ppc)(opc2)\n" ); 13925 return False; 13926 } 13927 return True; 13928 } 13929 13930 /* 13931 * VSX Logical Instructions 13932 */ 13933 static Bool 13934 dis_vx_logic ( UInt theInstr, UInt opc2 ) 13935 { 13936 /* XX3-Form */ 13937 UChar opc1 = ifieldOPC( theInstr ); 13938 UChar XT = ifieldRegXT ( theInstr ); 13939 UChar XA = ifieldRegXA ( theInstr ); 13940 UChar XB = ifieldRegXB ( theInstr ); 13941 IRTemp vA = newTemp( Ity_V128 ); 13942 IRTemp vB = newTemp( Ity_V128 ); 13943 13944 if (opc1 != 0x3C) { 13945 vex_printf( "dis_vx_logic(ppc)(instr)\n" ); 13946 return False; 13947 } 13948 13949 assign( vA, getVSReg( XA ) ); 13950 assign( vB, getVSReg( XB ) ); 13951 13952 switch (opc2) { 13953 case 0x268: // xxlxor 13954 DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13955 putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) ); 13956 break; 13957 case 0x248: // xxlor 13958 DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13959 putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) ); 13960 break; 13961 case 0x288: // xxlnor 13962 DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13963 putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ), 13964 mkexpr( vB ) ) ) ); 13965 break; 13966 case 0x208: // xxland 13967 DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13968 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) ); 13969 break; 13970 case 0x228: //xxlandc 13971 DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13972 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128, 13973 mkexpr( vB ) ) ) ); 13974 break; 13975 default: 13976 vex_printf( "dis_vx_logic(ppc)(opc2)\n" ); 13977 return False; 13978 } 13979 return True; 13980 } 13981 13982 /* 13983 * VSX Load Instructions 13984 * NOTE: VSX supports word-aligned storage access. 13985 */ 13986 static Bool 13987 dis_vx_load ( UInt theInstr ) 13988 { 13989 /* XX1-Form */ 13990 UChar opc1 = ifieldOPC( theInstr ); 13991 UChar XT = ifieldRegXT ( theInstr ); 13992 UChar rA_addr = ifieldRegA( theInstr ); 13993 UChar rB_addr = ifieldRegB( theInstr ); 13994 UInt opc2 = ifieldOPClo10( theInstr ); 13995 13996 IRType ty = mode64 ? Ity_I64 : Ity_I32; 13997 IRTemp EA = newTemp( ty ); 13998 13999 if (opc1 != 0x1F) { 14000 vex_printf( "dis_vx_load(ppc)(instr)\n" ); 14001 return False; 14002 } 14003 14004 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 14005 14006 switch (opc2) { 14007 case 0x24C: // lxsdx 14008 { 14009 IRExpr * exp; 14010 DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 14011 exp = loadBE( Ity_I64, mkexpr( EA ) ); 14012 // We need to pass an expression of type Ity_V128 with putVSReg, but the load 14013 // we just performed is only a DW. But since the contents of VSR[XT] element 1 14014 // are undefined after this operation, we can just do a splat op. 14015 putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) ); 14016 break; 14017 } 14018 case 0x34C: // lxvd2x 14019 { 14020 IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32; 14021 IRExpr * high, *low; 14022 ULong ea_off = 8; 14023 IRExpr* high_addr; 14024 DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 14025 high = loadBE( Ity_I64, mkexpr( EA ) ); 14026 high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off ) 14027 : mkU32( ea_off ) ); 14028 low = loadBE( Ity_I64, high_addr ); 14029 putVSReg( XT, binop( Iop_64HLtoV128, high, low ) ); 14030 break; 14031 } 14032 case 0x14C: // lxvdsx 14033 { 14034 IRTemp data = newTemp(Ity_I64); 14035 DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 14036 assign( data, loadBE( Ity_I64, mkexpr( EA ) ) ); 14037 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) ); 14038 break; 14039 } 14040 case 0x30C: 14041 { 14042 IRExpr * t3, *t2, *t1, *t0; 14043 UInt ea_off = 0; 14044 IRExpr* irx_addr; 14045 14046 DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 14047 t3 = loadBE( Ity_I32, mkexpr( EA ) ); 14048 ea_off += 4; 14049 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 14050 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 14051 t2 = loadBE( Ity_I32, irx_addr ); 14052 ea_off += 4; 14053 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 14054 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 14055 t1 = loadBE( Ity_I32, irx_addr ); 14056 ea_off += 4; 14057 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 14058 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 14059 t0 = loadBE( Ity_I32, irx_addr ); 14060 putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ), 14061 binop( Iop_32HLto64, t1, t0 ) ) ); 14062 break; 14063 } 14064 default: 14065 vex_printf( "dis_vx_load(ppc)(opc2)\n" ); 14066 return False; 14067 } 14068 return True; 14069 } 14070 14071 /* 14072 * VSX Store Instructions 14073 * NOTE: VSX supports word-aligned storage access. 14074 */ 14075 static Bool 14076 dis_vx_store ( UInt theInstr ) 14077 { 14078 /* XX1-Form */ 14079 UChar opc1 = ifieldOPC( theInstr ); 14080 UChar XS = ifieldRegXS( theInstr ); 14081 UChar rA_addr = ifieldRegA( theInstr ); 14082 UChar rB_addr = ifieldRegB( theInstr ); 14083 IRTemp vS = newTemp( Ity_V128 ); 14084 UInt opc2 = ifieldOPClo10( theInstr ); 14085 14086 IRType ty = mode64 ? Ity_I64 : Ity_I32; 14087 IRTemp EA = newTemp( ty ); 14088 14089 if (opc1 != 0x1F) { 14090 vex_printf( "dis_vx_store(ppc)(instr)\n" ); 14091 return False; 14092 } 14093 14094 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 14095 assign( vS, getVSReg( XS ) ); 14096 14097 switch (opc2) { 14098 case 0x2CC: 14099 { 14100 IRExpr * high64; 14101 DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 14102 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 14103 storeBE( mkexpr( EA ), high64 ); 14104 break; 14105 } 14106 case 0x3CC: 14107 { 14108 IRExpr * high64, *low64; 14109 DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 14110 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 14111 low64 = unop( Iop_V128to64, mkexpr( vS ) ); 14112 storeBE( mkexpr( EA ), high64 ); 14113 storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 ) 14114 : mkU32( 8 ) ), low64 ); 14115 break; 14116 } 14117 case 0x38C: 14118 { 14119 UInt ea_off = 0; 14120 IRExpr* irx_addr; 14121 IRTemp hi64 = newTemp( Ity_I64 ); 14122 IRTemp lo64 = newTemp( Ity_I64 ); 14123 14124 DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 14125 14126 // This instruction supports word-aligned stores, so EA may not be 14127 // quad-word aligned. Therefore, do 4 individual word-size stores. 14128 assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) ); 14129 assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) ); 14130 14131 storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) ); 14132 ea_off += 4; 14133 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 14134 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 14135 storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) ); 14136 ea_off += 4; 14137 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 14138 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 14139 storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) ); 14140 ea_off += 4; 14141 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 14142 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 14143 storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) ); 14144 14145 break; 14146 } 14147 default: 14148 vex_printf( "dis_vx_store(ppc)(opc2)\n" ); 14149 return False; 14150 } 14151 return True; 14152 } 14153 14154 /* 14155 * VSX permute and other miscealleous instructions 14156 */ 14157 static Bool 14158 dis_vx_permute_misc( UInt theInstr, UInt opc2 ) 14159 { 14160 /* XX3-Form */ 14161 UChar opc1 = ifieldOPC( theInstr ); 14162 UChar XT = ifieldRegXT ( theInstr ); 14163 UChar XA = ifieldRegXA ( theInstr ); 14164 UChar XB = ifieldRegXB ( theInstr ); 14165 IRTemp vT = newTemp( Ity_V128 ); 14166 IRTemp vA = newTemp( Ity_V128 ); 14167 IRTemp vB = newTemp( Ity_V128 ); 14168 14169 if (opc1 != 0x3C) { 14170 vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" ); 14171 return False; 14172 } 14173 14174 assign( vA, getVSReg( XA ) ); 14175 assign( vB, getVSReg( XB ) ); 14176 14177 switch (opc2) { 14178 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate) 14179 { 14180 UChar SHW = ifieldSHW ( theInstr ); 14181 IRTemp result = newTemp(Ity_V128); 14182 if ( SHW != 0 ) { 14183 IRTemp hi = newTemp(Ity_V128); 14184 IRTemp lo = newTemp(Ity_V128); 14185 assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) ); 14186 assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) ); 14187 assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) ); 14188 } else 14189 assign ( result, mkexpr(vA) ); 14190 DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW); 14191 putVSReg( XT, mkexpr(result) ); 14192 break; 14193 } 14194 case 0x28: // xpermdi (VSX Permute Doubleword Immediate) 14195 { 14196 UChar DM = ifieldDM ( theInstr ); 14197 IRTemp hi = newTemp(Ity_I64); 14198 IRTemp lo = newTemp(Ity_I64); 14199 14200 if (DM & 0x2) 14201 assign( hi, unop(Iop_V128to64, mkexpr(vA)) ); 14202 else 14203 assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) ); 14204 14205 if (DM & 0x1) 14206 assign( lo, unop(Iop_V128to64, mkexpr(vB)) ); 14207 else 14208 assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) ); 14209 14210 assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) ); 14211 14212 DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM); 14213 putVSReg( XT, mkexpr( vT ) ); 14214 break; 14215 } 14216 case 0x48: // xxmrghw (VSX Merge High Word) 14217 case 0xc8: // xxmrglw (VSX Merge Low Word) 14218 { 14219 char type = (opc2 == 0x48) ? 'h' : 'l'; 14220 IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64; 14221 IRTemp a64 = newTemp(Ity_I64); 14222 IRTemp ahi32 = newTemp(Ity_I32); 14223 IRTemp alo32 = newTemp(Ity_I32); 14224 IRTemp b64 = newTemp(Ity_I64); 14225 IRTemp bhi32 = newTemp(Ity_I32); 14226 IRTemp blo32 = newTemp(Ity_I32); 14227 14228 assign( a64, unop(word_op, mkexpr(vA)) ); 14229 assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) ); 14230 assign( alo32, unop(Iop_64to32, mkexpr(a64)) ); 14231 14232 assign( b64, unop(word_op, mkexpr(vB)) ); 14233 assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) ); 14234 assign( blo32, unop(Iop_64to32, mkexpr(b64)) ); 14235 14236 assign( vT, binop(Iop_64HLtoV128, 14237 binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)), 14238 binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) ); 14239 14240 DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB); 14241 putVSReg( XT, mkexpr( vT ) ); 14242 break; 14243 } 14244 case 0x018: // xxsel (VSX Select) 14245 { 14246 UChar XC = ifieldRegXC(theInstr); 14247 IRTemp vC = newTemp( Ity_V128 ); 14248 assign( vC, getVSReg( XC ) ); 14249 DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC); 14250 /* vD = (vA & ~vC) | (vB & vC) */ 14251 putVSReg( XT, binop(Iop_OrV128, 14252 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 14253 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 14254 break; 14255 } 14256 case 0x148: // xxspltw (VSX Splat Word) 14257 { 14258 UChar UIM = ifieldRegA(theInstr) & 3; 14259 UChar sh_uim = (3 - (UIM)) * 32; 14260 DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM); 14261 putVSReg( XT, 14262 unop( Iop_Dup32x4, 14263 unop( Iop_V128to32, 14264 binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) ); 14265 break; 14266 } 14267 14268 default: 14269 vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" ); 14270 return False; 14271 } 14272 return True; 14273 } 14274 14275 /* 14276 AltiVec Load Instructions 14277 */ 14278 static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr ) 14279 { 14280 /* X-Form */ 14281 UChar opc1 = ifieldOPC(theInstr); 14282 UChar vD_addr = ifieldRegDS(theInstr); 14283 UChar rA_addr = ifieldRegA(theInstr); 14284 UChar rB_addr = ifieldRegB(theInstr); 14285 UInt opc2 = ifieldOPClo10(theInstr); 14286 UChar b0 = ifieldBIT0(theInstr); 14287 14288 IRType ty = mode64 ? Ity_I64 : Ity_I32; 14289 IRTemp EA = newTemp(ty); 14290 IRTemp EA_align16 = newTemp(ty); 14291 14292 if (opc1 != 0x1F || b0 != 0) { 14293 vex_printf("dis_av_load(ppc)(instr)\n"); 14294 return False; 14295 } 14296 14297 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 14298 assign( EA_align16, addr_align( mkexpr(EA), 16 ) ); 14299 14300 switch (opc2) { 14301 14302 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123) 14303 IRDirty* d; 14304 UInt vD_off = vectorGuestRegOffset(vD_addr); 14305 IRExpr** args = mkIRExprVec_3( 14306 mkU32(vD_off), 14307 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 14308 mkU32(0xF)), 14309 mkU32(0)/*left*/ ); 14310 if (!mode64) { 14311 d = unsafeIRDirty_0_N ( 14312 0/*regparms*/, 14313 "ppc32g_dirtyhelper_LVS", 14314 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 14315 args ); 14316 } else { 14317 d = unsafeIRDirty_0_N ( 14318 0/*regparms*/, 14319 "ppc64g_dirtyhelper_LVS", 14320 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 14321 args ); 14322 } 14323 DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 14324 /* declare guest state effects */ 14325 d->needsBBP = True; 14326 d->nFxState = 1; 14327 vex_bzero(&d->fxState, sizeof(d->fxState)); 14328 d->fxState[0].fx = Ifx_Write; 14329 d->fxState[0].offset = vD_off; 14330 d->fxState[0].size = sizeof(U128); 14331 14332 /* execute the dirty call, side-effecting guest state */ 14333 stmt( IRStmt_Dirty(d) ); 14334 break; 14335 } 14336 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125) 14337 IRDirty* d; 14338 UInt vD_off = vectorGuestRegOffset(vD_addr); 14339 IRExpr** args = mkIRExprVec_3( 14340 mkU32(vD_off), 14341 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 14342 mkU32(0xF)), 14343 mkU32(1)/*right*/ ); 14344 if (!mode64) { 14345 d = unsafeIRDirty_0_N ( 14346 0/*regparms*/, 14347 "ppc32g_dirtyhelper_LVS", 14348 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 14349 args ); 14350 } else { 14351 d = unsafeIRDirty_0_N ( 14352 0/*regparms*/, 14353 "ppc64g_dirtyhelper_LVS", 14354 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 14355 args ); 14356 } 14357 DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 14358 /* declare guest state effects */ 14359 d->needsBBP = True; 14360 d->nFxState = 1; 14361 vex_bzero(&d->fxState, sizeof(d->fxState)); 14362 d->fxState[0].fx = Ifx_Write; 14363 d->fxState[0].offset = vD_off; 14364 d->fxState[0].size = sizeof(U128); 14365 14366 /* execute the dirty call, side-effecting guest state */ 14367 stmt( IRStmt_Dirty(d) ); 14368 break; 14369 } 14370 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119) 14371 DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 14372 /* loads addressed byte into vector[EA[0:3] 14373 since all other destination bytes are undefined, 14374 can simply load entire vector from 16-aligned EA */ 14375 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 14376 break; 14377 14378 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121) 14379 DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 14380 /* see note for lvebx */ 14381 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 14382 break; 14383 14384 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122) 14385 DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 14386 /* see note for lvebx */ 14387 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 14388 break; 14389 14390 case 0x067: // lvx (Load Vector Indexed, AV p127) 14391 DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 14392 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 14393 break; 14394 14395 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128) 14396 DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 14397 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 14398 break; 14399 14400 default: 14401 vex_printf("dis_av_load(ppc)(opc2)\n"); 14402 return False; 14403 } 14404 return True; 14405 } 14406 14407 /* 14408 AltiVec Store Instructions 14409 */ 14410 static Bool dis_av_store ( UInt theInstr ) 14411 { 14412 /* X-Form */ 14413 UChar opc1 = ifieldOPC(theInstr); 14414 UChar vS_addr = ifieldRegDS(theInstr); 14415 UChar rA_addr = ifieldRegA(theInstr); 14416 UChar rB_addr = ifieldRegB(theInstr); 14417 UInt opc2 = ifieldOPClo10(theInstr); 14418 UChar b0 = ifieldBIT0(theInstr); 14419 14420 IRType ty = mode64 ? Ity_I64 : Ity_I32; 14421 IRTemp EA = newTemp(ty); 14422 IRTemp addr_aligned = newTemp(ty); 14423 IRTemp vS = newTemp(Ity_V128); 14424 IRTemp eb = newTemp(Ity_I8); 14425 IRTemp idx = newTemp(Ity_I8); 14426 14427 if (opc1 != 0x1F || b0 != 0) { 14428 vex_printf("dis_av_store(ppc)(instr)\n"); 14429 return False; 14430 } 14431 14432 assign( vS, getVReg(vS_addr)); 14433 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 14434 14435 switch (opc2) { 14436 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131) 14437 DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 14438 assign( eb, binop(Iop_And8, mkU8(0xF), 14439 unop(Iop_32to8, 14440 mkNarrowTo32(ty, mkexpr(EA)) )) ); 14441 assign( idx, binop(Iop_Shl8, 14442 binop(Iop_Sub8, mkU8(15), mkexpr(eb)), 14443 mkU8(3)) ); 14444 storeBE( mkexpr(EA), 14445 unop(Iop_32to8, unop(Iop_V128to32, 14446 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 14447 break; 14448 } 14449 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132) 14450 DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 14451 assign( addr_aligned, addr_align(mkexpr(EA), 2) ); 14452 assign( eb, binop(Iop_And8, mkU8(0xF), 14453 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 14454 assign( idx, binop(Iop_Shl8, 14455 binop(Iop_Sub8, mkU8(14), mkexpr(eb)), 14456 mkU8(3)) ); 14457 storeBE( mkexpr(addr_aligned), 14458 unop(Iop_32to16, unop(Iop_V128to32, 14459 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 14460 break; 14461 } 14462 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133) 14463 DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 14464 assign( addr_aligned, addr_align(mkexpr(EA), 4) ); 14465 assign( eb, binop(Iop_And8, mkU8(0xF), 14466 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 14467 assign( idx, binop(Iop_Shl8, 14468 binop(Iop_Sub8, mkU8(12), mkexpr(eb)), 14469 mkU8(3)) ); 14470 storeBE( mkexpr(addr_aligned), 14471 unop(Iop_V128to32, 14472 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) ); 14473 break; 14474 } 14475 14476 case 0x0E7: // stvx (Store Vector Indexed, AV p134) 14477 DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 14478 storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 14479 break; 14480 14481 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135) 14482 DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 14483 storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 14484 break; 14485 14486 default: 14487 vex_printf("dis_av_store(ppc)(opc2)\n"); 14488 return False; 14489 } 14490 return True; 14491 } 14492 14493 /* 14494 AltiVec Arithmetic Instructions 14495 */ 14496 static Bool dis_av_arith ( UInt theInstr ) 14497 { 14498 /* VX-Form */ 14499 UChar opc1 = ifieldOPC(theInstr); 14500 UChar vD_addr = ifieldRegDS(theInstr); 14501 UChar vA_addr = ifieldRegA(theInstr); 14502 UChar vB_addr = ifieldRegB(theInstr); 14503 UInt opc2 = IFIELD( theInstr, 0, 11 ); 14504 14505 IRTemp vA = newTemp(Ity_V128); 14506 IRTemp vB = newTemp(Ity_V128); 14507 IRTemp z3 = newTemp(Ity_I64); 14508 IRTemp z2 = newTemp(Ity_I64); 14509 IRTemp z1 = newTemp(Ity_I64); 14510 IRTemp z0 = newTemp(Ity_I64); 14511 IRTemp aEvn, aOdd; 14512 IRTemp a15, a14, a13, a12, a11, a10, a9, a8; 14513 IRTemp a7, a6, a5, a4, a3, a2, a1, a0; 14514 IRTemp b3, b2, b1, b0; 14515 14516 aEvn = aOdd = IRTemp_INVALID; 14517 a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID; 14518 a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID; 14519 b3 = b2 = b1 = b0 = IRTemp_INVALID; 14520 14521 assign( vA, getVReg(vA_addr)); 14522 assign( vB, getVReg(vB_addr)); 14523 14524 if (opc1 != 0x4) { 14525 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n"); 14526 return False; 14527 } 14528 14529 switch (opc2) { 14530 /* Add */ 14531 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136) 14532 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14533 /* unsigned_ov(x+y) = (y >u not(x)) */ 14534 putVReg( vD_addr, binop(Iop_ShrN32x4, 14535 binop(Iop_CmpGT32Ux4, mkexpr(vB), 14536 unop(Iop_NotV128, mkexpr(vA))), 14537 mkU8(31)) ); 14538 break; 14539 } 14540 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141) 14541 DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14542 putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) ); 14543 break; 14544 14545 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143) 14546 DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14547 putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) ); 14548 break; 14549 14550 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145) 14551 DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14552 putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) ); 14553 break; 14554 14555 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142) 14556 DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14557 putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) ); 14558 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16 14559 break; 14560 14561 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144) 14562 DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14563 putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) ); 14564 // TODO: set VSCR[SAT] 14565 break; 14566 14567 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146) 14568 DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14569 putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) ); 14570 // TODO: set VSCR[SAT] 14571 break; 14572 14573 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138) 14574 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14575 putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) ); 14576 // TODO: set VSCR[SAT] 14577 break; 14578 14579 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139) 14580 DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14581 putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) ); 14582 // TODO: set VSCR[SAT] 14583 break; 14584 14585 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140) 14586 DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14587 putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) ); 14588 // TODO: set VSCR[SAT] 14589 break; 14590 14591 14592 /* Subtract */ 14593 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260) 14594 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14595 /* unsigned_ov(x-y) = (y >u x) */ 14596 putVReg( vD_addr, binop(Iop_ShrN32x4, 14597 unop(Iop_NotV128, 14598 binop(Iop_CmpGT32Ux4, mkexpr(vB), 14599 mkexpr(vA))), 14600 mkU8(31)) ); 14601 break; 14602 } 14603 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265) 14604 DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14605 putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) ); 14606 break; 14607 14608 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267) 14609 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14610 putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) ); 14611 break; 14612 14613 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269) 14614 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14615 putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) ); 14616 break; 14617 14618 case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266) 14619 DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14620 putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) ); 14621 // TODO: set VSCR[SAT] 14622 break; 14623 14624 case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268) 14625 DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14626 putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) ); 14627 // TODO: set VSCR[SAT] 14628 break; 14629 14630 case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270) 14631 DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14632 putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) ); 14633 // TODO: set VSCR[SAT] 14634 break; 14635 14636 case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262) 14637 DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14638 putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) ); 14639 // TODO: set VSCR[SAT] 14640 break; 14641 14642 case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263) 14643 DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14644 putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) ); 14645 // TODO: set VSCR[SAT] 14646 break; 14647 14648 case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264) 14649 DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14650 putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) ); 14651 // TODO: set VSCR[SAT] 14652 break; 14653 14654 14655 /* Maximum */ 14656 case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182) 14657 DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14658 putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) ); 14659 break; 14660 14661 case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183) 14662 DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14663 putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) ); 14664 break; 14665 14666 case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184) 14667 DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14668 putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) ); 14669 break; 14670 14671 case 0x102: // vmaxsb (Maximum Signed Byte, AV p179) 14672 DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14673 putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) ); 14674 break; 14675 14676 case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180) 14677 DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14678 putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) ); 14679 break; 14680 14681 case 0x182: // vmaxsw (Maximum Signed Word, AV p181) 14682 DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14683 putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) ); 14684 break; 14685 14686 14687 /* Minimum */ 14688 case 0x202: // vminub (Minimum Unsigned Byte, AV p191) 14689 DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14690 putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) ); 14691 break; 14692 14693 case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192) 14694 DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14695 putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) ); 14696 break; 14697 14698 case 0x282: // vminuw (Minimum Unsigned Word, AV p193) 14699 DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14700 putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) ); 14701 break; 14702 14703 case 0x302: // vminsb (Minimum Signed Byte, AV p188) 14704 DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14705 putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) ); 14706 break; 14707 14708 case 0x342: // vminsh (Minimum Signed Half Word, AV p189) 14709 DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14710 putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) ); 14711 break; 14712 14713 case 0x382: // vminsw (Minimum Signed Word, AV p190) 14714 DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14715 putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) ); 14716 break; 14717 14718 14719 /* Average */ 14720 case 0x402: // vavgub (Average Unsigned Byte, AV p152) 14721 DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14722 putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) ); 14723 break; 14724 14725 case 0x442: // vavguh (Average Unsigned Half Word, AV p153) 14726 DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14727 putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) ); 14728 break; 14729 14730 case 0x482: // vavguw (Average Unsigned Word, AV p154) 14731 DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14732 putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) ); 14733 break; 14734 14735 case 0x502: // vavgsb (Average Signed Byte, AV p149) 14736 DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14737 putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) ); 14738 break; 14739 14740 case 0x542: // vavgsh (Average Signed Half Word, AV p150) 14741 DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14742 putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) ); 14743 break; 14744 14745 case 0x582: // vavgsw (Average Signed Word, AV p151) 14746 DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14747 putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) ); 14748 break; 14749 14750 14751 /* Multiply */ 14752 case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213) 14753 DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14754 putVReg( vD_addr, 14755 binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB))); 14756 break; 14757 14758 case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214) 14759 DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14760 putVReg( vD_addr, 14761 binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB))); 14762 break; 14763 14764 case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211) 14765 DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14766 putVReg( vD_addr, 14767 binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB))); 14768 break; 14769 14770 case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212) 14771 DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14772 putVReg( vD_addr, 14773 binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB))); 14774 break; 14775 14776 case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209) 14777 DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14778 putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 14779 break; 14780 14781 case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210) 14782 DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14783 putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 14784 break; 14785 14786 case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207) 14787 DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14788 putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) )); 14789 break; 14790 14791 case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208) 14792 DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14793 putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 14794 break; 14795 14796 14797 /* Sum Across Partial */ 14798 case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275) 14799 IRTemp aEE, aEO, aOE, aOO; 14800 aEE = aEO = aOE = aOO = IRTemp_INVALID; 14801 DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14802 14803 /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */ 14804 expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 14805 expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 14806 expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 14807 14808 /* break V128 to 4xI32's, zero-extending to I64's */ 14809 breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 14810 breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 14811 breakV128to4x64U( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 14812 breakV128to4x64U( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 14813 breakV128to4x64U( mkexpr(vB), &b3, &b2, &b1, &b0 ); 14814 14815 /* add lanes */ 14816 assign( z3, binop(Iop_Add64, mkexpr(b3), 14817 binop(Iop_Add64, 14818 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 14819 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 14820 assign( z2, binop(Iop_Add64, mkexpr(b2), 14821 binop(Iop_Add64, 14822 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 14823 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 14824 assign( z1, binop(Iop_Add64, mkexpr(b1), 14825 binop(Iop_Add64, 14826 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 14827 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 14828 assign( z0, binop(Iop_Add64, mkexpr(b0), 14829 binop(Iop_Add64, 14830 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 14831 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 14832 14833 /* saturate-narrow to 32bit, and combine to V128 */ 14834 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 14835 mkexpr(z1), mkexpr(z0)) ); 14836 break; 14837 } 14838 case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273) 14839 IRTemp aEE, aEO, aOE, aOO; 14840 aEE = aEO = aOE = aOO = IRTemp_INVALID; 14841 DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14842 14843 /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */ 14844 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 14845 expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 14846 expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 14847 14848 /* break V128 to 4xI32's, sign-extending to I64's */ 14849 breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 14850 breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 14851 breakV128to4x64S( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 14852 breakV128to4x64S( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 14853 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 14854 14855 /* add lanes */ 14856 assign( z3, binop(Iop_Add64, mkexpr(b3), 14857 binop(Iop_Add64, 14858 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 14859 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 14860 assign( z2, binop(Iop_Add64, mkexpr(b2), 14861 binop(Iop_Add64, 14862 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 14863 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 14864 assign( z1, binop(Iop_Add64, mkexpr(b1), 14865 binop(Iop_Add64, 14866 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 14867 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 14868 assign( z0, binop(Iop_Add64, mkexpr(b0), 14869 binop(Iop_Add64, 14870 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 14871 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 14872 14873 /* saturate-narrow to 32bit, and combine to V128 */ 14874 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 14875 mkexpr(z1), mkexpr(z0)) ); 14876 break; 14877 } 14878 case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274) 14879 DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14880 14881 /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */ 14882 expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...) 14883 14884 /* break V128 to 4xI32's, sign-extending to I64's */ 14885 breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 ); 14886 breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 ); 14887 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 14888 14889 /* add lanes */ 14890 assign( z3, binop(Iop_Add64, mkexpr(b3), 14891 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)))); 14892 assign( z2, binop(Iop_Add64, mkexpr(b2), 14893 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))); 14894 assign( z1, binop(Iop_Add64, mkexpr(b1), 14895 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)))); 14896 assign( z0, binop(Iop_Add64, mkexpr(b0), 14897 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))); 14898 14899 /* saturate-narrow to 32bit, and combine to V128 */ 14900 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 14901 mkexpr(z1), mkexpr(z0)) ); 14902 break; 14903 } 14904 case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272) 14905 DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14906 14907 /* break V128 to 4xI32's, sign-extending to I64's */ 14908 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 14909 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 14910 14911 /* add lanes */ 14912 assign( z2, binop(Iop_Add64, mkexpr(b2), 14913 binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) ); 14914 assign( z0, binop(Iop_Add64, mkexpr(b0), 14915 binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) ); 14916 14917 /* saturate-narrow to 32bit, and combine to V128 */ 14918 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2), 14919 mkU64(0), mkexpr(z0)) ); 14920 break; 14921 } 14922 case 0x788: { // vsumsws (Sum SW Saturate, AV p271) 14923 DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14924 14925 /* break V128 to 4xI32's, sign-extending to I64's */ 14926 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 14927 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 14928 14929 /* add lanes */ 14930 assign( z0, binop(Iop_Add64, mkexpr(b0), 14931 binop(Iop_Add64, 14932 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 14933 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 14934 14935 /* saturate-narrow to 32bit, and combine to V128 */ 14936 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0), 14937 mkU64(0), mkexpr(z0)) ); 14938 break; 14939 } 14940 default: 14941 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2); 14942 return False; 14943 } 14944 return True; 14945 } 14946 14947 /* 14948 AltiVec Logic Instructions 14949 */ 14950 static Bool dis_av_logic ( UInt theInstr ) 14951 { 14952 /* VX-Form */ 14953 UChar opc1 = ifieldOPC(theInstr); 14954 UChar vD_addr = ifieldRegDS(theInstr); 14955 UChar vA_addr = ifieldRegA(theInstr); 14956 UChar vB_addr = ifieldRegB(theInstr); 14957 UInt opc2 = IFIELD( theInstr, 0, 11 ); 14958 14959 IRTemp vA = newTemp(Ity_V128); 14960 IRTemp vB = newTemp(Ity_V128); 14961 assign( vA, getVReg(vA_addr)); 14962 assign( vB, getVReg(vB_addr)); 14963 14964 if (opc1 != 0x4) { 14965 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n"); 14966 return False; 14967 } 14968 14969 switch (opc2) { 14970 case 0x404: // vand (And, AV p147) 14971 DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14972 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) ); 14973 break; 14974 14975 case 0x444: // vandc (And, AV p148) 14976 DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14977 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), 14978 unop(Iop_NotV128, mkexpr(vB))) ); 14979 break; 14980 14981 case 0x484: // vor (Or, AV p217) 14982 DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14983 putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) ); 14984 break; 14985 14986 case 0x4C4: // vxor (Xor, AV p282) 14987 DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14988 putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) ); 14989 break; 14990 14991 case 0x504: // vnor (Nor, AV p216) 14992 DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 14993 putVReg( vD_addr, 14994 unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) ); 14995 break; 14996 14997 default: 14998 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2); 14999 return False; 15000 } 15001 return True; 15002 } 15003 15004 /* 15005 AltiVec Compare Instructions 15006 */ 15007 static Bool dis_av_cmp ( UInt theInstr ) 15008 { 15009 /* VXR-Form */ 15010 UChar opc1 = ifieldOPC(theInstr); 15011 UChar vD_addr = ifieldRegDS(theInstr); 15012 UChar vA_addr = ifieldRegA(theInstr); 15013 UChar vB_addr = ifieldRegB(theInstr); 15014 UChar flag_rC = ifieldBIT10(theInstr); 15015 UInt opc2 = IFIELD( theInstr, 0, 10 ); 15016 15017 IRTemp vA = newTemp(Ity_V128); 15018 IRTemp vB = newTemp(Ity_V128); 15019 IRTemp vD = newTemp(Ity_V128); 15020 assign( vA, getVReg(vA_addr)); 15021 assign( vB, getVReg(vB_addr)); 15022 15023 if (opc1 != 0x4) { 15024 vex_printf("dis_av_cmp(ppc)(instr)\n"); 15025 return False; 15026 } 15027 15028 switch (opc2) { 15029 case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160) 15030 DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 15031 vD_addr, vA_addr, vB_addr); 15032 assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) ); 15033 break; 15034 15035 case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161) 15036 DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 15037 vD_addr, vA_addr, vB_addr); 15038 assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) ); 15039 break; 15040 15041 case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162) 15042 DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 15043 vD_addr, vA_addr, vB_addr); 15044 assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) ); 15045 break; 15046 15047 case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168) 15048 DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 15049 vD_addr, vA_addr, vB_addr); 15050 assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) ); 15051 break; 15052 15053 case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169) 15054 DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 15055 vD_addr, vA_addr, vB_addr); 15056 assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) ); 15057 break; 15058 15059 case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170) 15060 DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 15061 vD_addr, vA_addr, vB_addr); 15062 assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) ); 15063 break; 15064 15065 case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165) 15066 DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 15067 vD_addr, vA_addr, vB_addr); 15068 assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) ); 15069 break; 15070 15071 case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166) 15072 DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 15073 vD_addr, vA_addr, vB_addr); 15074 assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) ); 15075 break; 15076 15077 case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167) 15078 DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 15079 vD_addr, vA_addr, vB_addr); 15080 assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) ); 15081 break; 15082 15083 default: 15084 vex_printf("dis_av_cmp(ppc)(opc2)\n"); 15085 return False; 15086 } 15087 15088 putVReg( vD_addr, mkexpr(vD) ); 15089 15090 if (flag_rC) { 15091 set_AV_CR6( mkexpr(vD), True ); 15092 } 15093 return True; 15094 } 15095 15096 /* 15097 AltiVec Multiply-Sum Instructions 15098 */ 15099 static Bool dis_av_multarith ( UInt theInstr ) 15100 { 15101 /* VA-Form */ 15102 UChar opc1 = ifieldOPC(theInstr); 15103 UChar vD_addr = ifieldRegDS(theInstr); 15104 UChar vA_addr = ifieldRegA(theInstr); 15105 UChar vB_addr = ifieldRegB(theInstr); 15106 UChar vC_addr = ifieldRegC(theInstr); 15107 UChar opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 15108 15109 IRTemp vA = newTemp(Ity_V128); 15110 IRTemp vB = newTemp(Ity_V128); 15111 IRTemp vC = newTemp(Ity_V128); 15112 IRTemp zeros = newTemp(Ity_V128); 15113 IRTemp aLo = newTemp(Ity_V128); 15114 IRTemp bLo = newTemp(Ity_V128); 15115 IRTemp cLo = newTemp(Ity_V128); 15116 IRTemp zLo = newTemp(Ity_V128); 15117 IRTemp aHi = newTemp(Ity_V128); 15118 IRTemp bHi = newTemp(Ity_V128); 15119 IRTemp cHi = newTemp(Ity_V128); 15120 IRTemp zHi = newTemp(Ity_V128); 15121 IRTemp abEvn = newTemp(Ity_V128); 15122 IRTemp abOdd = newTemp(Ity_V128); 15123 IRTemp z3 = newTemp(Ity_I64); 15124 IRTemp z2 = newTemp(Ity_I64); 15125 IRTemp z1 = newTemp(Ity_I64); 15126 IRTemp z0 = newTemp(Ity_I64); 15127 IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0; 15128 IRTemp c3, c2, c1, c0; 15129 15130 ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID; 15131 c3 = c2 = c1 = c0 = IRTemp_INVALID; 15132 15133 assign( vA, getVReg(vA_addr)); 15134 assign( vB, getVReg(vB_addr)); 15135 assign( vC, getVReg(vC_addr)); 15136 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 15137 15138 if (opc1 != 0x4) { 15139 vex_printf("dis_av_multarith(ppc)(instr)\n"); 15140 return False; 15141 } 15142 15143 switch (opc2) { 15144 /* Multiply-Add */ 15145 case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185) 15146 IRTemp cSigns = newTemp(Ity_V128); 15147 DIP("vmhaddshs v%d,v%d,v%d,v%d\n", 15148 vD_addr, vA_addr, vB_addr, vC_addr); 15149 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC))); 15150 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 15151 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 15152 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 15153 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 15154 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 15155 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 15156 15157 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 15158 binop(Iop_SarN32x4, 15159 binop(Iop_MullEven16Sx8, 15160 mkexpr(aLo), mkexpr(bLo)), 15161 mkU8(15))) ); 15162 15163 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 15164 binop(Iop_SarN32x4, 15165 binop(Iop_MullEven16Sx8, 15166 mkexpr(aHi), mkexpr(bHi)), 15167 mkU8(15))) ); 15168 15169 putVReg( vD_addr, 15170 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 15171 break; 15172 } 15173 case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186) 15174 IRTemp zKonst = newTemp(Ity_V128); 15175 IRTemp cSigns = newTemp(Ity_V128); 15176 DIP("vmhraddshs v%d,v%d,v%d,v%d\n", 15177 vD_addr, vA_addr, vB_addr, vC_addr); 15178 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) ); 15179 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 15180 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 15181 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 15182 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 15183 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 15184 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 15185 15186 /* shifting our const avoids store/load version of Dup */ 15187 assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)), 15188 mkU8(14)) ); 15189 15190 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 15191 binop(Iop_SarN32x4, 15192 binop(Iop_Add32x4, mkexpr(zKonst), 15193 binop(Iop_MullEven16Sx8, 15194 mkexpr(aLo), mkexpr(bLo))), 15195 mkU8(15))) ); 15196 15197 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 15198 binop(Iop_SarN32x4, 15199 binop(Iop_Add32x4, mkexpr(zKonst), 15200 binop(Iop_MullEven16Sx8, 15201 mkexpr(aHi), mkexpr(bHi))), 15202 mkU8(15))) ); 15203 15204 putVReg( vD_addr, 15205 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 15206 break; 15207 } 15208 case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194) 15209 DIP("vmladduhm v%d,v%d,v%d,v%d\n", 15210 vD_addr, vA_addr, vB_addr, vC_addr); 15211 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 15212 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 15213 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC))); 15214 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 15215 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 15216 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC))); 15217 assign(zLo, binop(Iop_Add32x4, 15218 binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)), 15219 mkexpr(cLo)) ); 15220 assign(zHi, binop(Iop_Add32x4, 15221 binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)), 15222 mkexpr(cHi))); 15223 putVReg( vD_addr, 15224 binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) ); 15225 break; 15226 } 15227 15228 15229 /* Multiply-Sum */ 15230 case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204) 15231 IRTemp abEE, abEO, abOE, abOO; 15232 abEE = abEO = abOE = abOO = IRTemp_INVALID; 15233 DIP("vmsumubm v%d,v%d,v%d,v%d\n", 15234 vD_addr, vA_addr, vB_addr, vC_addr); 15235 15236 /* multiply vA,vB (unsigned, widening) */ 15237 assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 15238 assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) ); 15239 15240 /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */ 15241 expand16Ux8( mkexpr(abEvn), &abEE, &abEO ); 15242 expand16Ux8( mkexpr(abOdd), &abOE, &abOO ); 15243 15244 putVReg( vD_addr, 15245 binop(Iop_Add32x4, mkexpr(vC), 15246 binop(Iop_Add32x4, 15247 binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)), 15248 binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) ); 15249 break; 15250 } 15251 case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201) 15252 IRTemp aEvn, aOdd, bEvn, bOdd; 15253 IRTemp abEE = newTemp(Ity_V128); 15254 IRTemp abEO = newTemp(Ity_V128); 15255 IRTemp abOE = newTemp(Ity_V128); 15256 IRTemp abOO = newTemp(Ity_V128); 15257 aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID; 15258 DIP("vmsummbm v%d,v%d,v%d,v%d\n", 15259 vD_addr, vA_addr, vB_addr, vC_addr); 15260 15261 /* sign-extend vA, zero-extend vB, for mixed-sign multiply 15262 (separating out adjacent lanes to different vectors) */ 15263 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); 15264 expand8Ux16( mkexpr(vB), &bEvn, &bOdd ); 15265 15266 /* multiply vA, vB, again separating adjacent lanes */ 15267 assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) )); 15268 assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) ); 15269 assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) )); 15270 assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) ); 15271 15272 /* add results together, + vC */ 15273 putVReg( vD_addr, 15274 binop(Iop_QAdd32Sx4, mkexpr(vC), 15275 binop(Iop_QAdd32Sx4, 15276 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)), 15277 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) ); 15278 break; 15279 } 15280 case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205) 15281 DIP("vmsumuhm v%d,v%d,v%d,v%d\n", 15282 vD_addr, vA_addr, vB_addr, vC_addr); 15283 assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 15284 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 15285 putVReg( vD_addr, 15286 binop(Iop_Add32x4, mkexpr(vC), 15287 binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) ); 15288 break; 15289 } 15290 case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206) 15291 DIP("vmsumuhs v%d,v%d,v%d,v%d\n", 15292 vD_addr, vA_addr, vB_addr, vC_addr); 15293 /* widening multiply, separating lanes */ 15294 assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) )); 15295 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 15296 15297 /* break V128 to 4xI32's, zero-extending to I64's */ 15298 breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 15299 breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 15300 breakV128to4x64U( mkexpr(vC), &c3, &c2, &c1, &c0 ); 15301 15302 /* add lanes */ 15303 assign( z3, binop(Iop_Add64, mkexpr(c3), 15304 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 15305 assign( z2, binop(Iop_Add64, mkexpr(c2), 15306 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 15307 assign( z1, binop(Iop_Add64, mkexpr(c1), 15308 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 15309 assign( z0, binop(Iop_Add64, mkexpr(c0), 15310 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 15311 15312 /* saturate-narrow to 32bit, and combine to V128 */ 15313 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 15314 mkexpr(z1), mkexpr(z0)) ); 15315 15316 break; 15317 } 15318 case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202) 15319 DIP("vmsumshm v%d,v%d,v%d,v%d\n", 15320 vD_addr, vA_addr, vB_addr, vC_addr); 15321 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 15322 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 15323 putVReg( vD_addr, 15324 binop(Iop_Add32x4, mkexpr(vC), 15325 binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) ); 15326 break; 15327 } 15328 case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203) 15329 DIP("vmsumshs v%d,v%d,v%d,v%d\n", 15330 vD_addr, vA_addr, vB_addr, vC_addr); 15331 /* widening multiply, separating lanes */ 15332 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 15333 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 15334 15335 /* break V128 to 4xI32's, sign-extending to I64's */ 15336 breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 15337 breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 15338 breakV128to4x64S( mkexpr(vC), &c3, &c2, &c1, &c0 ); 15339 15340 /* add lanes */ 15341 assign( z3, binop(Iop_Add64, mkexpr(c3), 15342 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 15343 assign( z2, binop(Iop_Add64, mkexpr(c2), 15344 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 15345 assign( z1, binop(Iop_Add64, mkexpr(c1), 15346 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 15347 assign( z0, binop(Iop_Add64, mkexpr(c0), 15348 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 15349 15350 /* saturate-narrow to 32bit, and combine to V128 */ 15351 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 15352 mkexpr(z1), mkexpr(z0)) ); 15353 break; 15354 } 15355 default: 15356 vex_printf("dis_av_multarith(ppc)(opc2)\n"); 15357 return False; 15358 } 15359 return True; 15360 } 15361 15362 /* 15363 AltiVec Shift/Rotate Instructions 15364 */ 15365 static Bool dis_av_shift ( UInt theInstr ) 15366 { 15367 /* VX-Form */ 15368 UChar opc1 = ifieldOPC(theInstr); 15369 UChar vD_addr = ifieldRegDS(theInstr); 15370 UChar vA_addr = ifieldRegA(theInstr); 15371 UChar vB_addr = ifieldRegB(theInstr); 15372 UInt opc2 = IFIELD( theInstr, 0, 11 ); 15373 15374 IRTemp vA = newTemp(Ity_V128); 15375 IRTemp vB = newTemp(Ity_V128); 15376 assign( vA, getVReg(vA_addr)); 15377 assign( vB, getVReg(vB_addr)); 15378 15379 if (opc1 != 0x4){ 15380 vex_printf("dis_av_shift(ppc)(instr)\n"); 15381 return False; 15382 } 15383 15384 switch (opc2) { 15385 /* Rotate */ 15386 case 0x004: // vrlb (Rotate Left Integer B, AV p234) 15387 DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15388 putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) ); 15389 break; 15390 15391 case 0x044: // vrlh (Rotate Left Integer HW, AV p235) 15392 DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15393 putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) ); 15394 break; 15395 15396 case 0x084: // vrlw (Rotate Left Integer W, AV p236) 15397 DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15398 putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) ); 15399 break; 15400 15401 15402 /* Shift Left */ 15403 case 0x104: // vslb (Shift Left Integer B, AV p240) 15404 DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15405 putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) ); 15406 break; 15407 15408 case 0x144: // vslh (Shift Left Integer HW, AV p242) 15409 DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15410 putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) ); 15411 break; 15412 15413 case 0x184: // vslw (Shift Left Integer W, AV p244) 15414 DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15415 putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) ); 15416 break; 15417 15418 case 0x1C4: { // vsl (Shift Left, AV p239) 15419 IRTemp sh = newTemp(Ity_I8); 15420 DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15421 assign( sh, binop(Iop_And8, mkU8(0x7), 15422 unop(Iop_32to8, 15423 unop(Iop_V128to32, mkexpr(vB)))) ); 15424 putVReg( vD_addr, 15425 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 15426 break; 15427 } 15428 case 0x40C: { // vslo (Shift Left by Octet, AV p243) 15429 IRTemp sh = newTemp(Ity_I8); 15430 DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15431 assign( sh, binop(Iop_And8, mkU8(0x78), 15432 unop(Iop_32to8, 15433 unop(Iop_V128to32, mkexpr(vB)))) ); 15434 putVReg( vD_addr, 15435 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 15436 break; 15437 } 15438 15439 15440 /* Shift Right */ 15441 case 0x204: // vsrb (Shift Right B, AV p256) 15442 DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15443 putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) ); 15444 break; 15445 15446 case 0x244: // vsrh (Shift Right HW, AV p257) 15447 DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15448 putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) ); 15449 break; 15450 15451 case 0x284: // vsrw (Shift Right W, AV p259) 15452 DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15453 putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) ); 15454 break; 15455 15456 case 0x2C4: { // vsr (Shift Right, AV p251) 15457 IRTemp sh = newTemp(Ity_I8); 15458 DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15459 assign( sh, binop(Iop_And8, mkU8(0x7), 15460 unop(Iop_32to8, 15461 unop(Iop_V128to32, mkexpr(vB)))) ); 15462 putVReg( vD_addr, 15463 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 15464 break; 15465 } 15466 case 0x304: // vsrab (Shift Right Alg B, AV p253) 15467 DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15468 putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) ); 15469 break; 15470 15471 case 0x344: // vsrah (Shift Right Alg HW, AV p254) 15472 DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15473 putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) ); 15474 break; 15475 15476 case 0x384: // vsraw (Shift Right Alg W, AV p255) 15477 DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15478 putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) ); 15479 break; 15480 15481 case 0x44C: { // vsro (Shift Right by Octet, AV p258) 15482 IRTemp sh = newTemp(Ity_I8); 15483 DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15484 assign( sh, binop(Iop_And8, mkU8(0x78), 15485 unop(Iop_32to8, 15486 unop(Iop_V128to32, mkexpr(vB)))) ); 15487 putVReg( vD_addr, 15488 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 15489 break; 15490 } 15491 15492 default: 15493 vex_printf("dis_av_shift(ppc)(opc2)\n"); 15494 return False; 15495 } 15496 return True; 15497 } 15498 15499 /* 15500 AltiVec Permute Instructions 15501 */ 15502 static Bool dis_av_permute ( UInt theInstr ) 15503 { 15504 /* VA-Form, VX-Form */ 15505 UChar opc1 = ifieldOPC(theInstr); 15506 UChar vD_addr = ifieldRegDS(theInstr); 15507 UChar vA_addr = ifieldRegA(theInstr); 15508 UChar UIMM_5 = vA_addr; 15509 UChar vB_addr = ifieldRegB(theInstr); 15510 UChar vC_addr = ifieldRegC(theInstr); 15511 UChar b10 = ifieldBIT10(theInstr); 15512 UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) ); 15513 UInt opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 15514 15515 UChar SIMM_8 = extend_s_5to8(UIMM_5); 15516 15517 IRTemp vA = newTemp(Ity_V128); 15518 IRTemp vB = newTemp(Ity_V128); 15519 IRTemp vC = newTemp(Ity_V128); 15520 assign( vA, getVReg(vA_addr)); 15521 assign( vB, getVReg(vB_addr)); 15522 assign( vC, getVReg(vC_addr)); 15523 15524 if (opc1 != 0x4) { 15525 vex_printf("dis_av_permute(ppc)(instr)\n"); 15526 return False; 15527 } 15528 15529 switch (opc2) { 15530 case 0x2A: // vsel (Conditional Select, AV p238) 15531 DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr); 15532 /* vD = (vA & ~vC) | (vB & vC) */ 15533 putVReg( vD_addr, binop(Iop_OrV128, 15534 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 15535 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 15536 return True; 15537 15538 case 0x2B: { // vperm (Permute, AV p218) 15539 /* limited to two args for IR, so have to play games... */ 15540 IRTemp a_perm = newTemp(Ity_V128); 15541 IRTemp b_perm = newTemp(Ity_V128); 15542 IRTemp mask = newTemp(Ity_V128); 15543 IRTemp vC_andF = newTemp(Ity_V128); 15544 DIP("vperm v%d,v%d,v%d,v%d\n", 15545 vD_addr, vA_addr, vB_addr, vC_addr); 15546 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what 15547 IR specifies, and also to hide irrelevant bits from 15548 memcheck */ 15549 assign( vC_andF, 15550 binop(Iop_AndV128, mkexpr(vC), 15551 unop(Iop_Dup8x16, mkU8(0xF))) ); 15552 assign( a_perm, 15553 binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) ); 15554 assign( b_perm, 15555 binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) ); 15556 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0 15557 assign( mask, binop(Iop_SarN8x16, 15558 binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)), 15559 mkU8(7)) ); 15560 // dst = (a & ~mask) | (b & mask) 15561 putVReg( vD_addr, binop(Iop_OrV128, 15562 binop(Iop_AndV128, mkexpr(a_perm), 15563 unop(Iop_NotV128, mkexpr(mask))), 15564 binop(Iop_AndV128, mkexpr(b_perm), 15565 mkexpr(mask))) ); 15566 return True; 15567 } 15568 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241) 15569 if (b10 != 0) { 15570 vex_printf("dis_av_permute(ppc)(vsldoi)\n"); 15571 return False; 15572 } 15573 DIP("vsldoi v%d,v%d,v%d,%d\n", 15574 vD_addr, vA_addr, vB_addr, SHB_uimm4); 15575 if (SHB_uimm4 == 0) 15576 putVReg( vD_addr, mkexpr(vA) ); 15577 else 15578 putVReg( vD_addr, 15579 binop(Iop_OrV128, 15580 binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)), 15581 binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) ); 15582 return True; 15583 15584 default: 15585 break; // Fall through... 15586 } 15587 15588 opc2 = IFIELD( theInstr, 0, 11 ); 15589 switch (opc2) { 15590 15591 /* Merge */ 15592 case 0x00C: // vmrghb (Merge High B, AV p195) 15593 DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15594 putVReg( vD_addr, 15595 binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) ); 15596 break; 15597 15598 case 0x04C: // vmrghh (Merge High HW, AV p196) 15599 DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15600 putVReg( vD_addr, 15601 binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) ); 15602 break; 15603 15604 case 0x08C: // vmrghw (Merge High W, AV p197) 15605 DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15606 putVReg( vD_addr, 15607 binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) ); 15608 break; 15609 15610 case 0x10C: // vmrglb (Merge Low B, AV p198) 15611 DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15612 putVReg( vD_addr, 15613 binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) ); 15614 break; 15615 15616 case 0x14C: // vmrglh (Merge Low HW, AV p199) 15617 DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15618 putVReg( vD_addr, 15619 binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) ); 15620 break; 15621 15622 case 0x18C: // vmrglw (Merge Low W, AV p200) 15623 DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15624 putVReg( vD_addr, 15625 binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) ); 15626 break; 15627 15628 15629 /* Splat */ 15630 case 0x20C: { // vspltb (Splat Byte, AV p245) 15631 /* vD = Dup8x16( vB[UIMM_5] ) */ 15632 UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8; 15633 DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 15634 putVReg( vD_addr, unop(Iop_Dup8x16, 15635 unop(Iop_32to8, unop(Iop_V128to32, 15636 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 15637 break; 15638 } 15639 case 0x24C: { // vsplth (Splat Half Word, AV p246) 15640 UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16; 15641 DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 15642 putVReg( vD_addr, unop(Iop_Dup16x8, 15643 unop(Iop_32to16, unop(Iop_V128to32, 15644 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 15645 break; 15646 } 15647 case 0x28C: { // vspltw (Splat Word, AV p250) 15648 /* vD = Dup32x4( vB[UIMM_5] ) */ 15649 UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32; 15650 DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 15651 putVReg( vD_addr, unop(Iop_Dup32x4, 15652 unop(Iop_V128to32, 15653 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) ); 15654 break; 15655 } 15656 case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247) 15657 DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8); 15658 putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) ); 15659 break; 15660 15661 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248) 15662 DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8); 15663 putVReg( vD_addr, 15664 unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) ); 15665 break; 15666 15667 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249) 15668 DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8); 15669 putVReg( vD_addr, 15670 unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) ); 15671 break; 15672 15673 default: 15674 vex_printf("dis_av_permute(ppc)(opc2)\n"); 15675 return False; 15676 } 15677 return True; 15678 } 15679 15680 /* 15681 AltiVec Pack/Unpack Instructions 15682 */ 15683 static Bool dis_av_pack ( UInt theInstr ) 15684 { 15685 /* VX-Form */ 15686 UChar opc1 = ifieldOPC(theInstr); 15687 UChar vD_addr = ifieldRegDS(theInstr); 15688 UChar vA_addr = ifieldRegA(theInstr); 15689 UChar vB_addr = ifieldRegB(theInstr); 15690 UInt opc2 = IFIELD( theInstr, 0, 11 ); 15691 15692 IRTemp signs = IRTemp_INVALID; 15693 IRTemp zeros = IRTemp_INVALID; 15694 IRTemp vA = newTemp(Ity_V128); 15695 IRTemp vB = newTemp(Ity_V128); 15696 assign( vA, getVReg(vA_addr)); 15697 assign( vB, getVReg(vB_addr)); 15698 15699 if (opc1 != 0x4) { 15700 vex_printf("dis_av_pack(ppc)(instr)\n"); 15701 return False; 15702 } 15703 15704 switch (opc2) { 15705 /* Packing */ 15706 case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224) 15707 DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15708 putVReg( vD_addr, 15709 binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) ); 15710 return True; 15711 15712 case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226) 15713 DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15714 putVReg( vD_addr, 15715 binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) ); 15716 return True; 15717 15718 case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225) 15719 DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15720 putVReg( vD_addr, 15721 binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) ); 15722 // TODO: set VSCR[SAT] 15723 return True; 15724 15725 case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227) 15726 DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15727 putVReg( vD_addr, 15728 binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) ); 15729 // TODO: set VSCR[SAT] 15730 return True; 15731 15732 case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221) 15733 // This insn does a signed->unsigned saturating conversion. 15734 // Conversion done here, then uses unsigned->unsigned vpk insn: 15735 // => UnsignedSaturatingNarrow( x & ~ (x >>s 15) ) 15736 IRTemp vA_tmp = newTemp(Ity_V128); 15737 IRTemp vB_tmp = newTemp(Ity_V128); 15738 DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15739 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 15740 unop(Iop_NotV128, 15741 binop(Iop_SarN16x8, 15742 mkexpr(vA), mkU8(15)))) ); 15743 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 15744 unop(Iop_NotV128, 15745 binop(Iop_SarN16x8, 15746 mkexpr(vB), mkU8(15)))) ); 15747 putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16, 15748 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 15749 // TODO: set VSCR[SAT] 15750 return True; 15751 } 15752 case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223) 15753 // This insn does a signed->unsigned saturating conversion. 15754 // Conversion done here, then uses unsigned->unsigned vpk insn: 15755 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) ) 15756 IRTemp vA_tmp = newTemp(Ity_V128); 15757 IRTemp vB_tmp = newTemp(Ity_V128); 15758 DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15759 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 15760 unop(Iop_NotV128, 15761 binop(Iop_SarN32x4, 15762 mkexpr(vA), mkU8(31)))) ); 15763 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 15764 unop(Iop_NotV128, 15765 binop(Iop_SarN32x4, 15766 mkexpr(vB), mkU8(31)))) ); 15767 putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8, 15768 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 15769 // TODO: set VSCR[SAT] 15770 return True; 15771 } 15772 case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220) 15773 DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15774 putVReg( vD_addr, 15775 binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) ); 15776 // TODO: set VSCR[SAT] 15777 return True; 15778 15779 case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222) 15780 DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15781 putVReg( vD_addr, 15782 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) ); 15783 // TODO: set VSCR[SAT] 15784 return True; 15785 15786 case 0x30E: { // vpkpx (Pack Pixel, AV p219) 15787 /* CAB: Worth a new primop? */ 15788 /* Using shifts to compact pixel elements, then packing them */ 15789 IRTemp a1 = newTemp(Ity_V128); 15790 IRTemp a2 = newTemp(Ity_V128); 15791 IRTemp a3 = newTemp(Ity_V128); 15792 IRTemp a_tmp = newTemp(Ity_V128); 15793 IRTemp b1 = newTemp(Ity_V128); 15794 IRTemp b2 = newTemp(Ity_V128); 15795 IRTemp b3 = newTemp(Ity_V128); 15796 IRTemp b_tmp = newTemp(Ity_V128); 15797 DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15798 assign( a1, binop(Iop_ShlN16x8, 15799 binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)), 15800 mkU8(10)) ); 15801 assign( a2, binop(Iop_ShlN16x8, 15802 binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)), 15803 mkU8(5)) ); 15804 assign( a3, binop(Iop_ShrN16x8, 15805 binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)), 15806 mkU8(11)) ); 15807 assign( a_tmp, binop(Iop_OrV128, mkexpr(a1), 15808 binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) ); 15809 15810 assign( b1, binop(Iop_ShlN16x8, 15811 binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)), 15812 mkU8(10)) ); 15813 assign( b2, binop(Iop_ShlN16x8, 15814 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)), 15815 mkU8(5)) ); 15816 assign( b3, binop(Iop_ShrN16x8, 15817 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)), 15818 mkU8(11)) ); 15819 assign( b_tmp, binop(Iop_OrV128, mkexpr(b1), 15820 binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) ); 15821 15822 putVReg( vD_addr, binop(Iop_NarrowBin32to16x8, 15823 mkexpr(a_tmp), mkexpr(b_tmp)) ); 15824 return True; 15825 } 15826 15827 default: 15828 break; // Fall through... 15829 } 15830 15831 15832 if (vA_addr != 0) { 15833 vex_printf("dis_av_pack(ppc)(vA_addr)\n"); 15834 return False; 15835 } 15836 15837 signs = newTemp(Ity_V128); 15838 zeros = newTemp(Ity_V128); 15839 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 15840 15841 switch (opc2) { 15842 /* Unpacking */ 15843 case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277) 15844 DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr); 15845 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 15846 putVReg( vD_addr, 15847 binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) ); 15848 break; 15849 } 15850 case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278) 15851 DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr); 15852 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 15853 putVReg( vD_addr, 15854 binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) ); 15855 break; 15856 } 15857 case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280) 15858 DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr); 15859 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 15860 putVReg( vD_addr, 15861 binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) ); 15862 break; 15863 } 15864 case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281) 15865 DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr); 15866 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 15867 putVReg( vD_addr, 15868 binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) ); 15869 break; 15870 } 15871 case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276) 15872 /* CAB: Worth a new primop? */ 15873 /* Using shifts to isolate pixel elements, then expanding them */ 15874 IRTemp z0 = newTemp(Ity_V128); 15875 IRTemp z1 = newTemp(Ity_V128); 15876 IRTemp z01 = newTemp(Ity_V128); 15877 IRTemp z2 = newTemp(Ity_V128); 15878 IRTemp z3 = newTemp(Ity_V128); 15879 IRTemp z23 = newTemp(Ity_V128); 15880 DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr); 15881 assign( z0, binop(Iop_ShlN16x8, 15882 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 15883 mkU8(8)) ); 15884 assign( z1, binop(Iop_ShrN16x8, 15885 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 15886 mkU8(11)) ); 15887 assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 15888 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 15889 assign( z2, binop(Iop_ShrN16x8, 15890 binop(Iop_ShlN16x8, 15891 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 15892 mkU8(11)), 15893 mkU8(3)) ); 15894 assign( z3, binop(Iop_ShrN16x8, 15895 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 15896 mkU8(11)) ); 15897 assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 15898 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 15899 putVReg( vD_addr, 15900 binop(Iop_OrV128, 15901 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 15902 mkexpr(z23)) ); 15903 break; 15904 } 15905 case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279) 15906 /* identical to vupkhpx, except interleaving LO */ 15907 IRTemp z0 = newTemp(Ity_V128); 15908 IRTemp z1 = newTemp(Ity_V128); 15909 IRTemp z01 = newTemp(Ity_V128); 15910 IRTemp z2 = newTemp(Ity_V128); 15911 IRTemp z3 = newTemp(Ity_V128); 15912 IRTemp z23 = newTemp(Ity_V128); 15913 DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr); 15914 assign( z0, binop(Iop_ShlN16x8, 15915 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 15916 mkU8(8)) ); 15917 assign( z1, binop(Iop_ShrN16x8, 15918 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 15919 mkU8(11)) ); 15920 assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 15921 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 15922 assign( z2, binop(Iop_ShrN16x8, 15923 binop(Iop_ShlN16x8, 15924 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 15925 mkU8(11)), 15926 mkU8(3)) ); 15927 assign( z3, binop(Iop_ShrN16x8, 15928 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 15929 mkU8(11)) ); 15930 assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 15931 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 15932 putVReg( vD_addr, 15933 binop(Iop_OrV128, 15934 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 15935 mkexpr(z23)) ); 15936 break; 15937 } 15938 default: 15939 vex_printf("dis_av_pack(ppc)(opc2)\n"); 15940 return False; 15941 } 15942 return True; 15943 } 15944 15945 15946 /* 15947 AltiVec Floating Point Arithmetic Instructions 15948 */ 15949 static Bool dis_av_fp_arith ( UInt theInstr ) 15950 { 15951 /* VA-Form */ 15952 UChar opc1 = ifieldOPC(theInstr); 15953 UChar vD_addr = ifieldRegDS(theInstr); 15954 UChar vA_addr = ifieldRegA(theInstr); 15955 UChar vB_addr = ifieldRegB(theInstr); 15956 UChar vC_addr = ifieldRegC(theInstr); 15957 UInt opc2=0; 15958 15959 IRTemp vA = newTemp(Ity_V128); 15960 IRTemp vB = newTemp(Ity_V128); 15961 IRTemp vC = newTemp(Ity_V128); 15962 assign( vA, getVReg(vA_addr)); 15963 assign( vB, getVReg(vB_addr)); 15964 assign( vC, getVReg(vC_addr)); 15965 15966 if (opc1 != 0x4) { 15967 vex_printf("dis_av_fp_arith(ppc)(instr)\n"); 15968 return False; 15969 } 15970 15971 opc2 = IFIELD( theInstr, 0, 6 ); 15972 switch (opc2) { 15973 case 0x2E: // vmaddfp (Multiply Add FP, AV p177) 15974 DIP("vmaddfp v%d,v%d,v%d,v%d\n", 15975 vD_addr, vA_addr, vC_addr, vB_addr); 15976 putVReg( vD_addr, 15977 binop(Iop_Add32Fx4, mkexpr(vB), 15978 binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) ); 15979 return True; 15980 15981 case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215) 15982 DIP("vnmsubfp v%d,v%d,v%d,v%d\n", 15983 vD_addr, vA_addr, vC_addr, vB_addr); 15984 putVReg( vD_addr, 15985 binop(Iop_Sub32Fx4, 15986 mkexpr(vB), 15987 binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) ); 15988 return True; 15989 } 15990 15991 default: 15992 break; // Fall through... 15993 } 15994 15995 opc2 = IFIELD( theInstr, 0, 11 ); 15996 switch (opc2) { 15997 case 0x00A: // vaddfp (Add FP, AV p137) 15998 DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15999 putVReg( vD_addr, binop(Iop_Add32Fx4, mkexpr(vA), mkexpr(vB)) ); 16000 return True; 16001 16002 case 0x04A: // vsubfp (Subtract FP, AV p261) 16003 DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16004 putVReg( vD_addr, binop(Iop_Sub32Fx4, mkexpr(vA), mkexpr(vB)) ); 16005 return True; 16006 16007 case 0x40A: // vmaxfp (Maximum FP, AV p178) 16008 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16009 putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) ); 16010 return True; 16011 16012 case 0x44A: // vminfp (Minimum FP, AV p187) 16013 DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16014 putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) ); 16015 return True; 16016 16017 default: 16018 break; // Fall through... 16019 } 16020 16021 16022 if (vA_addr != 0) { 16023 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n"); 16024 return False; 16025 } 16026 16027 switch (opc2) { 16028 case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228) 16029 DIP("vrefp v%d,v%d\n", vD_addr, vB_addr); 16030 putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) ); 16031 return True; 16032 16033 case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237) 16034 DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr); 16035 putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) ); 16036 return True; 16037 16038 case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173) 16039 DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr); 16040 DIP(" => not implemented\n"); 16041 return False; 16042 16043 case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175) 16044 DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr); 16045 DIP(" => not implemented\n"); 16046 return False; 16047 16048 default: 16049 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2); 16050 return False; 16051 } 16052 return True; 16053 } 16054 16055 /* 16056 AltiVec Floating Point Compare Instructions 16057 */ 16058 static Bool dis_av_fp_cmp ( UInt theInstr ) 16059 { 16060 /* VXR-Form */ 16061 UChar opc1 = ifieldOPC(theInstr); 16062 UChar vD_addr = ifieldRegDS(theInstr); 16063 UChar vA_addr = ifieldRegA(theInstr); 16064 UChar vB_addr = ifieldRegB(theInstr); 16065 UChar flag_rC = ifieldBIT10(theInstr); 16066 UInt opc2 = IFIELD( theInstr, 0, 10 ); 16067 16068 Bool cmp_bounds = False; 16069 16070 IRTemp vA = newTemp(Ity_V128); 16071 IRTemp vB = newTemp(Ity_V128); 16072 IRTemp vD = newTemp(Ity_V128); 16073 assign( vA, getVReg(vA_addr)); 16074 assign( vB, getVReg(vB_addr)); 16075 16076 if (opc1 != 0x4) { 16077 vex_printf("dis_av_fp_cmp(ppc)(instr)\n"); 16078 return False; 16079 } 16080 16081 switch (opc2) { 16082 case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159) 16083 DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16084 vD_addr, vA_addr, vB_addr); 16085 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 16086 break; 16087 16088 case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163) 16089 DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16090 vD_addr, vA_addr, vB_addr); 16091 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 16092 break; 16093 16094 case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164) 16095 DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16096 vD_addr, vA_addr, vB_addr); 16097 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 16098 break; 16099 16100 case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157) 16101 IRTemp gt = newTemp(Ity_V128); 16102 IRTemp lt = newTemp(Ity_V128); 16103 IRTemp zeros = newTemp(Ity_V128); 16104 DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16105 vD_addr, vA_addr, vB_addr); 16106 cmp_bounds = True; 16107 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 16108 16109 /* Note: making use of fact that the ppc backend for compare insns 16110 return zero'd lanes if either of the corresponding arg lanes is 16111 a nan. 16112 16113 Perhaps better to have an irop Iop_isNan32Fx4, but then we'd 16114 need this for the other compares too (vcmpeqfp etc)... 16115 Better still, tighten down the spec for compare irops. 16116 */ 16117 assign( gt, unop(Iop_NotV128, 16118 binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) ); 16119 assign( lt, unop(Iop_NotV128, 16120 binop(Iop_CmpGE32Fx4, mkexpr(vA), 16121 binop(Iop_Sub32Fx4, mkexpr(zeros), 16122 mkexpr(vB)))) ); 16123 16124 // finally, just shift gt,lt to correct position 16125 assign( vD, binop(Iop_ShlN32x4, 16126 binop(Iop_OrV128, 16127 binop(Iop_AndV128, mkexpr(gt), 16128 unop(Iop_Dup32x4, mkU32(0x2))), 16129 binop(Iop_AndV128, mkexpr(lt), 16130 unop(Iop_Dup32x4, mkU32(0x1)))), 16131 mkU8(30)) ); 16132 break; 16133 } 16134 16135 default: 16136 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n"); 16137 return False; 16138 } 16139 16140 putVReg( vD_addr, mkexpr(vD) ); 16141 16142 if (flag_rC) { 16143 set_AV_CR6( mkexpr(vD), !cmp_bounds ); 16144 } 16145 return True; 16146 } 16147 16148 /* 16149 AltiVec Floating Point Convert/Round Instructions 16150 */ 16151 static Bool dis_av_fp_convert ( UInt theInstr ) 16152 { 16153 /* VX-Form */ 16154 UChar opc1 = ifieldOPC(theInstr); 16155 UChar vD_addr = ifieldRegDS(theInstr); 16156 UChar UIMM_5 = ifieldRegA(theInstr); 16157 UChar vB_addr = ifieldRegB(theInstr); 16158 UInt opc2 = IFIELD( theInstr, 0, 11 ); 16159 16160 IRTemp vB = newTemp(Ity_V128); 16161 IRTemp vScale = newTemp(Ity_V128); 16162 IRTemp vInvScale = newTemp(Ity_V128); 16163 16164 float scale, inv_scale; 16165 16166 assign( vB, getVReg(vB_addr)); 16167 16168 /* scale = 2^UIMM, cast to float, reinterpreted as uint */ 16169 scale = (float)( (unsigned int) 1<<UIMM_5 ); 16170 assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) ); 16171 inv_scale = 1/scale; 16172 assign( vInvScale, 16173 unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) ); 16174 16175 if (opc1 != 0x4) { 16176 vex_printf("dis_av_fp_convert(ppc)(instr)\n"); 16177 return False; 16178 } 16179 16180 switch (opc2) { 16181 case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156) 16182 DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 16183 putVReg( vD_addr, binop(Iop_Mul32Fx4, 16184 unop(Iop_I32UtoFx4, mkexpr(vB)), 16185 mkexpr(vInvScale)) ); 16186 return True; 16187 16188 case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155) 16189 DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 16190 16191 putVReg( vD_addr, binop(Iop_Mul32Fx4, 16192 unop(Iop_I32StoFx4, mkexpr(vB)), 16193 mkexpr(vInvScale)) ); 16194 return True; 16195 16196 case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172) 16197 DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 16198 putVReg( vD_addr, 16199 unop(Iop_QFtoI32Ux4_RZ, 16200 binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) ); 16201 return True; 16202 16203 case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171) 16204 DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 16205 putVReg( vD_addr, 16206 unop(Iop_QFtoI32Sx4_RZ, 16207 binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) ); 16208 return True; 16209 16210 default: 16211 break; // Fall through... 16212 } 16213 16214 if (UIMM_5 != 0) { 16215 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n"); 16216 return False; 16217 } 16218 16219 switch (opc2) { 16220 case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231) 16221 DIP("vrfin v%d,v%d\n", vD_addr, vB_addr); 16222 putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) ); 16223 break; 16224 16225 case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233) 16226 DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr); 16227 putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) ); 16228 break; 16229 16230 case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232) 16231 DIP("vrfip v%d,v%d\n", vD_addr, vB_addr); 16232 putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) ); 16233 break; 16234 16235 case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230) 16236 DIP("vrfim v%d,v%d\n", vD_addr, vB_addr); 16237 putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) ); 16238 break; 16239 16240 default: 16241 vex_printf("dis_av_fp_convert(ppc)(opc2)\n"); 16242 return False; 16243 } 16244 return True; 16245 } 16246 16247 16248 /* The 0x3C primary opcode (VSX category) uses several different forms of 16249 * extended opcodes: 16250 * o XX2-form: 16251 * - [10:2] (IBM notation [21:29]) 16252 * o XX3-form variants: 16253 * - variant 1: [10:3] (IBM notation [21:28]) 16254 * - variant 2: [9:3] (IBM notation [22:28]) 16255 * - variant 3: [7:3] (IBM notation [24:28]) 16256 * o XX-4 form: 16257 * - [10:6] (IBM notation [21:25]) 16258 * 16259 * The XX2-form needs bit 0 masked from the standard extended opcode 16260 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked; 16261 * and the XX4-form needs bits 0, 1, and 2 masked. Additionally, the 16262 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the 16263 * front end since their encoding does not begin at bit 21 like the standard 16264 * format. 16265 * 16266 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the 16267 * secondary opcode for such VSX instructions. 16268 * 16269 */ 16270 16271 16272 struct vsx_insn { 16273 UInt opcode; 16274 Char * name; 16275 }; 16276 16277 // ATTENTION: Keep this array sorted on the opcocde!!! 16278 static struct vsx_insn vsx_all[] = { 16279 { 0x8, "xxsldwi" }, 16280 { 0x18, "xxsel" }, 16281 { 0x28, "xxpermdi" }, 16282 { 0x48, "xxmrghw" }, 16283 { 0x80, "xsadddp" }, 16284 { 0x84, "xsmaddadp" }, 16285 { 0x8c, "xscmpudp" }, 16286 { 0x90, "xscvdpuxws" }, 16287 { 0x92, "xsrdpi" }, 16288 { 0x94, "xsrsqrtedp" }, 16289 { 0x96, "xssqrtdp" }, 16290 { 0xa0, "xssubdp" }, 16291 { 0xa4, "xsmaddmdp" }, 16292 { 0xac, "xscmpodp" }, 16293 { 0xb0, "xscvdpsxws" }, 16294 { 0xb2, "xsrdpiz" }, 16295 { 0xb4, "xsredp" }, 16296 { 0xc0, "xsmuldp" }, 16297 { 0xc4, "xsmsubadp" }, 16298 { 0xc8, "xxmrglw" }, 16299 { 0xd2, "xsrdpip" }, 16300 { 0xd4, "xstsqrtdp" }, 16301 { 0xd6, "xsrdpic" }, 16302 { 0xe0, "xsdivdp" }, 16303 { 0xe4, "xsmsubmdp" }, 16304 { 0xf2, "xsrdpim" }, 16305 { 0xf4, "xstdivdp" }, 16306 { 0x100, "xvaddsp" }, 16307 { 0x104, "xvmaddasp" }, 16308 { 0x10c, "xvcmpeqsp" }, 16309 { 0x110, "xvcvspuxws" }, 16310 { 0x112, "xvrspi" }, 16311 { 0x114, "xvrsqrtesp" }, 16312 { 0x116, "xvsqrtsp" }, 16313 { 0x120, "xvsubsp" }, 16314 { 0x124, "xvmaddmsp" }, 16315 { 0x12c, "xvcmpgtsp" }, 16316 { 0x130, "xvcvspsxws" }, 16317 { 0x132, "xvrspiz" }, 16318 { 0x134, "xvresp" }, 16319 { 0x140, "xvmulsp" }, 16320 { 0x144, "xvmsubasp" }, 16321 { 0x148, "xxspltw" }, 16322 { 0x14c, "xvcmpgesp" }, 16323 { 0x150, "xvcvuxwsp" }, 16324 { 0x152, "xvrspip" }, 16325 { 0x154, "xvtsqrtsp" }, 16326 { 0x156, "xvrspic" }, 16327 { 0x160, "xvdivsp" }, 16328 { 0x164, "xvmsubmsp" }, 16329 { 0x170, "xvcvsxwsp" }, 16330 { 0x172, "xvrspim" }, 16331 { 0x174, "xvtdivsp" }, 16332 { 0x180, "xvadddp" }, 16333 { 0x184, "xvmaddadp" }, 16334 { 0x18c, "xvcmpeqdp" }, 16335 { 0x190, "xvcvdpuxws" }, 16336 { 0x192, "xvrdpi" }, 16337 { 0x194, "xvrsqrtedp" }, 16338 { 0x196, "xvsqrtdp" }, 16339 { 0x1a0, "xvsubdp" }, 16340 { 0x1a4, "xvmaddmdp" }, 16341 { 0x1ac, "xvcmpgtdp" }, 16342 { 0x1b0, "xvcvdpsxws" }, 16343 { 0x1b2, "xvrdpiz" }, 16344 { 0x1b4, "xvredp" }, 16345 { 0x1c0, "xvmuldp" }, 16346 { 0x1c4, "xvmsubadp" }, 16347 { 0x1cc, "xvcmpgedp" }, 16348 { 0x1d0, "xvcvuxwdp" }, 16349 { 0x1d2, "xvrdpip" }, 16350 { 0x1d4, "xvtsqrtdp" }, 16351 { 0x1d6, "xvrdpic" }, 16352 { 0x1e0, "xvdivdp" }, 16353 { 0x1e4, "xvmsubmdp" }, 16354 { 0x1f0, "xvcvsxwdp" }, 16355 { 0x1f2, "xvrdpim" }, 16356 { 0x1f4, "xvtdivdp" }, 16357 { 0x208, "xxland" }, 16358 { 0x212, "xscvdpsp" }, 16359 { 0x228, "xxlandc" }, 16360 { 0x248 , "xxlor" }, 16361 { 0x268, "xxlxor" }, 16362 { 0x280, "xsmaxdp" }, 16363 { 0x284, "xsnmaddadp" }, 16364 { 0x288, "xxlnor" }, 16365 { 0x290, "xscvdpuxds" }, 16366 { 0x292, "xscvspdp" }, 16367 { 0x2a0, "xsmindp" }, 16368 { 0x2a4, "xsnmaddmdp" }, 16369 { 0x2b0, "xscvdpsxds" }, 16370 { 0x2b2, "xsabsdp" }, 16371 { 0x2c0, "xscpsgndp" }, 16372 { 0x2c4, "xsnmsubadp" }, 16373 { 0x2d0, "xscvuxddp" }, 16374 { 0x2d2, "xsnabsdp" }, 16375 { 0x2e4, "xsnmsubmdp" }, 16376 { 0x2f0, "xscvsxddp" }, 16377 { 0x2f2, "xsnegdp" }, 16378 { 0x300, "xvmaxsp" }, 16379 { 0x304, "xvnmaddasp" }, 16380 { 0x30c, "xvcmpeqsp." }, 16381 { 0x310, "xvcvspuxds" }, 16382 { 0x312, "xvcvdpsp" }, 16383 { 0x320, "xvminsp" }, 16384 { 0x324, "xvnmaddmsp" }, 16385 { 0x32c, "xvcmpgtsp." }, 16386 { 0x330, "xvcvspsxds" }, 16387 { 0x332, "xvabssp" }, 16388 { 0x340, "xvcpsgnsp" }, 16389 { 0x344, "xvnmsubasp" }, 16390 { 0x34c, "xvcmpgesp." }, 16391 { 0x350, "xvcvuxdsp" }, 16392 { 0x352, "xvnabssp" }, 16393 { 0x364, "xvnmsubmsp" }, 16394 { 0x370, "xvcvsxdsp" }, 16395 { 0x372, "xvnegsp" }, 16396 { 0x380, "xvmaxdp" }, 16397 { 0x384, "xvnmaddadp" }, 16398 { 0x38c, "xvcmpeqdp." }, 16399 { 0x390, "xvcvdpuxds" }, 16400 { 0x392, "xvcvspdp" }, 16401 { 0x3a0, "xvmindp" }, 16402 { 0x3a4, "xvnmaddmdp" }, 16403 { 0x3ac, "xvcmpgtdp." }, 16404 { 0x3b0, "xvcvdpsxds" }, 16405 { 0x3b2, "xvabsdp" }, 16406 { 0x3c0, "xvcpsgndp" }, 16407 { 0x3c4, "xvnmsubadp" }, 16408 { 0x3cc, "xvcmpgedp." }, 16409 { 0x3d0, "xvcvuxddp" }, 16410 { 0x3d2, "xvnabsdp" }, 16411 { 0x3e4, "xvnmsubmdp" }, 16412 { 0x3f0, "xvcvsxddp" }, 16413 { 0x3f2, "xvnegdp" } 16414 }; 16415 #define VSX_ALL_LEN 135 16416 16417 // ATTENTION: This search function assumes vsx_all array is sorted. 16418 static Int findVSXextOpCode(UInt opcode) 16419 { 16420 Int low, mid, high; 16421 low = 0; 16422 high = VSX_ALL_LEN - 1; 16423 while (low <= high) { 16424 mid = (low + high)/2; 16425 if (opcode < vsx_all[mid].opcode) 16426 high = mid - 1; 16427 else if (opcode > vsx_all[mid].opcode) 16428 low = mid + 1; 16429 else 16430 return mid; 16431 } 16432 return -1; 16433 } 16434 16435 16436 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is 16437 * passed, and we then try to match it up with one of the VSX forms 16438 * below. 16439 */ 16440 static UInt get_VSX60_opc2(UInt opc2_full) 16441 { 16442 #define XX2_MASK 0x000003FE 16443 #define XX3_1_MASK 0x000003FC 16444 #define XX3_2_MASK 0x000001FC 16445 #define XX3_3_MASK 0x0000007C 16446 #define XX4_MASK 0x00000018 16447 Int ret; 16448 UInt vsxExtOpcode = 0; 16449 16450 if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0) 16451 vsxExtOpcode = vsx_all[ret].opcode; 16452 else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0) 16453 vsxExtOpcode = vsx_all[ret].opcode; 16454 else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0) 16455 vsxExtOpcode = vsx_all[ret].opcode; 16456 else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0) 16457 vsxExtOpcode = vsx_all[ret].opcode; 16458 else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0) 16459 vsxExtOpcode = vsx_all[ret].opcode; 16460 16461 return vsxExtOpcode; 16462 } 16463 16464 /*------------------------------------------------------------*/ 16465 /*--- Disassemble a single instruction ---*/ 16466 /*------------------------------------------------------------*/ 16467 16468 /* Disassemble a single instruction into IR. The instruction 16469 is located in host memory at &guest_code[delta]. */ 16470 16471 static 16472 DisResult disInstr_PPC_WRK ( 16473 Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ), 16474 Bool resteerCisOk, 16475 void* callback_opaque, 16476 Long delta64, 16477 VexArchInfo* archinfo, 16478 VexAbiInfo* abiinfo 16479 ) 16480 { 16481 UChar opc1; 16482 UInt opc2; 16483 DisResult dres; 16484 UInt theInstr; 16485 IRType ty = mode64 ? Ity_I64 : Ity_I32; 16486 Bool allow_F = False; 16487 Bool allow_V = False; 16488 Bool allow_FX = False; 16489 Bool allow_GX = False; 16490 Bool allow_VX = False; // Equates to "supports Power ISA 2.06 16491 Bool allow_DFP = False; 16492 UInt hwcaps = archinfo->hwcaps; 16493 Long delta; 16494 16495 /* What insn variants are we supporting today? */ 16496 if (mode64) { 16497 allow_F = True; 16498 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC64_V)); 16499 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX)); 16500 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX)); 16501 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX)); 16502 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP)); 16503 } else { 16504 allow_F = (0 != (hwcaps & VEX_HWCAPS_PPC32_F)); 16505 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC32_V)); 16506 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX)); 16507 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX)); 16508 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX)); 16509 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP)); 16510 } 16511 16512 /* The running delta */ 16513 delta = (Long)mkSzAddr(ty, (ULong)delta64); 16514 16515 /* Set result defaults. */ 16516 dres.whatNext = Dis_Continue; 16517 dres.len = 0; 16518 dres.continueAt = 0; 16519 dres.jk_StopHere = Ijk_INVALID; 16520 16521 /* At least this is simple on PPC32: insns are all 4 bytes long, and 16522 4-aligned. So just fish the whole thing out of memory right now 16523 and have done. */ 16524 theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) ); 16525 16526 if (0) vex_printf("insn: 0x%x\n", theInstr); 16527 16528 DIP("\t0x%llx: ", (ULong)guest_CIA_curr_instr); 16529 16530 /* Spot "Special" instructions (see comment at top of file). */ 16531 { 16532 UChar* code = (UChar*)(guest_code + delta); 16533 /* Spot the 16-byte preamble: 16534 32-bit mode: 16535 54001800 rlwinm 0,0,3,0,0 16536 54006800 rlwinm 0,0,13,0,0 16537 5400E800 rlwinm 0,0,29,0,0 16538 54009800 rlwinm 0,0,19,0,0 16539 64-bit mode: 16540 78001800 rotldi 0,0,3 16541 78006800 rotldi 0,0,13 16542 7800E802 rotldi 0,0,61 16543 78009802 rotldi 0,0,51 16544 */ 16545 UInt word1 = mode64 ? 0x78001800 : 0x54001800; 16546 UInt word2 = mode64 ? 0x78006800 : 0x54006800; 16547 UInt word3 = mode64 ? 0x7800E802 : 0x5400E800; 16548 UInt word4 = mode64 ? 0x78009802 : 0x54009800; 16549 if (getUIntBigendianly(code+ 0) == word1 && 16550 getUIntBigendianly(code+ 4) == word2 && 16551 getUIntBigendianly(code+ 8) == word3 && 16552 getUIntBigendianly(code+12) == word4) { 16553 /* Got a "Special" instruction preamble. Which one is it? */ 16554 if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) { 16555 /* %R3 = client_request ( %R4 ) */ 16556 DIP("r3 = client_request ( %%r4 )\n"); 16557 delta += 20; 16558 putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta )); 16559 dres.jk_StopHere = Ijk_ClientReq; 16560 dres.whatNext = Dis_StopHere; 16561 goto decode_success; 16562 } 16563 else 16564 if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) { 16565 /* %R3 = guest_NRADDR */ 16566 DIP("r3 = guest_NRADDR\n"); 16567 delta += 20; 16568 dres.len = 20; 16569 putIReg(3, IRExpr_Get( OFFB_NRADDR, ty )); 16570 goto decode_success; 16571 } 16572 else 16573 if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) { 16574 /* branch-and-link-to-noredir %R11 */ 16575 DIP("branch-and-link-to-noredir r11\n"); 16576 delta += 20; 16577 putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) ); 16578 putGST( PPC_GST_CIA, getIReg(11)); 16579 dres.jk_StopHere = Ijk_NoRedir; 16580 dres.whatNext = Dis_StopHere; 16581 goto decode_success; 16582 } 16583 else 16584 if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { 16585 /* %R3 = guest_NRADDR_GPR2 */ 16586 DIP("r3 = guest_NRADDR_GPR2\n"); 16587 delta += 20; 16588 dres.len = 20; 16589 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty )); 16590 goto decode_success; 16591 } 16592 /* We don't know what it is. Set opc1/opc2 so decode_failure 16593 can print the insn following the Special-insn preamble. */ 16594 theInstr = getUIntBigendianly(code+16); 16595 opc1 = ifieldOPC(theInstr); 16596 opc2 = ifieldOPClo10(theInstr); 16597 goto decode_failure; 16598 /*NOTREACHED*/ 16599 } 16600 } 16601 16602 opc1 = ifieldOPC(theInstr); 16603 opc2 = ifieldOPClo10(theInstr); 16604 16605 // Note: all 'reserved' bits must be cleared, else invalid 16606 switch (opc1) { 16607 16608 /* Integer Arithmetic Instructions */ 16609 case 0x0C: case 0x0D: case 0x0E: // addic, addic., addi 16610 case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic 16611 if (dis_int_arith( theInstr )) goto decode_success; 16612 goto decode_failure; 16613 16614 /* Integer Compare Instructions */ 16615 case 0x0B: case 0x0A: // cmpi, cmpli 16616 if (dis_int_cmp( theInstr )) goto decode_success; 16617 goto decode_failure; 16618 16619 /* Integer Logical Instructions */ 16620 case 0x1C: case 0x1D: case 0x18: // andi., andis., ori 16621 case 0x19: case 0x1A: case 0x1B: // oris, xori, xoris 16622 if (dis_int_logic( theInstr )) goto decode_success; 16623 goto decode_failure; 16624 16625 /* Integer Rotate Instructions */ 16626 case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm 16627 if (dis_int_rot( theInstr )) goto decode_success; 16628 goto decode_failure; 16629 16630 /* 64bit Integer Rotate Instructions */ 16631 case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi 16632 if (dis_int_rot( theInstr )) goto decode_success; 16633 goto decode_failure; 16634 16635 /* Integer Load Instructions */ 16636 case 0x22: case 0x23: case 0x2A: // lbz, lbzu, lha 16637 case 0x2B: case 0x28: case 0x29: // lhau, lhz, lhzu 16638 case 0x20: case 0x21: // lwz, lwzu 16639 if (dis_int_load( theInstr )) goto decode_success; 16640 goto decode_failure; 16641 16642 /* Integer Store Instructions */ 16643 case 0x26: case 0x27: case 0x2C: // stb, stbu, sth 16644 case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu 16645 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 16646 goto decode_failure; 16647 16648 /* Integer Load and Store Multiple Instructions */ 16649 case 0x2E: case 0x2F: // lmw, stmw 16650 if (dis_int_ldst_mult( theInstr )) goto decode_success; 16651 goto decode_failure; 16652 16653 /* Branch Instructions */ 16654 case 0x12: case 0x10: // b, bc 16655 if (dis_branch(theInstr, abiinfo, &dres, 16656 resteerOkFn, callback_opaque)) 16657 goto decode_success; 16658 goto decode_failure; 16659 16660 /* System Linkage Instructions */ 16661 case 0x11: // sc 16662 if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success; 16663 goto decode_failure; 16664 16665 /* Trap Instructions */ 16666 case 0x02: case 0x03: // tdi, twi 16667 if (dis_trapi(theInstr, &dres)) goto decode_success; 16668 goto decode_failure; 16669 16670 /* Floating Point Load Instructions */ 16671 case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd 16672 case 0x33: // lfdu 16673 if (!allow_F) goto decode_noF; 16674 if (dis_fp_load( theInstr )) goto decode_success; 16675 goto decode_failure; 16676 16677 /* Floating Point Store Instructions */ 16678 case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx 16679 case 0x37: // stfdux 16680 if (!allow_F) goto decode_noF; 16681 if (dis_fp_store( theInstr )) goto decode_success; 16682 goto decode_failure; 16683 16684 /* Floating Point Load Double Pair Instructions */ 16685 case 0x39: case 0x3D: 16686 if (!allow_F) goto decode_noF; 16687 if (dis_fp_pair( theInstr )) goto decode_success; 16688 goto decode_failure; 16689 16690 /* 64bit Integer Loads */ 16691 case 0x3A: // ld, ldu, lwa 16692 if (!mode64) goto decode_failure; 16693 if (dis_int_load( theInstr )) goto decode_success; 16694 goto decode_failure; 16695 16696 case 0x3B: 16697 if (!allow_F) goto decode_noF; 16698 opc2 = ifieldOPClo10(theInstr); 16699 16700 switch (opc2) { 16701 case 0x2: // dadd - DFP Add 16702 case 0x202: // dsub - DFP Subtract 16703 case 0x22: // dmul - DFP Mult 16704 case 0x222: // ddiv - DFP Divide 16705 if (!allow_DFP) goto decode_noDFP; 16706 if (dis_dfp_arith( theInstr )) 16707 goto decode_success; 16708 case 0x82: // dcmpo, DFP comparison ordered instruction 16709 case 0x282: // dcmpu, DFP comparison unordered instruction 16710 if (!allow_DFP) 16711 goto decode_failure; 16712 if (dis_dfp_compare( theInstr ) ) 16713 goto decode_success; 16714 goto decode_failure; 16715 case 0x102: // dctdp - DFP convert to DFP long 16716 case 0x302: // drsp - DFP round to dfp short 16717 case 0x122: // dctfix - DFP convert to fixed 16718 if (!allow_DFP) 16719 goto decode_failure; 16720 if (dis_dfp_fmt_conv( theInstr )) 16721 goto decode_success; 16722 goto decode_failure; 16723 case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed 16724 if (!allow_VX) 16725 goto decode_failure; 16726 if (dis_dfp_fmt_conv( theInstr )) 16727 goto decode_success; 16728 goto decode_failure; 16729 case 0x2A2: // dtstsf - DFP number of significant digits 16730 if (!allow_DFP) 16731 goto decode_failure; 16732 if (dis_dfp_significant_digits(theInstr)) 16733 goto decode_success; 16734 goto decode_failure; 16735 case 0x142: // ddedpd DFP Decode DPD to BCD 16736 case 0x342: // denbcd DFP Encode BCD to DPD 16737 if (!allow_DFP) 16738 goto decode_failure; 16739 if (dis_dfp_bcd(theInstr)) 16740 goto decode_success; 16741 goto decode_failure; 16742 case 0x162: // dxex - Extract exponent 16743 case 0x362: // diex - Insert exponent 16744 if (!allow_DFP) 16745 goto decode_failure; 16746 if (dis_dfp_extract_insert( theInstr ) ) 16747 goto decode_success; 16748 goto decode_failure; 16749 case 0x3CE: // fcfidus (implemented as native insn) 16750 if (!allow_VX) 16751 goto decode_noVX; 16752 if (dis_fp_round( theInstr )) 16753 goto decode_success; 16754 goto decode_failure; 16755 case 0x34E: // fcfids 16756 if (dis_fp_round( theInstr )) 16757 goto decode_success; 16758 goto decode_failure; 16759 } 16760 16761 opc2 = ifieldOPClo9( theInstr ); 16762 switch (opc2) { 16763 case 0x42: // dscli, DFP shift left 16764 case 0x62: // dscri, DFP shift right 16765 if (!allow_DFP) 16766 goto decode_failure; 16767 if (dis_dfp_shift( theInstr )) 16768 goto decode_success; 16769 goto decode_failure; 16770 case 0xc2: // dtstdc, DFP test data class 16771 case 0xe2: // dtstdg, DFP test data group 16772 if (!allow_DFP) 16773 goto decode_failure; 16774 if (dis_dfp_class_test( theInstr )) 16775 goto decode_success; 16776 goto decode_failure; 16777 } 16778 16779 opc2 = ifieldOPClo8( theInstr ); 16780 switch (opc2) { 16781 case 0x3: // dqua - DFP Quantize 16782 case 0x23: // drrnd - DFP Reround 16783 case 0x43: // dquai - DFP Quantize immediate 16784 if (!allow_DFP) 16785 goto decode_failure; 16786 if (dis_dfp_quantize_sig_rrnd( theInstr ) ) 16787 goto decode_success; 16788 goto decode_failure; 16789 case 0xA2: // dtstex - DFP Test exponent 16790 if (!allow_DFP) 16791 goto decode_failure; 16792 if (dis_dfp_exponent_test( theInstr ) ) 16793 goto decode_success; 16794 goto decode_failure; 16795 case 0x63: // drintx - Round to an integer value 16796 case 0xE3: // drintn - Round to an integer value 16797 if (!allow_DFP) 16798 goto decode_failure; 16799 if (dis_dfp_round( theInstr ) ) { 16800 goto decode_success; 16801 } 16802 goto decode_failure; 16803 default: 16804 break; /* fall through to next opc2 check */ 16805 } 16806 16807 opc2 = IFIELD(theInstr, 1, 5); 16808 switch (opc2) { 16809 /* Floating Point Arith Instructions */ 16810 case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds 16811 case 0x19: // fmuls 16812 if (dis_fp_arith(theInstr)) goto decode_success; 16813 goto decode_failure; 16814 case 0x16: // fsqrts 16815 if (!allow_FX) goto decode_noFX; 16816 if (dis_fp_arith(theInstr)) goto decode_success; 16817 goto decode_failure; 16818 case 0x18: // fres 16819 if (!allow_GX) goto decode_noGX; 16820 if (dis_fp_arith(theInstr)) goto decode_success; 16821 goto decode_failure; 16822 16823 /* Floating Point Mult-Add Instructions */ 16824 case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs 16825 case 0x1F: // fnmadds 16826 if (dis_fp_multadd(theInstr)) goto decode_success; 16827 goto decode_failure; 16828 16829 case 0x1A: // frsqrtes 16830 if (!allow_GX) goto decode_noGX; 16831 if (dis_fp_arith(theInstr)) goto decode_success; 16832 goto decode_failure; 16833 16834 default: 16835 goto decode_failure; 16836 } 16837 break; 16838 16839 case 0x3C: // VSX instructions (except load/store) 16840 { 16841 // All of these VSX instructions use some VMX facilities, so 16842 // if allow_V is not set, we'll skip trying to decode. 16843 if (!allow_V) goto decode_noVX; 16844 16845 UInt vsxOpc2 = get_VSX60_opc2(opc2); 16846 /* The vsxOpc2 returned is the "normalized" value, representing the 16847 * instructions secondary opcode as taken from the standard secondary 16848 * opcode field [21:30] (IBM notatition), even if the actual field 16849 * is non-standard. These normalized values are given in the opcode 16850 * appendices of the ISA 2.06 document. 16851 */ 16852 if (vsxOpc2 == 0) 16853 goto decode_failure; 16854 16855 switch (vsxOpc2) { 16856 case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw 16857 case 0x018: case 0x148: // xxsel, xxspltw 16858 if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success; 16859 goto decode_failure; 16860 case 0x268: case 0x248: case 0x288: case 0x208: case 0x228: // xxlxor, xxlor, xxlnor, xxland, xxlandc 16861 if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success; 16862 goto decode_failure; 16863 case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp 16864 case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp 16865 case 0x280: case 0x2A0: // xsmaxdp, xsmindp 16866 case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip 16867 case 0x0B4: case 0x094: // xsredp, xsrsqrtedp 16868 case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz 16869 case 0x092: // xsrdpi 16870 if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success; 16871 goto decode_failure; 16872 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 16873 if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success; 16874 goto decode_failure; 16875 case 0x080: case 0x0E0: // xsadddp, xsdivdp 16876 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp 16877 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp 16878 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp 16879 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp 16880 case 0x0C0: case 0x0A0: // xsmuldp, xssubdp 16881 case 0x096: case 0x0F4: // xssqrtdp, xstdivdp 16882 case 0x0D4: // xstsqrtdp 16883 if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success; 16884 goto decode_failure; 16885 case 0x180: // xvadddp 16886 case 0x1E0: // xvdivdp 16887 case 0x1C0: // xvmuldp 16888 case 0x1A0: // xvsubdp 16889 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp 16890 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp 16891 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp 16892 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp 16893 case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp 16894 case 0x196: // xvsqrtdp 16895 if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success; 16896 goto decode_failure; 16897 case 0x100: // xvaddsp 16898 case 0x160: // xvdivsp 16899 case 0x140: // xvmulsp 16900 case 0x120: // xvsubsp 16901 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp 16902 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp 16903 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp 16904 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp 16905 case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp 16906 case 0x116: // xvsqrtsp 16907 if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success; 16908 goto decode_failure; 16909 16910 case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp 16911 case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp 16912 case 0x090: // xscvdpuxws 16913 // The above VSX conversion instructions employ some ISA 2.06 16914 // floating point conversion instructions under the covers, 16915 // so if allow_VX (which means "supports ISA 2.06") is not set, 16916 // we'll skip the decode. 16917 if (!allow_VX) goto decode_noVX; 16918 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success; 16919 goto decode_failure; 16920 16921 case 0x2B0: case 0x2F0: // xscvdpsxds, xscvsxddp 16922 case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws 16923 case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds 16924 case 0x212: // xscvdpsp 16925 case 0x292: case 0x312: // xscvspdp, xvcvdpsp 16926 case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws 16927 case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds 16928 case 0x392: case 0x330: // xvcvspdp, xvcvspsxds 16929 case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp 16930 case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp 16931 case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp 16932 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success; 16933 goto decode_failure; 16934 16935 case 0x18C: case 0x38C: // xvcmpeqdp[.] 16936 case 0x10C: case 0x30C: // xvcmpeqsp[.] 16937 case 0x14C: case 0x34C: // xvcmpgesp[.] 16938 case 0x12C: case 0x32C: // xvcmpgtsp[.] 16939 case 0x1CC: case 0x3CC: // xvcmpgedp[.] 16940 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] 16941 if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success; 16942 goto decode_failure; 16943 16944 case 0x134: // xvresp 16945 case 0x1B4: // xvredp 16946 case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp 16947 case 0x380: case 0x3A0: // xvmaxdp, xvmindp 16948 case 0x300: case 0x320: // xvmaxsp, xvminsp 16949 case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp 16950 case 0x3B2: case 0x332: // xvabsdp, xvabssp 16951 case 0x3D2: case 0x352: // xvnabsdp, xvnabssp 16952 case 0x192: case 0x1D6: // xvrdpi, xvrdpic 16953 case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip 16954 case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp 16955 case 0x112: case 0x156: // xvrspi, xvrspic 16956 case 0x172: case 0x152: // xvrspim, xvrspip 16957 case 0x132: // xvrspiz 16958 if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success; 16959 goto decode_failure; 16960 16961 default: 16962 goto decode_failure; 16963 } 16964 break; 16965 } 16966 16967 /* 64bit Integer Stores */ 16968 case 0x3E: // std, stdu 16969 if (!mode64) goto decode_failure; 16970 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 16971 goto decode_failure; 16972 16973 case 0x3F: 16974 if (!allow_F) goto decode_noF; 16975 /* Instrs using opc[1:5] never overlap instrs using opc[1:10], 16976 so we can simply fall through the first switch statement */ 16977 16978 opc2 = IFIELD(theInstr, 1, 5); 16979 switch (opc2) { 16980 /* Floating Point Arith Instructions */ 16981 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd 16982 case 0x19: // fmul 16983 if (dis_fp_arith(theInstr)) goto decode_success; 16984 goto decode_failure; 16985 case 0x16: // fsqrt 16986 if (!allow_FX) goto decode_noFX; 16987 if (dis_fp_arith(theInstr)) goto decode_success; 16988 goto decode_failure; 16989 case 0x17: case 0x1A: // fsel, frsqrte 16990 if (!allow_GX) goto decode_noGX; 16991 if (dis_fp_arith(theInstr)) goto decode_success; 16992 goto decode_failure; 16993 16994 /* Floating Point Mult-Add Instructions */ 16995 case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub 16996 case 0x1F: // fnmadd 16997 if (dis_fp_multadd(theInstr)) goto decode_success; 16998 goto decode_failure; 16999 17000 case 0x18: // fre 17001 if (!allow_GX) goto decode_noGX; 17002 if (dis_fp_arith(theInstr)) goto decode_success; 17003 goto decode_failure; 17004 17005 default: 17006 break; // Fall through 17007 } 17008 17009 opc2 = IFIELD(theInstr, 1, 10); 17010 switch (opc2) { 17011 /* 128-bit DFP instructions */ 17012 case 0x2: // daddq - DFP Add 17013 case 0x202: // dsubq - DFP Subtract 17014 case 0x22: // dmulq - DFP Mult 17015 case 0x222: // ddivq - DFP Divide 17016 if (!allow_DFP) goto decode_noDFP; 17017 if (dis_dfp_arithq( theInstr )) 17018 goto decode_success; 17019 goto decode_failure; 17020 case 0x162: // dxexq - DFP Extract exponent 17021 case 0x362: // diexq - DFP Insert exponent 17022 if (!allow_DFP) 17023 goto decode_failure; 17024 if (dis_dfp_extract_insertq( theInstr )) 17025 goto decode_success; 17026 goto decode_failure; 17027 17028 case 0x82: // dcmpoq, DFP comparison ordered instruction 17029 case 0x282: // dcmpuq, DFP comparison unordered instruction 17030 if (!allow_DFP) 17031 goto decode_failure; 17032 if (dis_dfp_compare( theInstr ) ) 17033 goto decode_success; 17034 goto decode_failure; 17035 17036 case 0x102: // dctqpq - DFP convert to DFP extended 17037 case 0x302: // drdpq - DFP round to dfp Long 17038 case 0x122: // dctfixq - DFP convert to fixed quad 17039 case 0x322: // dcffixq - DFP convert from fixed quad 17040 if (!allow_DFP) 17041 goto decode_failure; 17042 if (dis_dfp_fmt_convq( theInstr )) 17043 goto decode_success; 17044 goto decode_failure; 17045 17046 case 0x2A2: // dtstsfq - DFP number of significant digits 17047 if (!allow_DFP) 17048 goto decode_failure; 17049 if (dis_dfp_significant_digits(theInstr)) 17050 goto decode_success; 17051 goto decode_failure; 17052 17053 case 0x142: // ddedpdq DFP Decode DPD to BCD 17054 case 0x342: // denbcdq DFP Encode BCD to DPD 17055 if (!allow_DFP) 17056 goto decode_failure; 17057 if (dis_dfp_bcdq(theInstr)) 17058 goto decode_success; 17059 goto decode_failure; 17060 17061 /* Floating Point Compare Instructions */ 17062 case 0x000: // fcmpu 17063 case 0x020: // fcmpo 17064 if (dis_fp_cmp(theInstr)) goto decode_success; 17065 goto decode_failure; 17066 17067 case 0x080: // ftdiv 17068 case 0x0A0: // ftsqrt 17069 if (dis_fp_tests(theInstr)) goto decode_success; 17070 goto decode_failure; 17071 17072 /* Floating Point Rounding/Conversion Instructions */ 17073 case 0x00C: // frsp 17074 case 0x00E: // fctiw 17075 case 0x00F: // fctiwz 17076 case 0x32E: // fctid 17077 case 0x32F: // fctidz 17078 case 0x34E: // fcfid 17079 if (dis_fp_round(theInstr)) goto decode_success; 17080 goto decode_failure; 17081 case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns) 17082 case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns) 17083 if (!allow_VX) goto decode_noVX; 17084 if (dis_fp_round(theInstr)) goto decode_success; 17085 goto decode_failure; 17086 17087 /* Power6 rounding stuff */ 17088 case 0x1E8: // frim 17089 case 0x1C8: // frip 17090 case 0x188: // frin 17091 case 0x1A8: // friz 17092 /* A hack to check for P6 capability . . . */ 17093 if ((allow_F && allow_V && allow_FX && allow_GX) && 17094 (dis_fp_round(theInstr))) 17095 goto decode_success; 17096 goto decode_failure; 17097 17098 /* Floating Point Move Instructions */ 17099 case 0x008: // fcpsgn 17100 case 0x028: // fneg 17101 case 0x048: // fmr 17102 case 0x088: // fnabs 17103 case 0x108: // fabs 17104 if (dis_fp_move( theInstr )) goto decode_success; 17105 goto decode_failure; 17106 17107 /* Floating Point Status/Control Register Instructions */ 17108 case 0x026: // mtfsb1 17109 case 0x040: // mcrfs 17110 case 0x046: // mtfsb0 17111 case 0x086: // mtfsfi 17112 case 0x247: // mffs 17113 case 0x2C7: // mtfsf 17114 // Some of the above instructions need to know more about the 17115 // ISA level supported by the host. 17116 if (dis_fp_scr( theInstr, allow_GX )) goto decode_success; 17117 goto decode_failure; 17118 17119 default: 17120 break; // Fall through... 17121 } 17122 17123 opc2 = ifieldOPClo9( theInstr ); 17124 switch (opc2) { 17125 case 0x42: // dscli, DFP shift left 17126 case 0x62: // dscri, DFP shift right 17127 if (!allow_DFP) 17128 goto decode_failure; 17129 if (dis_dfp_shiftq( theInstr )) 17130 goto decode_success; 17131 goto decode_failure; 17132 case 0xc2: // dtstdc, DFP test data class 17133 case 0xe2: // dtstdg, DFP test data group 17134 if (!allow_DFP) 17135 goto decode_failure; 17136 if (dis_dfp_class_test( theInstr )) 17137 goto decode_success; 17138 goto decode_failure; 17139 default: 17140 break; 17141 } 17142 17143 opc2 = ifieldOPClo8( theInstr ); 17144 switch (opc2) { 17145 case 0x3: // dquaq - DFP Quantize Quad 17146 case 0x23: // drrndq - DFP Reround Quad 17147 case 0x43: // dquaiq - DFP Quantize immediate Quad 17148 if (!allow_DFP) 17149 goto decode_failure; 17150 if (dis_dfp_quantize_sig_rrndq( theInstr )) 17151 goto decode_success; 17152 goto decode_failure; 17153 case 0xA2: // dtstexq - DFP Test exponent Quad 17154 if (dis_dfp_exponent_test( theInstr ) ) 17155 goto decode_success; 17156 goto decode_failure; 17157 case 0x63: // drintxq - DFP Round to an integer value 17158 case 0xE3: // drintnq - DFP Round to an integer value 17159 if (!allow_DFP) 17160 goto decode_failure; 17161 if (dis_dfp_roundq( theInstr )) 17162 goto decode_success; 17163 goto decode_failure; 17164 17165 default: 17166 goto decode_failure; 17167 } 17168 break; 17169 17170 case 0x13: 17171 switch (opc2) { 17172 17173 /* Condition Register Logical Instructions */ 17174 case 0x101: case 0x081: case 0x121: // crand, crandc, creqv 17175 case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror 17176 case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf 17177 if (dis_cond_logic( theInstr )) goto decode_success; 17178 goto decode_failure; 17179 17180 /* Branch Instructions */ 17181 case 0x210: case 0x010: // bcctr, bclr 17182 if (dis_branch(theInstr, abiinfo, &dres, 17183 resteerOkFn, callback_opaque)) 17184 goto decode_success; 17185 goto decode_failure; 17186 17187 /* Memory Synchronization Instructions */ 17188 case 0x096: // isync 17189 if (dis_memsync( theInstr )) goto decode_success; 17190 goto decode_failure; 17191 17192 default: 17193 goto decode_failure; 17194 } 17195 break; 17196 17197 17198 case 0x1F: 17199 17200 /* For arith instns, bit10 is the OE flag (overflow enable) */ 17201 17202 opc2 = IFIELD(theInstr, 1, 9); 17203 switch (opc2) { 17204 /* Integer Arithmetic Instructions */ 17205 case 0x10A: case 0x00A: case 0x08A: // add, addc, adde 17206 case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw 17207 case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu 17208 case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf 17209 case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme 17210 case 0x0C8: // subfze 17211 if (dis_int_arith( theInstr )) goto decode_success; 17212 goto decode_failure; 17213 17214 case 0x18B: // divweu (implemented as native insn) 17215 case 0x1AB: // divwe (implemented as native insn) 17216 if (!allow_VX) goto decode_noVX; 17217 if (dis_int_arith( theInstr )) goto decode_success; 17218 goto decode_failure; 17219 17220 /* 64bit Integer Arithmetic */ 17221 case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld 17222 case 0x1C9: case 0x1E9: // divdu, divd 17223 if (!mode64) goto decode_failure; 17224 if (dis_int_arith( theInstr )) goto decode_success; 17225 goto decode_failure; 17226 17227 case 0x1A9: // divde (implemented as native insn) 17228 case 0x189: // divdeuo (implemented as native insn) 17229 if (!allow_VX) goto decode_noVX; 17230 if (!mode64) goto decode_failure; 17231 if (dis_int_arith( theInstr )) goto decode_success; 17232 goto decode_failure; 17233 17234 case 0x1FC: // cmpb 17235 if (dis_int_logic( theInstr )) goto decode_success; 17236 goto decode_failure; 17237 17238 default: 17239 break; // Fall through... 17240 } 17241 17242 /* All remaining opcodes use full 10 bits. */ 17243 17244 opc2 = IFIELD(theInstr, 1, 10); 17245 switch (opc2) { 17246 /* Integer Compare Instructions */ 17247 case 0x000: case 0x020: // cmp, cmpl 17248 if (dis_int_cmp( theInstr )) goto decode_success; 17249 goto decode_failure; 17250 17251 /* Integer Logical Instructions */ 17252 case 0x01C: case 0x03C: case 0x01A: // and, andc, cntlzw 17253 case 0x11C: case 0x3BA: case 0x39A: // eqv, extsb, extsh 17254 case 0x1DC: case 0x07C: case 0x1BC: // nand, nor, or 17255 case 0x19C: case 0x13C: // orc, xor 17256 case 0x2DF: case 0x25F: // mftgpr, mffgpr 17257 if (dis_int_logic( theInstr )) goto decode_success; 17258 goto decode_failure; 17259 17260 /* 64bit Integer Logical Instructions */ 17261 case 0x3DA: case 0x03A: // extsw, cntlzd 17262 if (!mode64) goto decode_failure; 17263 if (dis_int_logic( theInstr )) goto decode_success; 17264 goto decode_failure; 17265 17266 /* 64bit Integer Parity Instructions */ 17267 case 0xba: case 0x9a: // prtyd, prtyw 17268 if (dis_int_parity( theInstr )) goto decode_success; 17269 goto decode_failure; 17270 17271 /* Integer Shift Instructions */ 17272 case 0x018: case 0x318: case 0x338: // slw, sraw, srawi 17273 case 0x218: // srw 17274 if (dis_int_shift( theInstr )) goto decode_success; 17275 goto decode_failure; 17276 17277 /* 64bit Integer Shift Instructions */ 17278 case 0x01B: case 0x31A: // sld, srad 17279 case 0x33A: case 0x33B: // sradi 17280 case 0x21B: // srd 17281 if (!mode64) goto decode_failure; 17282 if (dis_int_shift( theInstr )) goto decode_success; 17283 goto decode_failure; 17284 17285 /* Integer Load Instructions */ 17286 case 0x057: case 0x077: case 0x157: // lbzx, lbzux, lhax 17287 case 0x177: case 0x117: case 0x137: // lhaux, lhzx, lhzux 17288 case 0x017: case 0x037: // lwzx, lwzux 17289 if (dis_int_load( theInstr )) goto decode_success; 17290 goto decode_failure; 17291 17292 /* 64bit Integer Load Instructions */ 17293 case 0x035: case 0x015: // ldux, ldx 17294 case 0x175: case 0x155: // lwaux, lwax 17295 if (!mode64) goto decode_failure; 17296 if (dis_int_load( theInstr )) goto decode_success; 17297 goto decode_failure; 17298 17299 /* Integer Store Instructions */ 17300 case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux 17301 case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx 17302 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 17303 goto decode_failure; 17304 17305 /* 64bit Integer Store Instructions */ 17306 case 0x0B5: case 0x095: // stdux, stdx 17307 if (!mode64) goto decode_failure; 17308 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 17309 goto decode_failure; 17310 17311 /* Integer Load and Store with Byte Reverse Instructions */ 17312 case 0x316: case 0x216: case 0x396: // lhbrx, lwbrx, sthbrx 17313 case 0x296: case 0x214: // stwbrx, ldbrx 17314 case 0x294: // stdbrx 17315 if (dis_int_ldst_rev( theInstr )) goto decode_success; 17316 goto decode_failure; 17317 17318 /* Integer Load and Store String Instructions */ 17319 case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi 17320 case 0x295: { // stswx 17321 Bool stopHere = False; 17322 Bool ok = dis_int_ldst_str( theInstr, &stopHere ); 17323 if (!ok) goto decode_failure; 17324 if (stopHere) { 17325 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) ); 17326 dres.jk_StopHere = Ijk_Boring; 17327 dres.whatNext = Dis_StopHere; 17328 } 17329 goto decode_success; 17330 } 17331 17332 /* Memory Synchronization Instructions */ 17333 case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx. 17334 case 0x256: // sync 17335 if (dis_memsync( theInstr )) goto decode_success; 17336 goto decode_failure; 17337 17338 /* 64bit Memory Synchronization Instructions */ 17339 case 0x054: case 0x0D6: // ldarx, stdcx. 17340 if (!mode64) goto decode_failure; 17341 if (dis_memsync( theInstr )) goto decode_success; 17342 goto decode_failure; 17343 17344 /* Processor Control Instructions */ 17345 case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr 17346 case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr 17347 if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success; 17348 goto decode_failure; 17349 17350 /* Cache Management Instructions */ 17351 case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst 17352 case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz 17353 case 0x3D6: // icbi 17354 if (dis_cache_manage( theInstr, &dres, archinfo )) 17355 goto decode_success; 17356 goto decode_failure; 17357 17358 //zz /* External Control Instructions */ 17359 //zz case 0x136: case 0x1B6: // eciwx, ecowx 17360 //zz DIP("external control op => not implemented\n"); 17361 //zz goto decode_failure; 17362 17363 /* Trap Instructions */ 17364 case 0x004: case 0x044: // tw, td 17365 if (dis_trap(theInstr, &dres)) goto decode_success; 17366 goto decode_failure; 17367 17368 /* Floating Point Load Instructions */ 17369 case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx 17370 case 0x277: // lfdux 17371 if (!allow_F) goto decode_noF; 17372 if (dis_fp_load( theInstr )) goto decode_success; 17373 goto decode_failure; 17374 17375 /* Floating Point Store Instructions */ 17376 case 0x297: case 0x2B7: case 0x2D7: // stfs, stfsu, stfd 17377 case 0x2F7: // stfdu, stfiwx 17378 if (!allow_F) goto decode_noF; 17379 if (dis_fp_store( theInstr )) goto decode_success; 17380 goto decode_failure; 17381 case 0x3D7: // stfiwx 17382 if (!allow_F) goto decode_noF; 17383 if (!allow_GX) goto decode_noGX; 17384 if (dis_fp_store( theInstr )) goto decode_success; 17385 goto decode_failure; 17386 17387 /* Floating Point Double Pair Indexed Instructions */ 17388 case 0x317: // lfdpx (Power6) 17389 case 0x397: // stfdpx (Power6) 17390 if (!allow_F) goto decode_noF; 17391 if (dis_fp_pair(theInstr)) goto decode_success; 17392 goto decode_failure; 17393 17394 case 0x357: // lfiwax 17395 if (!allow_F) goto decode_noF; 17396 if (dis_fp_load( theInstr )) goto decode_success; 17397 goto decode_failure; 17398 17399 case 0x377: // lfiwzx 17400 if (!allow_F) goto decode_noF; 17401 if (dis_fp_load( theInstr )) goto decode_success; 17402 goto decode_failure; 17403 17404 /* AltiVec instructions */ 17405 17406 /* AV Cache Control - Data streams */ 17407 case 0x156: case 0x176: case 0x336: // dst, dstst, dss 17408 if (!allow_V) goto decode_noV; 17409 if (dis_av_datastream( theInstr )) goto decode_success; 17410 goto decode_failure; 17411 17412 /* AV Load */ 17413 case 0x006: case 0x026: // lvsl, lvsr 17414 case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx 17415 case 0x067: case 0x167: // lvx, lvxl 17416 if (!allow_V) goto decode_noV; 17417 if (dis_av_load( abiinfo, theInstr )) goto decode_success; 17418 goto decode_failure; 17419 17420 /* AV Store */ 17421 case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx 17422 case 0x0E7: case 0x1E7: // stvx, stvxl 17423 if (!allow_V) goto decode_noV; 17424 if (dis_av_store( theInstr )) goto decode_success; 17425 goto decode_failure; 17426 17427 /* VSX Load */ 17428 case 0x24C: // lxsdx 17429 case 0x34C: // lxvd2x 17430 case 0x14C: // lxvdsx 17431 case 0x30C: // lxvw4x 17432 // All of these VSX load instructions use some VMX facilities, so 17433 // if allow_V is not set, we'll skip trying to decode. 17434 if (!allow_V) goto decode_noV; 17435 17436 if (dis_vx_load( theInstr )) goto decode_success; 17437 goto decode_failure; 17438 17439 /* VSX Store */ 17440 case 0x2CC: // stxsdx 17441 case 0x3CC: // stxvd2x 17442 case 0x38C: // stxvw4x 17443 // All of these VSX store instructions use some VMX facilities, so 17444 // if allow_V is not set, we'll skip trying to decode. 17445 if (!allow_V) goto decode_noV; 17446 17447 if (dis_vx_store( theInstr )) goto decode_success; 17448 goto decode_failure; 17449 17450 /* Miscellaneous ISA 2.06 instructions */ 17451 case 0x1FA: // popcntd 17452 case 0x17A: // popcntw 17453 case 0x7A: // popcntb 17454 if (dis_int_logic( theInstr )) goto decode_success; 17455 goto decode_failure; 17456 17457 case 0x0FC: // bpermd 17458 if (dis_int_logic( theInstr )) goto decode_success; 17459 goto decode_failure; 17460 17461 default: 17462 /* Deal with some other cases that we would otherwise have 17463 punted on. */ 17464 /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */ 17465 /* only decode this insn when reserved bit 0 (31 in IBM's 17466 notation) is zero */ 17467 if (IFIELD(theInstr, 0, 6) == (15<<1)) { 17468 UInt rT = ifieldRegDS( theInstr ); 17469 UInt rA = ifieldRegA( theInstr ); 17470 UInt rB = ifieldRegB( theInstr ); 17471 UInt bi = ifieldRegC( theInstr ); 17472 putIReg( 17473 rT, 17474 IRExpr_Mux0X( unop(Iop_32to8,getCRbit( bi )), 17475 getIReg(rB), 17476 rA == 0 ? (mode64 ? mkU64(0) : mkU32(0)) 17477 : getIReg(rA) ) 17478 ); 17479 DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi); 17480 goto decode_success; 17481 } 17482 goto decode_failure; 17483 } 17484 break; 17485 17486 17487 case 0x04: 17488 /* AltiVec instructions */ 17489 17490 opc2 = IFIELD(theInstr, 0, 6); 17491 switch (opc2) { 17492 /* AV Mult-Add, Mult-Sum */ 17493 case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm 17494 case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm 17495 case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs 17496 if (!allow_V) goto decode_noV; 17497 if (dis_av_multarith( theInstr )) goto decode_success; 17498 goto decode_failure; 17499 17500 /* AV Permutations */ 17501 case 0x2A: // vsel 17502 case 0x2B: // vperm 17503 case 0x2C: // vsldoi 17504 if (!allow_V) goto decode_noV; 17505 if (dis_av_permute( theInstr )) goto decode_success; 17506 goto decode_failure; 17507 17508 /* AV Floating Point Mult-Add/Sub */ 17509 case 0x2E: case 0x2F: // vmaddfp, vnmsubfp 17510 if (!allow_V) goto decode_noV; 17511 if (dis_av_fp_arith( theInstr )) goto decode_success; 17512 goto decode_failure; 17513 17514 default: 17515 break; // Fall through... 17516 } 17517 17518 opc2 = IFIELD(theInstr, 0, 11); 17519 switch (opc2) { 17520 /* AV Arithmetic */ 17521 case 0x180: // vaddcuw 17522 case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm 17523 case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws 17524 case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws 17525 case 0x580: // vsubcuw 17526 case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm 17527 case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws 17528 case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws 17529 case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw 17530 case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw 17531 case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw 17532 case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw 17533 case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw 17534 case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw 17535 case 0x008: case 0x048: // vmuloub, vmulouh 17536 case 0x108: case 0x148: // vmulosb, vmulosh 17537 case 0x208: case 0x248: // vmuleub, vmuleuh 17538 case 0x308: case 0x348: // vmulesb, vmulesh 17539 case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs 17540 case 0x688: case 0x788: // vsum2sws, vsumsws 17541 if (!allow_V) goto decode_noV; 17542 if (dis_av_arith( theInstr )) goto decode_success; 17543 goto decode_failure; 17544 17545 /* AV Rotate, Shift */ 17546 case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw 17547 case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw 17548 case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw 17549 case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw 17550 case 0x1C4: case 0x2C4: // vsl, vsr 17551 case 0x40C: case 0x44C: // vslo, vsro 17552 if (!allow_V) goto decode_noV; 17553 if (dis_av_shift( theInstr )) goto decode_success; 17554 goto decode_failure; 17555 17556 /* AV Logic */ 17557 case 0x404: case 0x444: case 0x484: // vand, vandc, vor 17558 case 0x4C4: case 0x504: // vxor, vnor 17559 if (!allow_V) goto decode_noV; 17560 if (dis_av_logic( theInstr )) goto decode_success; 17561 goto decode_failure; 17562 17563 /* AV Processor Control */ 17564 case 0x604: case 0x644: // mfvscr, mtvscr 17565 if (!allow_V) goto decode_noV; 17566 if (dis_av_procctl( theInstr )) goto decode_success; 17567 goto decode_failure; 17568 17569 /* AV Floating Point Arithmetic */ 17570 case 0x00A: case 0x04A: // vaddfp, vsubfp 17571 case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp 17572 case 0x1CA: // vlogefp 17573 case 0x40A: case 0x44A: // vmaxfp, vminfp 17574 if (!allow_V) goto decode_noV; 17575 if (dis_av_fp_arith( theInstr )) goto decode_success; 17576 goto decode_failure; 17577 17578 /* AV Floating Point Round/Convert */ 17579 case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip 17580 case 0x2CA: // vrfim 17581 case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs 17582 case 0x3CA: // vctsxs 17583 if (!allow_V) goto decode_noV; 17584 if (dis_av_fp_convert( theInstr )) goto decode_success; 17585 goto decode_failure; 17586 17587 /* AV Merge, Splat */ 17588 case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw 17589 case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw 17590 case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw 17591 case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw 17592 if (!allow_V) goto decode_noV; 17593 if (dis_av_permute( theInstr )) goto decode_success; 17594 goto decode_failure; 17595 17596 /* AV Pack, Unpack */ 17597 case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus 17598 case 0x0CE: // vpkuwus 17599 case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss 17600 case 0x1CE: // vpkswss 17601 case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb 17602 case 0x2CE: // vupklsh 17603 case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx 17604 if (!allow_V) goto decode_noV; 17605 if (dis_av_pack( theInstr )) goto decode_success; 17606 goto decode_failure; 17607 17608 default: 17609 break; // Fall through... 17610 } 17611 17612 opc2 = IFIELD(theInstr, 0, 10); 17613 switch (opc2) { 17614 17615 /* AV Compare */ 17616 case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw 17617 case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw 17618 case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw 17619 if (!allow_V) goto decode_noV; 17620 if (dis_av_cmp( theInstr )) goto decode_success; 17621 goto decode_failure; 17622 17623 /* AV Floating Point Compare */ 17624 case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp 17625 case 0x3C6: // vcmpbfp 17626 if (!allow_V) goto decode_noV; 17627 if (dis_av_fp_cmp( theInstr )) goto decode_success; 17628 goto decode_failure; 17629 17630 default: 17631 goto decode_failure; 17632 } 17633 break; 17634 17635 default: 17636 goto decode_failure; 17637 17638 decode_noF: 17639 vassert(!allow_F); 17640 vex_printf("disInstr(ppc): declined to decode an FP insn.\n"); 17641 goto decode_failure; 17642 decode_noV: 17643 vassert(!allow_V); 17644 vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n"); 17645 goto decode_failure; 17646 decode_noVX: 17647 vassert(!allow_VX); 17648 vex_printf("disInstr(ppc): declined to decode a Power ISA 2.06 insn.\n"); 17649 goto decode_failure; 17650 decode_noFX: 17651 vassert(!allow_FX); 17652 vex_printf("disInstr(ppc): " 17653 "declined to decode a GeneralPurpose-Optional insn.\n"); 17654 goto decode_failure; 17655 decode_noGX: 17656 vassert(!allow_GX); 17657 vex_printf("disInstr(ppc): " 17658 "declined to decode a Graphics-Optional insn.\n"); 17659 goto decode_failure; 17660 decode_noDFP: 17661 vassert(!allow_DFP); 17662 vex_printf("disInstr(ppc): " 17663 "declined to decode a Decimal Floating Point insn.\n"); 17664 goto decode_failure; 17665 17666 17667 decode_failure: 17668 /* All decode failures end up here. */ 17669 opc2 = (theInstr) & 0x7FF; 17670 vex_printf("disInstr(ppc): unhandled instruction: " 17671 "0x%x\n", theInstr); 17672 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n", 17673 opc1, opc1, opc2, opc2); 17674 17675 /* Tell the dispatcher that this insn cannot be decoded, and so has 17676 not been executed, and (is currently) the next to be executed. 17677 CIA should be up-to-date since it made so at the start of each 17678 insn, but nevertheless be paranoid and update it again right 17679 now. */ 17680 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) ); 17681 dres.whatNext = Dis_StopHere; 17682 dres.jk_StopHere = Ijk_NoDecode; 17683 dres.len = 0; 17684 return dres; 17685 17686 } /* switch (opc) for the main (primary) opcode switch. */ 17687 17688 decode_success: 17689 /* All decode successes end up here. */ 17690 switch (dres.whatNext) { 17691 case Dis_Continue: 17692 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4)); 17693 break; 17694 case Dis_ResteerU: 17695 case Dis_ResteerC: 17696 putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt)); 17697 break; 17698 case Dis_StopHere: 17699 break; 17700 default: 17701 vassert(0); 17702 } 17703 DIP("\n"); 17704 17705 if (dres.len == 0) { 17706 dres.len = 4; 17707 } else { 17708 vassert(dres.len == 20); 17709 } 17710 return dres; 17711 } 17712 17713 #undef DIP 17714 #undef DIS 17715 17716 17717 /*------------------------------------------------------------*/ 17718 /*--- Top-level fn ---*/ 17719 /*------------------------------------------------------------*/ 17720 17721 /* Disassemble a single instruction into IR. The instruction 17722 is located in host memory at &guest_code[delta]. */ 17723 17724 DisResult disInstr_PPC ( IRSB* irsb_IN, 17725 Bool (*resteerOkFn) ( void*, Addr64 ), 17726 Bool resteerCisOk, 17727 void* callback_opaque, 17728 UChar* guest_code_IN, 17729 Long delta, 17730 Addr64 guest_IP, 17731 VexArch guest_arch, 17732 VexArchInfo* archinfo, 17733 VexAbiInfo* abiinfo, 17734 Bool host_bigendian_IN ) 17735 { 17736 IRType ty; 17737 DisResult dres; 17738 UInt mask32, mask64; 17739 UInt hwcaps_guest = archinfo->hwcaps; 17740 17741 vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64); 17742 17743 /* global -- ick */ 17744 mode64 = guest_arch == VexArchPPC64; 17745 ty = mode64 ? Ity_I64 : Ity_I32; 17746 17747 /* do some sanity checks */ 17748 mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V 17749 | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX 17750 | VEX_HWCAPS_PPC32_DFP; 17751 17752 mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX 17753 | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP; 17754 17755 if (mode64) { 17756 vassert((hwcaps_guest & mask32) == 0); 17757 } else { 17758 vassert((hwcaps_guest & mask64) == 0); 17759 } 17760 17761 /* Set globals (see top of this file) */ 17762 guest_code = guest_code_IN; 17763 irsb = irsb_IN; 17764 host_is_bigendian = host_bigendian_IN; 17765 17766 guest_CIA_curr_instr = mkSzAddr(ty, guest_IP); 17767 guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta); 17768 17769 dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque, 17770 delta, archinfo, abiinfo ); 17771 17772 return dres; 17773 } 17774 17775 17776 /*------------------------------------------------------------*/ 17777 /*--- Unused stuff ---*/ 17778 /*------------------------------------------------------------*/ 17779 17780 ///* A potentially more memcheck-friendly implementation of Clz32, with 17781 // the boundary case Clz32(0) = 32, which is what ppc requires. */ 17782 // 17783 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg ) 17784 //{ 17785 // /* Welcome ... to SSA R Us. */ 17786 // IRTemp n1 = newTemp(Ity_I32); 17787 // IRTemp n2 = newTemp(Ity_I32); 17788 // IRTemp n3 = newTemp(Ity_I32); 17789 // IRTemp n4 = newTemp(Ity_I32); 17790 // IRTemp n5 = newTemp(Ity_I32); 17791 // IRTemp n6 = newTemp(Ity_I32); 17792 // IRTemp n7 = newTemp(Ity_I32); 17793 // IRTemp n8 = newTemp(Ity_I32); 17794 // IRTemp n9 = newTemp(Ity_I32); 17795 // IRTemp n10 = newTemp(Ity_I32); 17796 // IRTemp n11 = newTemp(Ity_I32); 17797 // IRTemp n12 = newTemp(Ity_I32); 17798 // 17799 // /* First, propagate the most significant 1-bit into all lower 17800 // positions in the word. */ 17801 // /* unsigned int clz ( unsigned int n ) 17802 // { 17803 // n |= (n >> 1); 17804 // n |= (n >> 2); 17805 // n |= (n >> 4); 17806 // n |= (n >> 8); 17807 // n |= (n >> 16); 17808 // return bitcount(~n); 17809 // } 17810 // */ 17811 // assign(n1, mkexpr(arg)); 17812 // assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1)))); 17813 // assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2)))); 17814 // assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4)))); 17815 // assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8)))); 17816 // assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16)))); 17817 // /* This gives a word of the form 0---01---1. Now invert it, giving 17818 // a word of the form 1---10---0, then do a population-count idiom 17819 // (to count the 1s, which is the number of leading zeroes, or 32 17820 // if the original word was 0. */ 17821 // assign(n7, unop(Iop_Not32, mkexpr(n6))); 17822 // 17823 // /* unsigned int bitcount ( unsigned int n ) 17824 // { 17825 // n = n - ((n >> 1) & 0x55555555); 17826 // n = (n & 0x33333333) + ((n >> 2) & 0x33333333); 17827 // n = (n + (n >> 4)) & 0x0F0F0F0F; 17828 // n = n + (n >> 8); 17829 // n = (n + (n >> 16)) & 0x3F; 17830 // return n; 17831 // } 17832 // */ 17833 // assign(n8, 17834 // binop(Iop_Sub32, 17835 // mkexpr(n7), 17836 // binop(Iop_And32, 17837 // binop(Iop_Shr32, mkexpr(n7), mkU8(1)), 17838 // mkU32(0x55555555)))); 17839 // assign(n9, 17840 // binop(Iop_Add32, 17841 // binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)), 17842 // binop(Iop_And32, 17843 // binop(Iop_Shr32, mkexpr(n8), mkU8(2)), 17844 // mkU32(0x33333333)))); 17845 // assign(n10, 17846 // binop(Iop_And32, 17847 // binop(Iop_Add32, 17848 // mkexpr(n9), 17849 // binop(Iop_Shr32, mkexpr(n9), mkU8(4))), 17850 // mkU32(0x0F0F0F0F))); 17851 // assign(n11, 17852 // binop(Iop_Add32, 17853 // mkexpr(n10), 17854 // binop(Iop_Shr32, mkexpr(n10), mkU8(8)))); 17855 // assign(n12, 17856 // binop(Iop_Add32, 17857 // mkexpr(n11), 17858 // binop(Iop_Shr32, mkexpr(n11), mkU8(16)))); 17859 // return 17860 // binop(Iop_And32, mkexpr(n12), mkU32(0x3F)); 17861 //} 17862 17863 /*--------------------------------------------------------------------*/ 17864 /*--- end guest_ppc_toIR.c ---*/ 17865 /*--------------------------------------------------------------------*/ 17866