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-2013 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 - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c) 74 ignores the rounding mode, and generates code that assumes 75 round-to-nearest. This means V will compute incorrect results 76 for uses of these IROps when the rounding mode (first) arg is 77 not mkU32(Irrm_NEAREST). 78 */ 79 80 /* "Special" instructions. 81 82 This instruction decoder can decode four special instructions 83 which mean nothing natively (are no-ops as far as regs/mem are 84 concerned) but have meaning for supporting Valgrind. A special 85 instruction is flagged by a 16-byte preamble: 86 87 32-bit mode: 5400183E 5400683E 5400E83E 5400983E 88 (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31; 89 rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31) 90 91 64-bit mode: 78001800 78006800 7800E802 78009802 92 (rotldi 0,0,3; rotldi 0,0,13; 93 rotldi 0,0,61; rotldi 0,0,51) 94 95 Following that, one of the following 3 are allowed 96 (standard interpretation in parentheses): 97 98 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 ) 99 7C421378 (or 2,2,2) %R3 = guest_NRADDR 100 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 101 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2 102 7CA52B78 (or 5,5,5) IR injection 103 104 Any other bytes following the 16-byte preamble are illegal and 105 constitute a failure in instruction decoding. This all assumes 106 that the preamble will never occur except in specific code 107 fragments designed for Valgrind to catch. 108 */ 109 110 111 /* Translates PPC32/64 code to IR. */ 112 113 /* References 114 115 #define PPC32 116 "PowerPC Microprocessor Family: 117 The Programming Environments Manual for 32-Bit Microprocessors" 118 02/21/2000 119 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2 120 121 #define PPC64 122 "PowerPC Microprocessor Family: 123 Programming Environments Manual for 64-Bit Microprocessors" 124 06/10/2003 125 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797 126 127 #define AV 128 "PowerPC Microprocessor Family: 129 AltiVec(TM) Technology Programming Environments Manual" 130 07/10/2003 131 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D 132 */ 133 134 #include "libvex_basictypes.h" 135 #include "libvex_ir.h" 136 #include "libvex.h" 137 #include "libvex_emnote.h" 138 #include "libvex_guest_ppc32.h" 139 #include "libvex_guest_ppc64.h" 140 141 #include "main_util.h" 142 #include "main_globals.h" 143 #include "guest_generic_bb_to_IR.h" 144 #include "guest_ppc_defs.h" 145 146 147 /*------------------------------------------------------------*/ 148 /*--- Globals ---*/ 149 /*------------------------------------------------------------*/ 150 151 /* These are set at the start of the translation of an insn, right 152 down in disInstr_PPC, so that we don't have to pass them around 153 endlessly. They are all constant during the translation of any 154 given insn. */ 155 156 /* We need to know this to do sub-register accesses correctly. */ 157 static Bool host_is_bigendian; 158 159 /* Pointer to the guest code area. */ 160 static UChar* guest_code; 161 162 /* The guest address corresponding to guest_code[0]. */ 163 static Addr64 guest_CIA_bbstart; 164 165 /* The guest address for the instruction currently being 166 translated. */ 167 static Addr64 guest_CIA_curr_instr; 168 169 /* The IRSB* into which we're generating code. */ 170 static IRSB* irsb; 171 172 /* Is our guest binary 32 or 64bit? Set at each call to 173 disInstr_PPC below. */ 174 static Bool mode64 = False; 175 176 // Given a pointer to a function as obtained by "& functionname" in C, 177 // produce a pointer to the actual entry point for the function. For 178 // most platforms it's the identity function. Unfortunately, on 179 // ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and 180 // ppc64-aix5. 181 static void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f ) 182 { 183 if (vbi->host_ppc_calls_use_fndescrs) { 184 /* f is a pointer to a 3-word function descriptor, of which the 185 first word is the entry address. */ 186 /* note, this is correct even with cross-jitting, since this is 187 purely a host issue, not a guest one. */ 188 HWord* fdescr = (HWord*)f; 189 return (void*)(fdescr[0]); 190 } else { 191 /* Simple; "& f" points directly at the code for f. */ 192 return f; 193 } 194 } 195 196 #define SIGN_BIT 0x8000000000000000ULL 197 #define SIGN_MASK 0x7fffffffffffffffULL 198 #define SIGN_BIT32 0x80000000 199 #define SIGN_MASK32 0x7fffffff 200 201 202 /*------------------------------------------------------------*/ 203 /*--- Debugging output ---*/ 204 /*------------------------------------------------------------*/ 205 206 #define DIP(format, args...) \ 207 if (vex_traceflags & VEX_TRACE_FE) \ 208 vex_printf(format, ## args) 209 210 #define DIS(buf, format, args...) \ 211 if (vex_traceflags & VEX_TRACE_FE) \ 212 vex_sprintf(buf, format, ## args) 213 214 215 /*------------------------------------------------------------*/ 216 /*--- Offsets of various parts of the ppc32/64 guest state ---*/ 217 /*------------------------------------------------------------*/ 218 219 #define offsetofPPCGuestState(_x) \ 220 (mode64 ? offsetof(VexGuestPPC64State, _x) : \ 221 offsetof(VexGuestPPC32State, _x)) 222 223 #define OFFB_CIA offsetofPPCGuestState(guest_CIA) 224 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL) 225 #define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO) 226 #define OFFB_LR offsetofPPCGuestState(guest_LR) 227 #define OFFB_CTR offsetofPPCGuestState(guest_CTR) 228 #define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO) 229 #define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV) 230 #define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA) 231 #define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC) 232 #define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND) 233 #define OFFB_DFPROUND offsetofPPCGuestState(guest_DFPROUND) 234 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE) 235 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR) 236 #define OFFB_EMNOTE offsetofPPCGuestState(guest_EMNOTE) 237 #define OFFB_CMSTART offsetofPPCGuestState(guest_CMSTART) 238 #define OFFB_CMLEN offsetofPPCGuestState(guest_CMLEN) 239 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) 240 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2) 241 #define OFFB_TFHAR offsetofPPCGuestState(guest_TFHAR) 242 #define OFFB_TEXASR offsetofPPCGuestState(guest_TEXASR) 243 #define OFFB_TFIAR offsetofPPCGuestState(guest_TFIAR) 244 245 246 /*------------------------------------------------------------*/ 247 /*--- Extract instruction fields --- */ 248 /*------------------------------------------------------------*/ 249 250 /* Extract field from insn, given idx (zero = lsb) and field length */ 251 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1)) 252 253 /* Extract primary opcode, instr[31:26] */ 254 static UChar ifieldOPC( UInt instr ) { 255 return toUChar( IFIELD( instr, 26, 6 ) ); 256 } 257 258 /* Extract 10-bit secondary opcode, instr[10:1] */ 259 static UInt ifieldOPClo10 ( UInt instr) { 260 return IFIELD( instr, 1, 10 ); 261 } 262 263 /* Extract 9-bit secondary opcode, instr[9:1] */ 264 static UInt ifieldOPClo9 ( UInt instr) { 265 return IFIELD( instr, 1, 9 ); 266 } 267 268 /* Extract 8-bit secondary opcode, instr[8:1] */ 269 static UInt ifieldOPClo8 ( UInt instr) { 270 return IFIELD( instr, 1, 8 ); 271 } 272 273 /* Extract 5-bit secondary opcode, instr[5:1] */ 274 static UInt ifieldOPClo5 ( UInt instr) { 275 return IFIELD( instr, 1, 5 ); 276 } 277 278 /* Extract RD (destination register) field, instr[25:21] */ 279 static UChar ifieldRegDS( UInt instr ) { 280 return toUChar( IFIELD( instr, 21, 5 ) ); 281 } 282 283 /* Extract XT (destination register) field, instr[0,25:21] */ 284 static UChar ifieldRegXT ( UInt instr ) 285 { 286 UChar upper_bit = toUChar (IFIELD (instr, 0, 1)); 287 UChar lower_bits = toUChar (IFIELD (instr, 21, 5)); 288 return (upper_bit << 5) | lower_bits; 289 } 290 291 /* Extract XS (store source register) field, instr[0,25:21] */ 292 static inline UChar ifieldRegXS ( UInt instr ) 293 { 294 return ifieldRegXT ( instr ); 295 } 296 297 /* Extract RA (1st source register) field, instr[20:16] */ 298 static UChar ifieldRegA ( UInt instr ) { 299 return toUChar( IFIELD( instr, 16, 5 ) ); 300 } 301 302 /* Extract XA (1st source register) field, instr[2,20:16] */ 303 static UChar ifieldRegXA ( UInt instr ) 304 { 305 UChar upper_bit = toUChar (IFIELD (instr, 2, 1)); 306 UChar lower_bits = toUChar (IFIELD (instr, 16, 5)); 307 return (upper_bit << 5) | lower_bits; 308 } 309 310 /* Extract RB (2nd source register) field, instr[15:11] */ 311 static UChar ifieldRegB ( UInt instr ) { 312 return toUChar( IFIELD( instr, 11, 5 ) ); 313 } 314 315 /* Extract XB (2nd source register) field, instr[1,15:11] */ 316 static UChar ifieldRegXB ( UInt instr ) 317 { 318 UChar upper_bit = toUChar (IFIELD (instr, 1, 1)); 319 UChar lower_bits = toUChar (IFIELD (instr, 11, 5)); 320 return (upper_bit << 5) | lower_bits; 321 } 322 323 /* Extract RC (3rd source register) field, instr[10:6] */ 324 static UChar ifieldRegC ( UInt instr ) { 325 return toUChar( IFIELD( instr, 6, 5 ) ); 326 } 327 328 /* Extract XC (3rd source register) field, instr[3,10:6] */ 329 static UChar ifieldRegXC ( UInt instr ) 330 { 331 UChar upper_bit = toUChar (IFIELD (instr, 3, 1)); 332 UChar lower_bits = toUChar (IFIELD (instr, 6, 5)); 333 return (upper_bit << 5) | lower_bits; 334 } 335 336 /* Extract bit 10, instr[10] */ 337 static UChar ifieldBIT10 ( UInt instr ) { 338 return toUChar( IFIELD( instr, 10, 1 ) ); 339 } 340 341 /* Extract 2nd lowest bit, instr[1] */ 342 static UChar ifieldBIT1 ( UInt instr ) { 343 return toUChar( IFIELD( instr, 1, 1 ) ); 344 } 345 346 /* Extract lowest bit, instr[0] */ 347 static UChar ifieldBIT0 ( UInt instr ) { 348 return toUChar( instr & 0x1 ); 349 } 350 351 /* Extract unsigned bottom half, instr[15:0] */ 352 static UInt ifieldUIMM16 ( UInt instr ) { 353 return instr & 0xFFFF; 354 } 355 356 /* Extract unsigned bottom 26 bits, instr[25:0] */ 357 static UInt ifieldUIMM26 ( UInt instr ) { 358 return instr & 0x3FFFFFF; 359 } 360 361 /* Extract DM field, instr[9:8] */ 362 static UChar ifieldDM ( UInt instr ) { 363 return toUChar( IFIELD( instr, 8, 2 ) ); 364 } 365 366 /* Extract SHW field, instr[9:8] */ 367 static inline UChar ifieldSHW ( UInt instr ) 368 { 369 return ifieldDM ( instr ); 370 } 371 372 /*------------------------------------------------------------*/ 373 /*--- Guest-state identifiers ---*/ 374 /*------------------------------------------------------------*/ 375 376 typedef enum { 377 PPC_GST_CIA, // Current Instruction Address 378 PPC_GST_LR, // Link Register 379 PPC_GST_CTR, // Count Register 380 PPC_GST_XER, // Overflow, carry flags, byte count 381 PPC_GST_CR, // Condition Register 382 PPC_GST_FPSCR, // Floating Point Status/Control Register 383 PPC_GST_VRSAVE, // Vector Save/Restore Register 384 PPC_GST_VSCR, // Vector Status and Control Register 385 PPC_GST_EMWARN, // Emulation warnings 386 PPC_GST_CMSTART,// For icbi: start of area to invalidate 387 PPC_GST_CMLEN, // For icbi: length of area to invalidate 388 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn 389 PPC_GST_SPRG3_RO, // SPRG3 390 PPC_GST_TFHAR, // Transactional Failure Handler Address Register 391 PPC_GST_TFIAR, // Transactional Failure Instruction Address Register 392 PPC_GST_TEXASR, // Transactional EXception And Summary Register 393 PPC_GST_MAX 394 } PPC_GST; 395 396 #define MASK_FPSCR_RN 0x3ULL // Binary floating point rounding mode 397 #define MASK_FPSCR_DRN 0x700000000ULL // Decimal floating point rounding mode 398 #define MASK_VSCR_VALID 0x00010001 399 400 401 /*------------------------------------------------------------*/ 402 /*--- FP Helpers ---*/ 403 /*------------------------------------------------------------*/ 404 405 /* Produce the 32-bit pattern corresponding to the supplied 406 float. */ 407 static UInt float_to_bits ( Float f ) 408 { 409 union { UInt i; Float f; } u; 410 vassert(4 == sizeof(UInt)); 411 vassert(4 == sizeof(Float)); 412 vassert(4 == sizeof(u)); 413 u.f = f; 414 return u.i; 415 } 416 417 418 /*------------------------------------------------------------*/ 419 /*--- Misc Helpers ---*/ 420 /*------------------------------------------------------------*/ 421 422 /* Generate mask with 1's from 'begin' through 'end', 423 wrapping if begin > end. 424 begin->end works from right to left, 0=lsb 425 */ 426 static UInt MASK32( UInt begin, UInt end ) 427 { 428 UInt m1, m2, mask; 429 vassert(begin < 32); 430 vassert(end < 32); 431 m1 = ((UInt)(-1)) << begin; 432 m2 = ((UInt)(-1)) << end << 1; 433 mask = m1 ^ m2; 434 if (begin > end) mask = ~mask; // wrap mask 435 return mask; 436 } 437 438 static ULong MASK64( UInt begin, UInt end ) 439 { 440 ULong m1, m2, mask; 441 vassert(begin < 64); 442 vassert(end < 64); 443 m1 = ((ULong)(-1)) << begin; 444 m2 = ((ULong)(-1)) << end << 1; 445 mask = m1 ^ m2; 446 if (begin > end) mask = ~mask; // wrap mask 447 return mask; 448 } 449 450 static Addr64 nextInsnAddr( void ) 451 { 452 return guest_CIA_curr_instr + 4; 453 } 454 455 456 /*------------------------------------------------------------*/ 457 /*--- Helper bits and pieces for deconstructing the ---*/ 458 /*--- ppc32/64 insn stream. ---*/ 459 /*------------------------------------------------------------*/ 460 461 /* Add a statement to the list held by "irsb". */ 462 static void stmt ( IRStmt* st ) 463 { 464 addStmtToIRSB( irsb, st ); 465 } 466 467 /* Generate a new temporary of the given type. */ 468 static IRTemp newTemp ( IRType ty ) 469 { 470 vassert(isPlausibleIRType(ty)); 471 return newIRTemp( irsb->tyenv, ty ); 472 } 473 474 /* Various simple conversions */ 475 476 static UChar extend_s_5to8 ( UChar x ) 477 { 478 return toUChar((((Int)x) << 27) >> 27); 479 } 480 481 static UInt extend_s_8to32( UChar x ) 482 { 483 return (UInt)((((Int)x) << 24) >> 24); 484 } 485 486 static UInt extend_s_16to32 ( UInt x ) 487 { 488 return (UInt)((((Int)x) << 16) >> 16); 489 } 490 491 static ULong extend_s_16to64 ( UInt x ) 492 { 493 return (ULong)((((Long)x) << 48) >> 48); 494 } 495 496 static ULong extend_s_26to64 ( UInt x ) 497 { 498 return (ULong)((((Long)x) << 38) >> 38); 499 } 500 501 static ULong extend_s_32to64 ( UInt x ) 502 { 503 return (ULong)((((Long)x) << 32) >> 32); 504 } 505 506 /* Do a big-endian load of a 32-bit word, regardless of the endianness 507 of the underlying host. */ 508 static UInt getUIntBigendianly ( UChar* p ) 509 { 510 UInt w = 0; 511 w = (w << 8) | p[0]; 512 w = (w << 8) | p[1]; 513 w = (w << 8) | p[2]; 514 w = (w << 8) | p[3]; 515 return w; 516 } 517 518 519 /*------------------------------------------------------------*/ 520 /*--- Helpers for constructing IR. ---*/ 521 /*------------------------------------------------------------*/ 522 523 static void assign ( IRTemp dst, IRExpr* e ) 524 { 525 stmt( IRStmt_WrTmp(dst, e) ); 526 } 527 528 /* This generates a normal (non store-conditional) store. */ 529 static void storeBE ( IRExpr* addr, IRExpr* data ) 530 { 531 IRType tyA = typeOfIRExpr(irsb->tyenv, addr); 532 vassert(tyA == Ity_I32 || tyA == Ity_I64); 533 stmt( IRStmt_Store(Iend_BE, addr, data) ); 534 } 535 536 static IRExpr* unop ( IROp op, IRExpr* a ) 537 { 538 return IRExpr_Unop(op, a); 539 } 540 541 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 542 { 543 return IRExpr_Binop(op, a1, a2); 544 } 545 546 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 547 { 548 return IRExpr_Triop(op, a1, a2, a3); 549 } 550 551 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2, 552 IRExpr* a3, IRExpr* a4 ) 553 { 554 return IRExpr_Qop(op, a1, a2, a3, a4); 555 } 556 557 static IRExpr* mkexpr ( IRTemp tmp ) 558 { 559 return IRExpr_RdTmp(tmp); 560 } 561 562 static IRExpr* mkU8 ( UChar i ) 563 { 564 return IRExpr_Const(IRConst_U8(i)); 565 } 566 567 static IRExpr* mkU16 ( UInt i ) 568 { 569 return IRExpr_Const(IRConst_U16(i)); 570 } 571 572 static IRExpr* mkU32 ( UInt i ) 573 { 574 return IRExpr_Const(IRConst_U32(i)); 575 } 576 577 static IRExpr* mkU64 ( ULong i ) 578 { 579 return IRExpr_Const(IRConst_U64(i)); 580 } 581 582 static IRExpr* mkV128 ( UShort i ) 583 { 584 vassert(i == 0 || i == 0xffff); 585 return IRExpr_Const(IRConst_V128(i)); 586 } 587 588 /* This generates a normal (non load-linked) load. */ 589 static IRExpr* loadBE ( IRType ty, IRExpr* addr ) 590 { 591 return IRExpr_Load(Iend_BE, ty, addr); 592 } 593 594 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 ) 595 { 596 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 597 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 598 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1), 599 unop(Iop_1Uto32, arg2))); 600 } 601 602 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 ) 603 { 604 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1); 605 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1); 606 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1), 607 unop(Iop_1Uto32, arg2))); 608 } 609 610 /* expand V128_8Ux16 to 2x V128_16Ux8's */ 611 static void expand8Ux16( IRExpr* vIn, 612 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 613 { 614 IRTemp ones8x16 = newTemp(Ity_V128); 615 616 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 617 vassert(vEvn && *vEvn == IRTemp_INVALID); 618 vassert(vOdd && *vOdd == IRTemp_INVALID); 619 *vEvn = newTemp(Ity_V128); 620 *vOdd = newTemp(Ity_V128); 621 622 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 623 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) ); 624 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 625 binop(Iop_ShrV128, vIn, mkU8(8))) ); 626 } 627 628 /* expand V128_8Sx16 to 2x V128_16Sx8's */ 629 static void expand8Sx16( IRExpr* vIn, 630 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 631 { 632 IRTemp ones8x16 = newTemp(Ity_V128); 633 634 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 635 vassert(vEvn && *vEvn == IRTemp_INVALID); 636 vassert(vOdd && *vOdd == IRTemp_INVALID); 637 *vEvn = newTemp(Ity_V128); 638 *vOdd = newTemp(Ity_V128); 639 640 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) ); 641 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) ); 642 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 643 binop(Iop_ShrV128, vIn, mkU8(8))) ); 644 } 645 646 /* expand V128_16Uto8 to 2x V128_32Ux4's */ 647 static void expand16Ux8( IRExpr* vIn, 648 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 649 { 650 IRTemp ones16x8 = newTemp(Ity_V128); 651 652 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 653 vassert(vEvn && *vEvn == IRTemp_INVALID); 654 vassert(vOdd && *vOdd == IRTemp_INVALID); 655 *vEvn = newTemp(Ity_V128); 656 *vOdd = newTemp(Ity_V128); 657 658 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 659 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) ); 660 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 661 binop(Iop_ShrV128, vIn, mkU8(16))) ); 662 } 663 664 /* expand V128_16Sto8 to 2x V128_32Sx4's */ 665 static void expand16Sx8( IRExpr* vIn, 666 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd ) 667 { 668 IRTemp ones16x8 = newTemp(Ity_V128); 669 670 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128); 671 vassert(vEvn && *vEvn == IRTemp_INVALID); 672 vassert(vOdd && *vOdd == IRTemp_INVALID); 673 *vEvn = newTemp(Ity_V128); 674 *vOdd = newTemp(Ity_V128); 675 676 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) ); 677 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) ); 678 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 679 binop(Iop_ShrV128, vIn, mkU8(16))) ); 680 } 681 682 /* break V128 to 4xF64's*/ 683 static void breakV128to4xF64( IRExpr* t128, 684 /*OUTs*/ 685 IRTemp* t3, IRTemp* t2, 686 IRTemp* t1, IRTemp* t0 ) 687 { 688 IRTemp hi64 = newTemp(Ity_I64); 689 IRTemp lo64 = newTemp(Ity_I64); 690 691 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 692 vassert(t0 && *t0 == IRTemp_INVALID); 693 vassert(t1 && *t1 == IRTemp_INVALID); 694 vassert(t2 && *t2 == IRTemp_INVALID); 695 vassert(t3 && *t3 == IRTemp_INVALID); 696 *t0 = newTemp(Ity_F64); 697 *t1 = newTemp(Ity_F64); 698 *t2 = newTemp(Ity_F64); 699 *t3 = newTemp(Ity_F64); 700 701 assign( hi64, unop(Iop_V128HIto64, t128) ); 702 assign( lo64, unop(Iop_V128to64, t128) ); 703 assign( *t3, 704 unop( Iop_F32toF64, 705 unop( Iop_ReinterpI32asF32, 706 unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) ); 707 assign( *t2, 708 unop( Iop_F32toF64, 709 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) ); 710 assign( *t1, 711 unop( Iop_F32toF64, 712 unop( Iop_ReinterpI32asF32, 713 unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) ); 714 assign( *t0, 715 unop( Iop_F32toF64, 716 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) ); 717 } 718 719 720 /* break V128 to 4xI32's, then sign-extend to I64's */ 721 static void breakV128to4x64S( IRExpr* t128, 722 /*OUTs*/ 723 IRTemp* t3, IRTemp* t2, 724 IRTemp* t1, IRTemp* t0 ) 725 { 726 IRTemp hi64 = newTemp(Ity_I64); 727 IRTemp lo64 = newTemp(Ity_I64); 728 729 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 730 vassert(t0 && *t0 == IRTemp_INVALID); 731 vassert(t1 && *t1 == IRTemp_INVALID); 732 vassert(t2 && *t2 == IRTemp_INVALID); 733 vassert(t3 && *t3 == IRTemp_INVALID); 734 *t0 = newTemp(Ity_I64); 735 *t1 = newTemp(Ity_I64); 736 *t2 = newTemp(Ity_I64); 737 *t3 = newTemp(Ity_I64); 738 739 assign( hi64, unop(Iop_V128HIto64, t128) ); 740 assign( lo64, unop(Iop_V128to64, t128) ); 741 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 742 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) ); 743 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 744 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) ); 745 } 746 747 /* break V128 to 4xI32's, then zero-extend to I64's */ 748 static void breakV128to4x64U ( IRExpr* t128, 749 /*OUTs*/ 750 IRTemp* t3, IRTemp* t2, 751 IRTemp* t1, IRTemp* t0 ) 752 { 753 IRTemp hi64 = newTemp(Ity_I64); 754 IRTemp lo64 = newTemp(Ity_I64); 755 756 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 757 vassert(t0 && *t0 == IRTemp_INVALID); 758 vassert(t1 && *t1 == IRTemp_INVALID); 759 vassert(t2 && *t2 == IRTemp_INVALID); 760 vassert(t3 && *t3 == IRTemp_INVALID); 761 *t0 = newTemp(Ity_I64); 762 *t1 = newTemp(Ity_I64); 763 *t2 = newTemp(Ity_I64); 764 *t3 = newTemp(Ity_I64); 765 766 assign( hi64, unop(Iop_V128HIto64, t128) ); 767 assign( lo64, unop(Iop_V128to64, t128) ); 768 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) ); 769 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) ); 770 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) ); 771 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) ); 772 } 773 774 static void breakV128to4x32( IRExpr* t128, 775 /*OUTs*/ 776 IRTemp* t3, IRTemp* t2, 777 IRTemp* t1, IRTemp* t0 ) 778 { 779 IRTemp hi64 = newTemp(Ity_I64); 780 IRTemp lo64 = newTemp(Ity_I64); 781 782 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128); 783 vassert(t0 && *t0 == IRTemp_INVALID); 784 vassert(t1 && *t1 == IRTemp_INVALID); 785 vassert(t2 && *t2 == IRTemp_INVALID); 786 vassert(t3 && *t3 == IRTemp_INVALID); 787 *t0 = newTemp(Ity_I32); 788 *t1 = newTemp(Ity_I32); 789 *t2 = newTemp(Ity_I32); 790 *t3 = newTemp(Ity_I32); 791 792 assign( hi64, unop(Iop_V128HIto64, t128) ); 793 assign( lo64, unop(Iop_V128to64, t128) ); 794 assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) ); 795 assign( *t2, unop(Iop_64to32, mkexpr(hi64)) ); 796 assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) ); 797 assign( *t0, unop(Iop_64to32, mkexpr(lo64)) ); 798 } 799 800 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2, 801 IRTemp t1, IRTemp t0 ) 802 { 803 return 804 binop( Iop_64HLtoV128, 805 binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)), 806 binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0)) 807 ); 808 } 809 810 811 /* Signed saturating narrow 64S to 32 */ 812 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 ) 813 { 814 IRTemp hi32 = newTemp(Ity_I32); 815 IRTemp lo32 = newTemp(Ity_I32); 816 817 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 818 819 assign( hi32, unop(Iop_64HIto32, t64)); 820 assign( lo32, unop(Iop_64to32, t64)); 821 822 return IRExpr_ITE( 823 /* if (hi32 == (lo32 >>s 31)) */ 824 binop(Iop_CmpEQ32, mkexpr(hi32), 825 binop( Iop_Sar32, mkexpr(lo32), mkU8(31))), 826 /* then: within signed-32 range: lo half good enough */ 827 mkexpr(lo32), 828 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */ 829 binop(Iop_Add32, mkU32(0x7FFFFFFF), 830 binop(Iop_Shr32, mkexpr(hi32), mkU8(31)))); 831 } 832 833 /* Unsigned saturating narrow 64S to 32 */ 834 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 ) 835 { 836 IRTemp hi32 = newTemp(Ity_I32); 837 IRTemp lo32 = newTemp(Ity_I32); 838 839 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64); 840 841 assign( hi32, unop(Iop_64HIto32, t64)); 842 assign( lo32, unop(Iop_64to32, t64)); 843 844 return IRExpr_ITE( 845 /* if (top 32 bits of t64 are 0) */ 846 binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)), 847 /* then: within unsigned-32 range: lo half good enough */ 848 mkexpr(lo32), 849 /* else: positive saturate -> 0xFFFFFFFF */ 850 mkU32(0xFFFFFFFF)); 851 } 852 853 /* Signed saturate narrow 64->32, combining to V128 */ 854 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2, 855 IRExpr* t1, IRExpr* t0 ) 856 { 857 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 858 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 859 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 860 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 861 return binop(Iop_64HLtoV128, 862 binop(Iop_32HLto64, 863 mkQNarrow64Sto32( t3 ), 864 mkQNarrow64Sto32( t2 )), 865 binop(Iop_32HLto64, 866 mkQNarrow64Sto32( t1 ), 867 mkQNarrow64Sto32( t0 ))); 868 } 869 870 /* Unsigned saturate narrow 64->32, combining to V128 */ 871 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2, 872 IRExpr* t1, IRExpr* t0 ) 873 { 874 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64); 875 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64); 876 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64); 877 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64); 878 return binop(Iop_64HLtoV128, 879 binop(Iop_32HLto64, 880 mkQNarrow64Uto32( t3 ), 881 mkQNarrow64Uto32( t2 )), 882 binop(Iop_32HLto64, 883 mkQNarrow64Uto32( t1 ), 884 mkQNarrow64Uto32( t0 ))); 885 } 886 887 /* Simulate irops Iop_MullOdd*, since we don't have them */ 888 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \ 889 binop(Iop_MullEven8Ux16, \ 890 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 891 binop(Iop_ShrV128, expr_vB, mkU8(8))) 892 893 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \ 894 binop(Iop_MullEven8Sx16, \ 895 binop(Iop_ShrV128, expr_vA, mkU8(8)), \ 896 binop(Iop_ShrV128, expr_vB, mkU8(8))) 897 898 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \ 899 binop(Iop_MullEven16Ux8, \ 900 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 901 binop(Iop_ShrV128, expr_vB, mkU8(16))) 902 903 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \ 904 binop(Iop_MullEven32Ux4, \ 905 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 906 binop(Iop_ShrV128, expr_vB, mkU8(32))) 907 908 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \ 909 binop(Iop_MullEven16Sx8, \ 910 binop(Iop_ShrV128, expr_vA, mkU8(16)), \ 911 binop(Iop_ShrV128, expr_vB, mkU8(16))) 912 913 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \ 914 binop(Iop_MullEven32Sx4, \ 915 binop(Iop_ShrV128, expr_vA, mkU8(32)), \ 916 binop(Iop_ShrV128, expr_vB, mkU8(32))) 917 918 919 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src ) 920 { 921 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 922 return unop(Iop_32Sto64, unop(Iop_64to32, src)); 923 } 924 925 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src ) 926 { 927 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64); 928 return unop(Iop_32Uto64, unop(Iop_64to32, src)); 929 } 930 931 static IROp mkSzOp ( IRType ty, IROp op8 ) 932 { 933 Int adj; 934 vassert(ty == Ity_I8 || ty == Ity_I16 || 935 ty == Ity_I32 || ty == Ity_I64); 936 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || 937 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 || 938 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 || 939 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || 940 op8 == Iop_Not8 ); 941 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3)); 942 return adj + op8; 943 } 944 945 /* Make sure we get valid 32 and 64bit addresses */ 946 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 947 { 948 vassert(ty == Ity_I32 || ty == Ity_I64); 949 return ( ty == Ity_I64 ? 950 (Addr64)addr : 951 (Addr64)extend_s_32to64( toUInt(addr) ) ); 952 } 953 954 /* sz, ULong -> IRExpr */ 955 static IRExpr* mkSzImm ( IRType ty, ULong imm64 ) 956 { 957 vassert(ty == Ity_I32 || ty == Ity_I64); 958 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64); 959 } 960 961 /* sz, ULong -> IRConst */ 962 static IRConst* mkSzConst ( IRType ty, ULong imm64 ) 963 { 964 vassert(ty == Ity_I32 || ty == Ity_I64); 965 return ( ty == Ity_I64 ? 966 IRConst_U64(imm64) : 967 IRConst_U32((UInt)imm64) ); 968 } 969 970 /* Sign extend imm16 -> IRExpr* */ 971 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 ) 972 { 973 vassert(ty == Ity_I32 || ty == Ity_I64); 974 return ( ty == Ity_I64 ? 975 mkU64(extend_s_16to64(imm16)) : 976 mkU32(extend_s_16to32(imm16)) ); 977 } 978 979 /* Sign extend imm32 -> IRExpr* */ 980 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 ) 981 { 982 vassert(ty == Ity_I32 || ty == Ity_I64); 983 return ( ty == Ity_I64 ? 984 mkU64(extend_s_32to64(imm32)) : 985 mkU32(imm32) ); 986 } 987 988 /* IR narrows I32/I64 -> I8/I16/I32 */ 989 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src ) 990 { 991 vassert(ty == Ity_I32 || ty == Ity_I64); 992 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 993 } 994 995 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src ) 996 { 997 vassert(ty == Ity_I32 || ty == Ity_I64); 998 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src); 999 } 1000 1001 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src ) 1002 { 1003 vassert(ty == Ity_I32 || ty == Ity_I64); 1004 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 1005 } 1006 1007 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */ 1008 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined ) 1009 { 1010 IROp op; 1011 vassert(ty == Ity_I32 || ty == Ity_I64); 1012 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64; 1013 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64; 1014 return unop(op, src); 1015 } 1016 1017 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined ) 1018 { 1019 IROp op; 1020 vassert(ty == Ity_I32 || ty == Ity_I64); 1021 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64; 1022 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64; 1023 return unop(op, src); 1024 } 1025 1026 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined ) 1027 { 1028 vassert(ty == Ity_I32 || ty == Ity_I64); 1029 if (ty == Ity_I32) 1030 return src; 1031 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 1032 } 1033 1034 1035 static Int integerGuestRegOffset ( UInt archreg ) 1036 { 1037 vassert(archreg < 32); 1038 1039 // jrs: probably not necessary; only matters if we reference sub-parts 1040 // of the ppc registers, but that isn't the case 1041 // later: this might affect Altivec though? 1042 vassert(host_is_bigendian); 1043 1044 switch (archreg) { 1045 case 0: return offsetofPPCGuestState(guest_GPR0); 1046 case 1: return offsetofPPCGuestState(guest_GPR1); 1047 case 2: return offsetofPPCGuestState(guest_GPR2); 1048 case 3: return offsetofPPCGuestState(guest_GPR3); 1049 case 4: return offsetofPPCGuestState(guest_GPR4); 1050 case 5: return offsetofPPCGuestState(guest_GPR5); 1051 case 6: return offsetofPPCGuestState(guest_GPR6); 1052 case 7: return offsetofPPCGuestState(guest_GPR7); 1053 case 8: return offsetofPPCGuestState(guest_GPR8); 1054 case 9: return offsetofPPCGuestState(guest_GPR9); 1055 case 10: return offsetofPPCGuestState(guest_GPR10); 1056 case 11: return offsetofPPCGuestState(guest_GPR11); 1057 case 12: return offsetofPPCGuestState(guest_GPR12); 1058 case 13: return offsetofPPCGuestState(guest_GPR13); 1059 case 14: return offsetofPPCGuestState(guest_GPR14); 1060 case 15: return offsetofPPCGuestState(guest_GPR15); 1061 case 16: return offsetofPPCGuestState(guest_GPR16); 1062 case 17: return offsetofPPCGuestState(guest_GPR17); 1063 case 18: return offsetofPPCGuestState(guest_GPR18); 1064 case 19: return offsetofPPCGuestState(guest_GPR19); 1065 case 20: return offsetofPPCGuestState(guest_GPR20); 1066 case 21: return offsetofPPCGuestState(guest_GPR21); 1067 case 22: return offsetofPPCGuestState(guest_GPR22); 1068 case 23: return offsetofPPCGuestState(guest_GPR23); 1069 case 24: return offsetofPPCGuestState(guest_GPR24); 1070 case 25: return offsetofPPCGuestState(guest_GPR25); 1071 case 26: return offsetofPPCGuestState(guest_GPR26); 1072 case 27: return offsetofPPCGuestState(guest_GPR27); 1073 case 28: return offsetofPPCGuestState(guest_GPR28); 1074 case 29: return offsetofPPCGuestState(guest_GPR29); 1075 case 30: return offsetofPPCGuestState(guest_GPR30); 1076 case 31: return offsetofPPCGuestState(guest_GPR31); 1077 default: break; 1078 } 1079 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/ 1080 } 1081 1082 static IRExpr* getIReg ( UInt archreg ) 1083 { 1084 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1085 vassert(archreg < 32); 1086 return IRExpr_Get( integerGuestRegOffset(archreg), ty ); 1087 } 1088 1089 /* Ditto, but write to a reg instead. */ 1090 static void putIReg ( UInt archreg, IRExpr* e ) 1091 { 1092 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1093 vassert(archreg < 32); 1094 vassert(typeOfIRExpr(irsb->tyenv, e) == ty ); 1095 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) ); 1096 } 1097 1098 1099 /* Floating point egisters are mapped to VSX registers[0..31]. */ 1100 static Int floatGuestRegOffset ( UInt archreg ) 1101 { 1102 vassert(archreg < 32); 1103 1104 switch (archreg) { 1105 case 0: return offsetofPPCGuestState(guest_VSR0); 1106 case 1: return offsetofPPCGuestState(guest_VSR1); 1107 case 2: return offsetofPPCGuestState(guest_VSR2); 1108 case 3: return offsetofPPCGuestState(guest_VSR3); 1109 case 4: return offsetofPPCGuestState(guest_VSR4); 1110 case 5: return offsetofPPCGuestState(guest_VSR5); 1111 case 6: return offsetofPPCGuestState(guest_VSR6); 1112 case 7: return offsetofPPCGuestState(guest_VSR7); 1113 case 8: return offsetofPPCGuestState(guest_VSR8); 1114 case 9: return offsetofPPCGuestState(guest_VSR9); 1115 case 10: return offsetofPPCGuestState(guest_VSR10); 1116 case 11: return offsetofPPCGuestState(guest_VSR11); 1117 case 12: return offsetofPPCGuestState(guest_VSR12); 1118 case 13: return offsetofPPCGuestState(guest_VSR13); 1119 case 14: return offsetofPPCGuestState(guest_VSR14); 1120 case 15: return offsetofPPCGuestState(guest_VSR15); 1121 case 16: return offsetofPPCGuestState(guest_VSR16); 1122 case 17: return offsetofPPCGuestState(guest_VSR17); 1123 case 18: return offsetofPPCGuestState(guest_VSR18); 1124 case 19: return offsetofPPCGuestState(guest_VSR19); 1125 case 20: return offsetofPPCGuestState(guest_VSR20); 1126 case 21: return offsetofPPCGuestState(guest_VSR21); 1127 case 22: return offsetofPPCGuestState(guest_VSR22); 1128 case 23: return offsetofPPCGuestState(guest_VSR23); 1129 case 24: return offsetofPPCGuestState(guest_VSR24); 1130 case 25: return offsetofPPCGuestState(guest_VSR25); 1131 case 26: return offsetofPPCGuestState(guest_VSR26); 1132 case 27: return offsetofPPCGuestState(guest_VSR27); 1133 case 28: return offsetofPPCGuestState(guest_VSR28); 1134 case 29: return offsetofPPCGuestState(guest_VSR29); 1135 case 30: return offsetofPPCGuestState(guest_VSR30); 1136 case 31: return offsetofPPCGuestState(guest_VSR31); 1137 default: break; 1138 } 1139 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/ 1140 } 1141 1142 static IRExpr* getFReg ( UInt archreg ) 1143 { 1144 vassert(archreg < 32); 1145 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 ); 1146 } 1147 1148 /* Ditto, but write to a reg instead. */ 1149 static void putFReg ( UInt archreg, IRExpr* e ) 1150 { 1151 vassert(archreg < 32); 1152 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1153 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) ); 1154 } 1155 1156 /* get Decimal float value. Note, they share floating point register file. */ 1157 static IRExpr* getDReg(UInt archreg) { 1158 IRExpr *e; 1159 vassert( archreg < 32 ); 1160 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 ); 1161 return e; 1162 } 1163 static IRExpr* getDReg32(UInt archreg) { 1164 IRExpr *e; 1165 vassert( archreg < 32 ); 1166 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 ); 1167 return e; 1168 } 1169 1170 /* Read a floating point register pair and combine their contents into a 1171 128-bit value */ 1172 static IRExpr *getDReg_pair(UInt archreg) { 1173 IRExpr *high = getDReg( archreg ); 1174 IRExpr *low = getDReg( archreg + 1 ); 1175 1176 return binop( Iop_D64HLtoD128, high, low ); 1177 } 1178 1179 /* Ditto, but write to a reg instead. */ 1180 static void putDReg32(UInt archreg, IRExpr* e) { 1181 vassert( archreg < 32 ); 1182 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 ); 1183 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1184 } 1185 1186 static void putDReg(UInt archreg, IRExpr* e) { 1187 vassert( archreg < 32 ); 1188 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 ); 1189 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) ); 1190 } 1191 1192 /* Write a 128-bit floating point value into a register pair. */ 1193 static void putDReg_pair(UInt archreg, IRExpr *e) { 1194 IRTemp low = newTemp( Ity_D64 ); 1195 IRTemp high = newTemp( Ity_D64 ); 1196 1197 vassert( archreg < 32 ); 1198 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 ); 1199 1200 assign( low, unop( Iop_D128LOtoD64, e ) ); 1201 assign( high, unop( Iop_D128HItoD64, e ) ); 1202 1203 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) ); 1204 stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) ); 1205 } 1206 1207 static Int vsxGuestRegOffset ( UInt archreg ) 1208 { 1209 vassert(archreg < 64); 1210 switch (archreg) { 1211 case 0: return offsetofPPCGuestState(guest_VSR0); 1212 case 1: return offsetofPPCGuestState(guest_VSR1); 1213 case 2: return offsetofPPCGuestState(guest_VSR2); 1214 case 3: return offsetofPPCGuestState(guest_VSR3); 1215 case 4: return offsetofPPCGuestState(guest_VSR4); 1216 case 5: return offsetofPPCGuestState(guest_VSR5); 1217 case 6: return offsetofPPCGuestState(guest_VSR6); 1218 case 7: return offsetofPPCGuestState(guest_VSR7); 1219 case 8: return offsetofPPCGuestState(guest_VSR8); 1220 case 9: return offsetofPPCGuestState(guest_VSR9); 1221 case 10: return offsetofPPCGuestState(guest_VSR10); 1222 case 11: return offsetofPPCGuestState(guest_VSR11); 1223 case 12: return offsetofPPCGuestState(guest_VSR12); 1224 case 13: return offsetofPPCGuestState(guest_VSR13); 1225 case 14: return offsetofPPCGuestState(guest_VSR14); 1226 case 15: return offsetofPPCGuestState(guest_VSR15); 1227 case 16: return offsetofPPCGuestState(guest_VSR16); 1228 case 17: return offsetofPPCGuestState(guest_VSR17); 1229 case 18: return offsetofPPCGuestState(guest_VSR18); 1230 case 19: return offsetofPPCGuestState(guest_VSR19); 1231 case 20: return offsetofPPCGuestState(guest_VSR20); 1232 case 21: return offsetofPPCGuestState(guest_VSR21); 1233 case 22: return offsetofPPCGuestState(guest_VSR22); 1234 case 23: return offsetofPPCGuestState(guest_VSR23); 1235 case 24: return offsetofPPCGuestState(guest_VSR24); 1236 case 25: return offsetofPPCGuestState(guest_VSR25); 1237 case 26: return offsetofPPCGuestState(guest_VSR26); 1238 case 27: return offsetofPPCGuestState(guest_VSR27); 1239 case 28: return offsetofPPCGuestState(guest_VSR28); 1240 case 29: return offsetofPPCGuestState(guest_VSR29); 1241 case 30: return offsetofPPCGuestState(guest_VSR30); 1242 case 31: return offsetofPPCGuestState(guest_VSR31); 1243 case 32: return offsetofPPCGuestState(guest_VSR32); 1244 case 33: return offsetofPPCGuestState(guest_VSR33); 1245 case 34: return offsetofPPCGuestState(guest_VSR34); 1246 case 35: return offsetofPPCGuestState(guest_VSR35); 1247 case 36: return offsetofPPCGuestState(guest_VSR36); 1248 case 37: return offsetofPPCGuestState(guest_VSR37); 1249 case 38: return offsetofPPCGuestState(guest_VSR38); 1250 case 39: return offsetofPPCGuestState(guest_VSR39); 1251 case 40: return offsetofPPCGuestState(guest_VSR40); 1252 case 41: return offsetofPPCGuestState(guest_VSR41); 1253 case 42: return offsetofPPCGuestState(guest_VSR42); 1254 case 43: return offsetofPPCGuestState(guest_VSR43); 1255 case 44: return offsetofPPCGuestState(guest_VSR44); 1256 case 45: return offsetofPPCGuestState(guest_VSR45); 1257 case 46: return offsetofPPCGuestState(guest_VSR46); 1258 case 47: return offsetofPPCGuestState(guest_VSR47); 1259 case 48: return offsetofPPCGuestState(guest_VSR48); 1260 case 49: return offsetofPPCGuestState(guest_VSR49); 1261 case 50: return offsetofPPCGuestState(guest_VSR50); 1262 case 51: return offsetofPPCGuestState(guest_VSR51); 1263 case 52: return offsetofPPCGuestState(guest_VSR52); 1264 case 53: return offsetofPPCGuestState(guest_VSR53); 1265 case 54: return offsetofPPCGuestState(guest_VSR54); 1266 case 55: return offsetofPPCGuestState(guest_VSR55); 1267 case 56: return offsetofPPCGuestState(guest_VSR56); 1268 case 57: return offsetofPPCGuestState(guest_VSR57); 1269 case 58: return offsetofPPCGuestState(guest_VSR58); 1270 case 59: return offsetofPPCGuestState(guest_VSR59); 1271 case 60: return offsetofPPCGuestState(guest_VSR60); 1272 case 61: return offsetofPPCGuestState(guest_VSR61); 1273 case 62: return offsetofPPCGuestState(guest_VSR62); 1274 case 63: return offsetofPPCGuestState(guest_VSR63); 1275 default: break; 1276 } 1277 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/ 1278 } 1279 1280 /* Vector registers are mapped to VSX registers[32..63]. */ 1281 static Int vectorGuestRegOffset ( UInt archreg ) 1282 { 1283 vassert(archreg < 32); 1284 1285 switch (archreg) { 1286 case 0: return offsetofPPCGuestState(guest_VSR32); 1287 case 1: return offsetofPPCGuestState(guest_VSR33); 1288 case 2: return offsetofPPCGuestState(guest_VSR34); 1289 case 3: return offsetofPPCGuestState(guest_VSR35); 1290 case 4: return offsetofPPCGuestState(guest_VSR36); 1291 case 5: return offsetofPPCGuestState(guest_VSR37); 1292 case 6: return offsetofPPCGuestState(guest_VSR38); 1293 case 7: return offsetofPPCGuestState(guest_VSR39); 1294 case 8: return offsetofPPCGuestState(guest_VSR40); 1295 case 9: return offsetofPPCGuestState(guest_VSR41); 1296 case 10: return offsetofPPCGuestState(guest_VSR42); 1297 case 11: return offsetofPPCGuestState(guest_VSR43); 1298 case 12: return offsetofPPCGuestState(guest_VSR44); 1299 case 13: return offsetofPPCGuestState(guest_VSR45); 1300 case 14: return offsetofPPCGuestState(guest_VSR46); 1301 case 15: return offsetofPPCGuestState(guest_VSR47); 1302 case 16: return offsetofPPCGuestState(guest_VSR48); 1303 case 17: return offsetofPPCGuestState(guest_VSR49); 1304 case 18: return offsetofPPCGuestState(guest_VSR50); 1305 case 19: return offsetofPPCGuestState(guest_VSR51); 1306 case 20: return offsetofPPCGuestState(guest_VSR52); 1307 case 21: return offsetofPPCGuestState(guest_VSR53); 1308 case 22: return offsetofPPCGuestState(guest_VSR54); 1309 case 23: return offsetofPPCGuestState(guest_VSR55); 1310 case 24: return offsetofPPCGuestState(guest_VSR56); 1311 case 25: return offsetofPPCGuestState(guest_VSR57); 1312 case 26: return offsetofPPCGuestState(guest_VSR58); 1313 case 27: return offsetofPPCGuestState(guest_VSR59); 1314 case 28: return offsetofPPCGuestState(guest_VSR60); 1315 case 29: return offsetofPPCGuestState(guest_VSR61); 1316 case 30: return offsetofPPCGuestState(guest_VSR62); 1317 case 31: return offsetofPPCGuestState(guest_VSR63); 1318 default: break; 1319 } 1320 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/ 1321 } 1322 1323 static IRExpr* getVReg ( UInt archreg ) 1324 { 1325 vassert(archreg < 32); 1326 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 ); 1327 } 1328 1329 /* Ditto, but write to a reg instead. */ 1330 static void putVReg ( UInt archreg, IRExpr* e ) 1331 { 1332 vassert(archreg < 32); 1333 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1334 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) ); 1335 } 1336 1337 /* Get contents of VSX guest register */ 1338 static IRExpr* getVSReg ( UInt archreg ) 1339 { 1340 vassert(archreg < 64); 1341 return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 ); 1342 } 1343 1344 /* Ditto, but write to a VSX reg instead. */ 1345 static void putVSReg ( UInt archreg, IRExpr* e ) 1346 { 1347 vassert(archreg < 64); 1348 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128); 1349 stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) ); 1350 } 1351 1352 1353 static Int guestCR321offset ( UInt cr ) 1354 { 1355 switch (cr) { 1356 case 0: return offsetofPPCGuestState(guest_CR0_321 ); 1357 case 1: return offsetofPPCGuestState(guest_CR1_321 ); 1358 case 2: return offsetofPPCGuestState(guest_CR2_321 ); 1359 case 3: return offsetofPPCGuestState(guest_CR3_321 ); 1360 case 4: return offsetofPPCGuestState(guest_CR4_321 ); 1361 case 5: return offsetofPPCGuestState(guest_CR5_321 ); 1362 case 6: return offsetofPPCGuestState(guest_CR6_321 ); 1363 case 7: return offsetofPPCGuestState(guest_CR7_321 ); 1364 default: vpanic("guestCR321offset(ppc)"); 1365 } 1366 } 1367 1368 static Int guestCR0offset ( UInt cr ) 1369 { 1370 switch (cr) { 1371 case 0: return offsetofPPCGuestState(guest_CR0_0 ); 1372 case 1: return offsetofPPCGuestState(guest_CR1_0 ); 1373 case 2: return offsetofPPCGuestState(guest_CR2_0 ); 1374 case 3: return offsetofPPCGuestState(guest_CR3_0 ); 1375 case 4: return offsetofPPCGuestState(guest_CR4_0 ); 1376 case 5: return offsetofPPCGuestState(guest_CR5_0 ); 1377 case 6: return offsetofPPCGuestState(guest_CR6_0 ); 1378 case 7: return offsetofPPCGuestState(guest_CR7_0 ); 1379 default: vpanic("guestCR3offset(ppc)"); 1380 } 1381 } 1382 1383 typedef enum { 1384 _placeholder0, 1385 _placeholder1, 1386 _placeholder2, 1387 BYTE, 1388 HWORD, 1389 WORD, 1390 DWORD 1391 } _popcount_data_type; 1392 1393 /* Generate an IR sequence to do a popcount operation on the supplied 1394 IRTemp, and return a new IRTemp holding the result. 'ty' may be 1395 Ity_I32 or Ity_I64 only. */ 1396 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type ) 1397 { 1398 /* Do count across 2^data_type bits, 1399 byte: data_type = 3 1400 half word: data_type = 4 1401 word: data_type = 5 1402 double word: data_type = 6 (not supported for 32-bit type) 1403 */ 1404 Int shift[6]; 1405 _popcount_data_type idx, i; 1406 IRTemp mask[6]; 1407 IRTemp old = IRTemp_INVALID; 1408 IRTemp nyu = IRTemp_INVALID; 1409 1410 vassert(ty == Ity_I64 || ty == Ity_I32); 1411 1412 if (ty == Ity_I32) { 1413 1414 for (idx = 0; idx < WORD; idx++) { 1415 mask[idx] = newTemp(ty); 1416 shift[idx] = 1 << idx; 1417 } 1418 assign(mask[0], mkU32(0x55555555)); 1419 assign(mask[1], mkU32(0x33333333)); 1420 assign(mask[2], mkU32(0x0F0F0F0F)); 1421 assign(mask[3], mkU32(0x00FF00FF)); 1422 assign(mask[4], mkU32(0x0000FFFF)); 1423 old = src; 1424 for (i = 0; i < data_type; i++) { 1425 nyu = newTemp(ty); 1426 assign(nyu, 1427 binop(Iop_Add32, 1428 binop(Iop_And32, 1429 mkexpr(old), 1430 mkexpr(mask[i])), 1431 binop(Iop_And32, 1432 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1433 mkexpr(mask[i])))); 1434 old = nyu; 1435 } 1436 return nyu; 1437 } 1438 1439 // else, ty == Ity_I64 1440 vassert(mode64); 1441 1442 for (i = 0; i < DWORD; i++) { 1443 mask[i] = newTemp( Ity_I64 ); 1444 shift[i] = 1 << i; 1445 } 1446 assign( mask[0], mkU64( 0x5555555555555555ULL ) ); 1447 assign( mask[1], mkU64( 0x3333333333333333ULL ) ); 1448 assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) ); 1449 assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) ); 1450 assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) ); 1451 assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) ); 1452 old = src; 1453 for (i = 0; i < data_type; i++) { 1454 nyu = newTemp( Ity_I64 ); 1455 assign( nyu, 1456 binop( Iop_Add64, 1457 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ), 1458 binop( Iop_And64, 1459 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ), 1460 mkexpr( mask[i] ) ) ) ); 1461 old = nyu; 1462 } 1463 return nyu; 1464 } 1465 1466 /* Special purpose population count function for 1467 * vpopcntd in 32-bit mode. 1468 */ 1469 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 ) 1470 { 1471 Int i, shift[6]; 1472 IRTemp mask[6]; 1473 IRTemp old = IRTemp_INVALID; 1474 IRTemp nyu1 = IRTemp_INVALID; 1475 IRTemp nyu2 = IRTemp_INVALID; 1476 IRTemp retval = newTemp(Ity_I64); 1477 1478 vassert(!mode64); 1479 1480 for (i = 0; i < WORD; i++) { 1481 mask[i] = newTemp(Ity_I32); 1482 shift[i] = 1 << i; 1483 } 1484 assign(mask[0], mkU32(0x55555555)); 1485 assign(mask[1], mkU32(0x33333333)); 1486 assign(mask[2], mkU32(0x0F0F0F0F)); 1487 assign(mask[3], mkU32(0x00FF00FF)); 1488 assign(mask[4], mkU32(0x0000FFFF)); 1489 old = src1; 1490 for (i = 0; i < WORD; i++) { 1491 nyu1 = newTemp(Ity_I32); 1492 assign(nyu1, 1493 binop(Iop_Add32, 1494 binop(Iop_And32, 1495 mkexpr(old), 1496 mkexpr(mask[i])), 1497 binop(Iop_And32, 1498 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1499 mkexpr(mask[i])))); 1500 old = nyu1; 1501 } 1502 1503 old = src2; 1504 for (i = 0; i < WORD; i++) { 1505 nyu2 = newTemp(Ity_I32); 1506 assign(nyu2, 1507 binop(Iop_Add32, 1508 binop(Iop_And32, 1509 mkexpr(old), 1510 mkexpr(mask[i])), 1511 binop(Iop_And32, 1512 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])), 1513 mkexpr(mask[i])))); 1514 old = nyu2; 1515 } 1516 assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2)))); 1517 return retval; 1518 } 1519 1520 1521 // ROTL(src32/64, rot_amt5/6) 1522 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src, 1523 IRExpr* rot_amt ) 1524 { 1525 IRExpr *mask, *rot; 1526 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8); 1527 1528 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) { 1529 // rot = (src << rot_amt) | (src >> (64-rot_amt)) 1530 mask = binop(Iop_And8, rot_amt, mkU8(63)); 1531 rot = binop(Iop_Or64, 1532 binop(Iop_Shl64, src, mask), 1533 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask))); 1534 } else { 1535 // rot = (src << rot_amt) | (src >> (32-rot_amt)) 1536 mask = binop(Iop_And8, rot_amt, mkU8(31)); 1537 rot = binop(Iop_Or32, 1538 binop(Iop_Shl32, src, mask), 1539 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask))); 1540 } 1541 /* Note: the ITE not merely an optimisation; it's needed 1542 because otherwise the Shr is a shift by the word size when 1543 mask denotes zero. For rotates by immediates, a lot of 1544 this junk gets folded out. */ 1545 return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)), 1546 /* non-zero rotate */ rot, 1547 /* zero rotate */ src); 1548 } 1549 1550 /* Standard effective address calc: (rA + rB) */ 1551 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB ) 1552 { 1553 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1554 vassert(rA < 32); 1555 vassert(rB < 32); 1556 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB)); 1557 } 1558 1559 /* Standard effective address calc: (rA + simm) */ 1560 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 ) 1561 { 1562 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1563 vassert(rA < 32); 1564 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), 1565 mkSzExtendS16(ty, simm16)); 1566 } 1567 1568 /* Standard effective address calc: (rA|0) */ 1569 static IRExpr* ea_rAor0 ( UInt rA ) 1570 { 1571 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1572 vassert(rA < 32); 1573 if (rA == 0) { 1574 return mkSzImm(ty, 0); 1575 } else { 1576 return getIReg(rA); 1577 } 1578 } 1579 1580 /* Standard effective address calc: (rA|0) + rB */ 1581 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB ) 1582 { 1583 vassert(rA < 32); 1584 vassert(rB < 32); 1585 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB ); 1586 } 1587 1588 /* Standard effective address calc: (rA|0) + simm16 */ 1589 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 ) 1590 { 1591 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1592 vassert(rA < 32); 1593 if (rA == 0) { 1594 return mkSzExtendS16(ty, simm16); 1595 } else { 1596 return ea_rA_simm( rA, simm16 ); 1597 } 1598 } 1599 1600 1601 /* Align effective address */ 1602 static IRExpr* addr_align( IRExpr* addr, UChar align ) 1603 { 1604 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1605 Long mask; 1606 switch (align) { 1607 case 1: return addr; // byte aligned 1608 case 2: mask = ((Long)-1) << 1; break; // half-word aligned 1609 case 4: mask = ((Long)-1) << 2; break; // word aligned 1610 case 16: mask = ((Long)-1) << 4; break; // quad-word aligned 1611 default: 1612 vex_printf("addr_align: align = %u\n", align); 1613 vpanic("addr_align(ppc)"); 1614 } 1615 1616 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty); 1617 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) ); 1618 } 1619 1620 1621 /* Exit the trace if ADDR (intended to be a guest memory address) is 1622 not ALIGN-aligned, generating a request for a SIGBUS followed by a 1623 restart of the current insn. */ 1624 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align ) 1625 { 1626 vassert(align == 4 || align == 8 || align == 16); 1627 if (mode64) { 1628 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64); 1629 stmt( 1630 IRStmt_Exit( 1631 binop(Iop_CmpNE64, 1632 binop(Iop_And64, mkexpr(addr), mkU64(align-1)), 1633 mkU64(0)), 1634 Ijk_SigBUS, 1635 IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA 1636 ) 1637 ); 1638 } else { 1639 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32); 1640 stmt( 1641 IRStmt_Exit( 1642 binop(Iop_CmpNE32, 1643 binop(Iop_And32, mkexpr(addr), mkU32(align-1)), 1644 mkU32(0)), 1645 Ijk_SigBUS, 1646 IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA 1647 ) 1648 ); 1649 } 1650 } 1651 1652 1653 /* Generate AbiHints which mark points at which the ELF or PowerOpen 1654 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some 1655 N) becomes undefined. That is at function calls and returns. ELF 1656 ppc32 doesn't have this "feature" (how fortunate for it). nia is 1657 the address of the next instruction to be executed. 1658 */ 1659 static void make_redzone_AbiHint ( VexAbiInfo* vbi, 1660 IRTemp nia, const HChar* who ) 1661 { 1662 Int szB = vbi->guest_stack_redzone_size; 1663 if (0) vex_printf("AbiHint: %s\n", who); 1664 vassert(szB >= 0); 1665 if (szB > 0) { 1666 if (mode64) { 1667 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64); 1668 stmt( IRStmt_AbiHint( 1669 binop(Iop_Sub64, getIReg(1), mkU64(szB)), 1670 szB, 1671 mkexpr(nia) 1672 )); 1673 } else { 1674 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32); 1675 stmt( IRStmt_AbiHint( 1676 binop(Iop_Sub32, getIReg(1), mkU32(szB)), 1677 szB, 1678 mkexpr(nia) 1679 )); 1680 } 1681 } 1682 } 1683 1684 1685 /*------------------------------------------------------------*/ 1686 /*--- Helpers for condition codes. ---*/ 1687 /*------------------------------------------------------------*/ 1688 1689 /* Condition register layout. 1690 1691 In the hardware, CR is laid out like this. The leftmost end is the 1692 most significant bit in the register; however the IBM documentation 1693 numbers the bits backwards for some reason. 1694 1695 CR0 CR1 .......... CR6 CR7 1696 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 1697 31 28 3 0 (normal bit numbering) 1698 1699 Each CR field is 4 bits: [<,>,==,SO] 1700 1701 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. 1702 1703 Indexing from BI to guest state: 1704 1705 let n = BI / 4 1706 off = BI % 4 1707 this references CR n: 1708 1709 off==0 -> guest_CRn_321 >> 3 1710 off==1 -> guest_CRn_321 >> 2 1711 off==2 -> guest_CRn_321 >> 1 1712 off==3 -> guest_CRn_SO 1713 1714 Bear in mind the only significant bit in guest_CRn_SO is bit 0 1715 (normal notation) and in guest_CRn_321 the significant bits are 1716 3, 2 and 1 (normal notation). 1717 */ 1718 1719 static void putCR321 ( UInt cr, IRExpr* e ) 1720 { 1721 vassert(cr < 8); 1722 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1723 stmt( IRStmt_Put(guestCR321offset(cr), e) ); 1724 } 1725 1726 static void putCR0 ( UInt cr, IRExpr* e ) 1727 { 1728 vassert(cr < 8); 1729 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1730 stmt( IRStmt_Put(guestCR0offset(cr), e) ); 1731 } 1732 1733 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) 1734 { 1735 vassert(cr < 8); 1736 return IRExpr_Get(guestCR0offset(cr), Ity_I8); 1737 } 1738 1739 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) 1740 { 1741 vassert(cr < 8); 1742 return IRExpr_Get(guestCR321offset(cr), Ity_I8); 1743 } 1744 1745 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1746 return it at the bottom of an I32; the top 31 bits are guaranteed 1747 to be zero. */ 1748 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi ) 1749 { 1750 UInt n = bi / 4; 1751 UInt off = bi % 4; 1752 vassert(bi < 32); 1753 if (off == 3) { 1754 /* Fetch the SO bit for this CR field */ 1755 /* Note: And32 is redundant paranoia iff guest state only has 0 1756 or 1 in that slot. */ 1757 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1758 } else { 1759 /* Fetch the <, > or == bit for this CR field */ 1760 return binop( Iop_And32, 1761 binop( Iop_Shr32, 1762 unop(Iop_8Uto32, getCR321(n)), 1763 mkU8(toUChar(3-off)) ), 1764 mkU32(1) ); 1765 } 1766 } 1767 1768 /* Dually, write the least significant bit of BIT to the specified CR 1769 bit. Indexing as per getCRbit. */ 1770 static void putCRbit ( UInt bi, IRExpr* bit ) 1771 { 1772 UInt n, off; 1773 IRExpr* safe; 1774 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32); 1775 safe = binop(Iop_And32, bit, mkU32(1)); 1776 n = bi / 4; 1777 off = bi % 4; 1778 vassert(bi < 32); 1779 if (off == 3) { 1780 /* This is the SO bit for this CR field */ 1781 putCR0(n, unop(Iop_32to8, safe)); 1782 } else { 1783 off = 3 - off; 1784 vassert(off == 1 || off == 2 || off == 3); 1785 putCR321( 1786 n, 1787 unop( Iop_32to8, 1788 binop( Iop_Or32, 1789 /* old value with field masked out */ 1790 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)), 1791 mkU32(~(1 << off))), 1792 /* new value in the right place */ 1793 binop(Iop_Shl32, safe, mkU8(toUChar(off))) 1794 ) 1795 ) 1796 ); 1797 } 1798 } 1799 1800 /* Fetch the specified CR bit (as per IBM/hardware notation) and 1801 return it somewhere in an I32; it does not matter where, but 1802 whichever bit it is, all other bits are guaranteed to be zero. In 1803 other words, the I32-typed expression will be zero if the bit is 1804 zero and nonzero if the bit is 1. Write into *where the index 1805 of where the bit will be. */ 1806 1807 static 1808 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ) 1809 { 1810 UInt n = bi / 4; 1811 UInt off = bi % 4; 1812 vassert(bi < 32); 1813 if (off == 3) { 1814 /* Fetch the SO bit for this CR field */ 1815 /* Note: And32 is redundant paranoia iff guest state only has 0 1816 or 1 in that slot. */ 1817 *where = 0; 1818 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1)); 1819 } else { 1820 /* Fetch the <, > or == bit for this CR field */ 1821 *where = 3-off; 1822 return binop( Iop_And32, 1823 unop(Iop_8Uto32, getCR321(n)), 1824 mkU32(1 << (3-off)) ); 1825 } 1826 } 1827 1828 /* Set the CR0 flags following an arithmetic operation. 1829 (Condition Register CR0 Field Definition, PPC32 p60) 1830 */ 1831 static IRExpr* getXER_SO ( void ); 1832 static void set_CR0 ( IRExpr* result ) 1833 { 1834 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 || 1835 typeOfIRExpr(irsb->tyenv,result) == Ity_I64); 1836 if (mode64) { 1837 putCR321( 0, unop(Iop_64to8, 1838 binop(Iop_CmpORD64S, result, mkU64(0))) ); 1839 } else { 1840 putCR321( 0, unop(Iop_32to8, 1841 binop(Iop_CmpORD32S, result, mkU32(0))) ); 1842 } 1843 putCR0( 0, getXER_SO() ); 1844 } 1845 1846 1847 /* Set the CR6 flags following an AltiVec compare operation. 1848 * NOTE: This also works for VSX single-precision compares. 1849 * */ 1850 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) 1851 { 1852 /* CR6[0:3] = {all_ones, 0, all_zeros, 0} 1853 all_ones = (v[0] && v[1] && v[2] && v[3]) 1854 all_zeros = ~(v[0] || v[1] || v[2] || v[3]) 1855 */ 1856 IRTemp v0 = newTemp(Ity_V128); 1857 IRTemp v1 = newTemp(Ity_V128); 1858 IRTemp v2 = newTemp(Ity_V128); 1859 IRTemp v3 = newTemp(Ity_V128); 1860 IRTemp rOnes = newTemp(Ity_I8); 1861 IRTemp rZeros = newTemp(Ity_I8); 1862 1863 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128); 1864 1865 assign( v0, result ); 1866 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); 1867 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); 1868 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); 1869 1870 assign( rZeros, unop(Iop_1Uto8, 1871 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1872 unop(Iop_Not32, 1873 unop(Iop_V128to32, 1874 binop(Iop_OrV128, 1875 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), 1876 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) 1877 ))) ); 1878 1879 if (test_all_ones) { 1880 assign( rOnes, unop(Iop_1Uto8, 1881 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), 1882 unop(Iop_V128to32, 1883 binop(Iop_AndV128, 1884 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), 1885 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))) 1886 ))) ); 1887 putCR321( 6, binop(Iop_Or8, 1888 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), 1889 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); 1890 } else { 1891 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); 1892 } 1893 putCR0( 6, mkU8(0) ); 1894 } 1895 1896 1897 1898 /*------------------------------------------------------------*/ 1899 /*--- Helpers for XER flags. ---*/ 1900 /*------------------------------------------------------------*/ 1901 1902 static void putXER_SO ( IRExpr* e ) 1903 { 1904 IRExpr* so; 1905 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1906 so = binop(Iop_And8, e, mkU8(1)); 1907 stmt( IRStmt_Put( OFFB_XER_SO, so ) ); 1908 } 1909 1910 static void putXER_OV ( IRExpr* e ) 1911 { 1912 IRExpr* ov; 1913 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1914 ov = binop(Iop_And8, e, mkU8(1)); 1915 stmt( IRStmt_Put( OFFB_XER_OV, ov ) ); 1916 } 1917 1918 static void putXER_CA ( IRExpr* e ) 1919 { 1920 IRExpr* ca; 1921 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1922 ca = binop(Iop_And8, e, mkU8(1)); 1923 stmt( IRStmt_Put( OFFB_XER_CA, ca ) ); 1924 } 1925 1926 static void putXER_BC ( IRExpr* e ) 1927 { 1928 IRExpr* bc; 1929 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8); 1930 bc = binop(Iop_And8, e, mkU8(0x7F)); 1931 stmt( IRStmt_Put( OFFB_XER_BC, bc ) ); 1932 } 1933 1934 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) 1935 { 1936 return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); 1937 } 1938 1939 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void ) 1940 { 1941 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) ); 1942 } 1943 1944 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ) 1945 { 1946 return IRExpr_Get( OFFB_XER_OV, Ity_I8 ); 1947 } 1948 1949 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void ) 1950 { 1951 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) ); 1952 } 1953 1954 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void ) 1955 { 1956 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 ); 1957 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) ); 1958 } 1959 1960 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ) 1961 { 1962 return IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 1963 } 1964 1965 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void ) 1966 { 1967 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 ); 1968 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) ); 1969 } 1970 1971 1972 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and 1973 %XER.SO accordingly. */ 1974 1975 static void set_XER_OV_32( UInt op, IRExpr* res, 1976 IRExpr* argL, IRExpr* argR ) 1977 { 1978 IRTemp t64; 1979 IRExpr* xer_ov; 1980 vassert(op < PPCG_FLAG_OP_NUMBER); 1981 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 1982 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 1983 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 1984 1985 # define INT32_MIN 0x80000000 1986 1987 # define XOR2(_aa,_bb) \ 1988 binop(Iop_Xor32,(_aa),(_bb)) 1989 1990 # define XOR3(_cc,_dd,_ee) \ 1991 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee)) 1992 1993 # define AND3(_ff,_gg,_hh) \ 1994 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh)) 1995 1996 #define NOT(_jj) \ 1997 unop(Iop_Not32, (_jj)) 1998 1999 switch (op) { 2000 case /* 0 */ PPCG_FLAG_OP_ADD: 2001 case /* 1 */ PPCG_FLAG_OP_ADDE: 2002 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */ 2003 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2004 xer_ov 2005 = AND3( XOR3(argL,argR,mkU32(-1)), 2006 XOR2(argL,res), 2007 mkU32(INT32_MIN) ); 2008 /* xer_ov can only be 0 or 1<<31 */ 2009 xer_ov 2010 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2011 break; 2012 2013 case /* 2 */ PPCG_FLAG_OP_DIVW: 2014 /* (argL == INT32_MIN && argR == -1) || argR == 0 */ 2015 xer_ov 2016 = mkOR1( 2017 mkAND1( 2018 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)), 2019 binop(Iop_CmpEQ32, argR, mkU32(-1)) 2020 ), 2021 binop(Iop_CmpEQ32, argR, mkU32(0) ) 2022 ); 2023 xer_ov 2024 = unop(Iop_1Uto32, xer_ov); 2025 break; 2026 2027 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2028 /* argR == 0 */ 2029 xer_ov 2030 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0))); 2031 break; 2032 2033 case /* 4 */ PPCG_FLAG_OP_MULLW: 2034 /* OV true if result can't be represented in 32 bits 2035 i.e sHi != sign extension of sLo */ 2036 t64 = newTemp(Ity_I64); 2037 assign( t64, binop(Iop_MullS32, argL, argR) ); 2038 xer_ov 2039 = binop( Iop_CmpNE32, 2040 unop(Iop_64HIto32, mkexpr(t64)), 2041 binop( Iop_Sar32, 2042 unop(Iop_64to32, mkexpr(t64)), 2043 mkU8(31)) 2044 ); 2045 xer_ov 2046 = unop(Iop_1Uto32, xer_ov); 2047 break; 2048 2049 case /* 5 */ PPCG_FLAG_OP_NEG: 2050 /* argL == INT32_MIN */ 2051 xer_ov 2052 = unop( Iop_1Uto32, 2053 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) ); 2054 break; 2055 2056 case /* 6 */ PPCG_FLAG_OP_SUBF: 2057 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2058 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2059 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */ 2060 xer_ov 2061 = AND3( XOR3(NOT(argL),argR,mkU32(-1)), 2062 XOR2(NOT(argL),res), 2063 mkU32(INT32_MIN) ); 2064 /* xer_ov can only be 0 or 1<<31 */ 2065 xer_ov 2066 = binop(Iop_Shr32, xer_ov, mkU8(31) ); 2067 break; 2068 2069 case PPCG_FLAG_OP_DIVWEU: 2070 xer_ov 2071 = binop( Iop_Or32, 2072 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2073 unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) ); 2074 break; 2075 2076 case PPCG_FLAG_OP_DIVWE: 2077 2078 /* If argR == 0 of if the result cannot fit in the 32-bit destination register, 2079 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero, 2080 * an overflow is implied. 2081 */ 2082 xer_ov = binop( Iop_Or32, 2083 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ), 2084 unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ), 2085 mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ), 2086 binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) ); 2087 break; 2088 2089 2090 2091 default: 2092 vex_printf("set_XER_OV: op = %u\n", op); 2093 vpanic("set_XER_OV(ppc)"); 2094 } 2095 2096 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2097 putXER_OV( unop(Iop_32to8, xer_ov) ); 2098 2099 /* Update the summary overflow */ 2100 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2101 2102 # undef INT32_MIN 2103 # undef AND3 2104 # undef XOR3 2105 # undef XOR2 2106 # undef NOT 2107 } 2108 2109 static void set_XER_OV_64( UInt op, IRExpr* res, 2110 IRExpr* argL, IRExpr* argR ) 2111 { 2112 IRExpr* xer_ov; 2113 vassert(op < PPCG_FLAG_OP_NUMBER); 2114 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2115 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2116 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2117 2118 # define INT64_MIN 0x8000000000000000ULL 2119 2120 # define XOR2(_aa,_bb) \ 2121 binop(Iop_Xor64,(_aa),(_bb)) 2122 2123 # define XOR3(_cc,_dd,_ee) \ 2124 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee)) 2125 2126 # define AND3(_ff,_gg,_hh) \ 2127 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh)) 2128 2129 #define NOT(_jj) \ 2130 unop(Iop_Not64, (_jj)) 2131 2132 switch (op) { 2133 case /* 0 */ PPCG_FLAG_OP_ADD: 2134 case /* 1 */ PPCG_FLAG_OP_ADDE: 2135 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */ 2136 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) 2137 xer_ov 2138 = AND3( XOR3(argL,argR,mkU64(-1)), 2139 XOR2(argL,res), 2140 mkU64(INT64_MIN) ); 2141 /* xer_ov can only be 0 or 1<<63 */ 2142 xer_ov 2143 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2144 break; 2145 2146 case /* 2 */ PPCG_FLAG_OP_DIVW: 2147 /* (argL == INT64_MIN && argR == -1) || argR == 0 */ 2148 xer_ov 2149 = mkOR1( 2150 mkAND1( 2151 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)), 2152 binop(Iop_CmpEQ64, argR, mkU64(-1)) 2153 ), 2154 binop(Iop_CmpEQ64, argR, mkU64(0) ) 2155 ); 2156 break; 2157 2158 case /* 3 */ PPCG_FLAG_OP_DIVWU: 2159 /* argR == 0 */ 2160 xer_ov 2161 = binop(Iop_CmpEQ64, argR, mkU64(0)); 2162 break; 2163 2164 case /* 4 */ PPCG_FLAG_OP_MULLW: { 2165 /* OV true if result can't be represented in 64 bits 2166 i.e sHi != sign extension of sLo */ 2167 xer_ov 2168 = binop( Iop_CmpNE32, 2169 unop(Iop_64HIto32, res), 2170 binop( Iop_Sar32, 2171 unop(Iop_64to32, res), 2172 mkU8(31)) 2173 ); 2174 break; 2175 } 2176 2177 case /* 5 */ PPCG_FLAG_OP_NEG: 2178 /* argL == INT64_MIN */ 2179 xer_ov 2180 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)); 2181 break; 2182 2183 case /* 6 */ PPCG_FLAG_OP_SUBF: 2184 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2185 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2186 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */ 2187 xer_ov 2188 = AND3( XOR3(NOT(argL),argR,mkU64(-1)), 2189 XOR2(NOT(argL),res), 2190 mkU64(INT64_MIN) ); 2191 /* xer_ov can only be 0 or 1<<63 */ 2192 xer_ov 2193 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63))); 2194 break; 2195 2196 case PPCG_FLAG_OP_DIVDE: 2197 2198 /* If argR == 0, we must set the OV bit. But there's another condition 2199 * where we can get overflow set for divde . . . when the 2200 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND 2201 * both dividend and divisor are non-zero, it implies an overflow. 2202 */ 2203 xer_ov 2204 = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2205 mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ), 2206 mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ), 2207 binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) ); 2208 break; 2209 2210 case PPCG_FLAG_OP_DIVDEU: 2211 /* If argR == 0 or if argL >= argR, set OV. */ 2212 xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ), 2213 binop( Iop_CmpLE64U, argR, argL ) ); 2214 break; 2215 2216 case /* 18 */ PPCG_FLAG_OP_MULLD: { 2217 IRTemp t128; 2218 /* OV true if result can't be represented in 64 bits 2219 i.e sHi != sign extension of sLo */ 2220 t128 = newTemp(Ity_I128); 2221 assign( t128, binop(Iop_MullS64, argL, argR) ); 2222 xer_ov 2223 = binop( Iop_CmpNE64, 2224 unop(Iop_128HIto64, mkexpr(t128)), 2225 binop( Iop_Sar64, 2226 unop(Iop_128to64, mkexpr(t128)), 2227 mkU8(63)) 2228 ); 2229 break; 2230 } 2231 2232 default: 2233 vex_printf("set_XER_OV: op = %u\n", op); 2234 vpanic("set_XER_OV(ppc64)"); 2235 } 2236 2237 /* xer_ov MUST denote either 0 or 1, no other value allowed */ 2238 putXER_OV( unop(Iop_1Uto8, xer_ov) ); 2239 2240 /* Update the summary overflow */ 2241 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); 2242 2243 # undef INT64_MIN 2244 # undef AND3 2245 # undef XOR3 2246 # undef XOR2 2247 # undef NOT 2248 } 2249 2250 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res, 2251 IRExpr* argL, IRExpr* argR ) 2252 { 2253 if (ty == Ity_I32) 2254 set_XER_OV_32( op, res, argL, argR ); 2255 else 2256 set_XER_OV_64( op, res, argL, argR ); 2257 } 2258 2259 2260 2261 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA 2262 value being OLDCA. Set %XER.CA accordingly. */ 2263 2264 static void set_XER_CA_32 ( UInt op, IRExpr* res, 2265 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2266 { 2267 IRExpr* xer_ca; 2268 vassert(op < PPCG_FLAG_OP_NUMBER); 2269 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32); 2270 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32); 2271 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32); 2272 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32); 2273 2274 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2275 seems reasonable given that it's always generated by 2276 getXER_CA32(), which masks it accordingly. In any case it being 2277 0 or 1 is an invariant of the ppc guest state representation; 2278 if it has any other value, that invariant has been violated. */ 2279 2280 switch (op) { 2281 case /* 0 */ PPCG_FLAG_OP_ADD: 2282 /* res <u argL */ 2283 xer_ca 2284 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL)); 2285 break; 2286 2287 case /* 1 */ PPCG_FLAG_OP_ADDE: 2288 /* res <u argL || (old_ca==1 && res==argL) */ 2289 xer_ca 2290 = mkOR1( 2291 binop(Iop_CmpLT32U, res, argL), 2292 mkAND1( 2293 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2294 binop(Iop_CmpEQ32, res, argL) 2295 ) 2296 ); 2297 xer_ca 2298 = unop(Iop_1Uto32, xer_ca); 2299 break; 2300 2301 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2302 /* res <u argR || (old_ca==1 && res==argR) */ 2303 xer_ca 2304 = mkOR1( 2305 binop(Iop_CmpLT32U, res, argR), 2306 mkAND1( 2307 binop(Iop_CmpEQ32, oldca, mkU32(1)), 2308 binop(Iop_CmpEQ32, res, argR) 2309 ) 2310 ); 2311 xer_ca 2312 = unop(Iop_1Uto32, xer_ca); 2313 break; 2314 2315 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2316 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2317 /* res <=u argR */ 2318 xer_ca 2319 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR)); 2320 break; 2321 2322 case /* 10 */ PPCG_FLAG_OP_SRAW: 2323 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2324 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2325 bit of argL. */ 2326 /* This term valid for shift amount < 32 only */ 2327 xer_ca 2328 = binop( 2329 Iop_And32, 2330 binop(Iop_Sar32, argL, mkU8(31)), 2331 binop( Iop_And32, 2332 argL, 2333 binop( Iop_Sub32, 2334 binop(Iop_Shl32, mkU32(1), 2335 unop(Iop_32to8,argR)), 2336 mkU32(1) ) 2337 ) 2338 ); 2339 xer_ca 2340 = IRExpr_ITE( 2341 /* shift amt > 31 ? */ 2342 binop(Iop_CmpLT32U, mkU32(31), argR), 2343 /* yes -- get sign bit of argL */ 2344 binop(Iop_Shr32, argL, mkU8(31)), 2345 /* no -- be like srawi */ 2346 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))) 2347 ); 2348 break; 2349 2350 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2351 /* xer_ca is 1 iff src was negative and bits_shifted_out != 2352 0. Since the shift amount is known to be in the range 2353 0 .. 31 inclusive the following seems viable: 2354 xer.ca == 1 iff the following is nonzero: 2355 (argL >>s 31) -- either all 0s or all 1s 2356 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2357 xer_ca 2358 = binop( 2359 Iop_And32, 2360 binop(Iop_Sar32, argL, mkU8(31)), 2361 binop( Iop_And32, 2362 argL, 2363 binop( Iop_Sub32, 2364 binop(Iop_Shl32, mkU32(1), 2365 unop(Iop_32to8,argR)), 2366 mkU32(1) ) 2367 ) 2368 ); 2369 xer_ca 2370 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))); 2371 break; 2372 2373 default: 2374 vex_printf("set_XER_CA: op = %u\n", op); 2375 vpanic("set_XER_CA(ppc)"); 2376 } 2377 2378 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2379 putXER_CA( unop(Iop_32to8, xer_ca) ); 2380 } 2381 2382 static void set_XER_CA_64 ( UInt op, IRExpr* res, 2383 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2384 { 2385 IRExpr* xer_ca; 2386 vassert(op < PPCG_FLAG_OP_NUMBER); 2387 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64); 2388 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64); 2389 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64); 2390 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64); 2391 2392 /* Incoming oldca is assumed to hold the values 0 or 1 only. This 2393 seems reasonable given that it's always generated by 2394 getXER_CA32(), which masks it accordingly. In any case it being 2395 0 or 1 is an invariant of the ppc guest state representation; 2396 if it has any other value, that invariant has been violated. */ 2397 2398 switch (op) { 2399 case /* 0 */ PPCG_FLAG_OP_ADD: 2400 /* res <u argL */ 2401 xer_ca 2402 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL)); 2403 break; 2404 2405 case /* 1 */ PPCG_FLAG_OP_ADDE: 2406 /* res <u argL || (old_ca==1 && res==argL) */ 2407 xer_ca 2408 = mkOR1( 2409 binop(Iop_CmpLT64U, res, argL), 2410 mkAND1( 2411 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2412 binop(Iop_CmpEQ64, res, argL) 2413 ) 2414 ); 2415 xer_ca 2416 = unop(Iop_1Uto32, xer_ca); 2417 break; 2418 2419 case /* 8 */ PPCG_FLAG_OP_SUBFE: 2420 /* res <u argR || (old_ca==1 && res==argR) */ 2421 xer_ca 2422 = mkOR1( 2423 binop(Iop_CmpLT64U, res, argR), 2424 mkAND1( 2425 binop(Iop_CmpEQ64, oldca, mkU64(1)), 2426 binop(Iop_CmpEQ64, res, argR) 2427 ) 2428 ); 2429 xer_ca 2430 = unop(Iop_1Uto32, xer_ca); 2431 break; 2432 2433 case /* 7 */ PPCG_FLAG_OP_SUBFC: 2434 case /* 9 */ PPCG_FLAG_OP_SUBFI: 2435 /* res <=u argR */ 2436 xer_ca 2437 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR)); 2438 break; 2439 2440 2441 case /* 10 */ PPCG_FLAG_OP_SRAW: 2442 /* The shift amount is guaranteed to be in 0 .. 31 inclusive. 2443 If it is <= 31, behave like SRAWI; else XER.CA is the sign 2444 bit of argL. */ 2445 /* This term valid for shift amount < 31 only */ 2446 2447 xer_ca 2448 = binop( 2449 Iop_And64, 2450 binop(Iop_Sar64, argL, mkU8(31)), 2451 binop( Iop_And64, 2452 argL, 2453 binop( Iop_Sub64, 2454 binop(Iop_Shl64, mkU64(1), 2455 unop(Iop_64to8,argR)), 2456 mkU64(1) ) 2457 ) 2458 ); 2459 xer_ca 2460 = IRExpr_ITE( 2461 /* shift amt > 31 ? */ 2462 binop(Iop_CmpLT64U, mkU64(31), argR), 2463 /* yes -- get sign bit of argL */ 2464 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2465 /* no -- be like srawi */ 2466 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2467 ); 2468 break; 2469 2470 case /* 11 */ PPCG_FLAG_OP_SRAWI: 2471 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2472 Since the shift amount is known to be in the range 0 .. 31 2473 inclusive the following seems viable: 2474 xer.ca == 1 iff the following is nonzero: 2475 (argL >>s 31) -- either all 0s or all 1s 2476 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2477 2478 xer_ca 2479 = binop( 2480 Iop_And64, 2481 binop(Iop_Sar64, argL, mkU8(31)), 2482 binop( Iop_And64, 2483 argL, 2484 binop( Iop_Sub64, 2485 binop(Iop_Shl64, mkU64(1), 2486 unop(Iop_64to8,argR)), 2487 mkU64(1) ) 2488 ) 2489 ); 2490 xer_ca 2491 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2492 break; 2493 2494 2495 case /* 12 */ PPCG_FLAG_OP_SRAD: 2496 /* The shift amount is guaranteed to be in 0 .. 63 inclusive. 2497 If it is <= 63, behave like SRADI; else XER.CA is the sign 2498 bit of argL. */ 2499 /* This term valid for shift amount < 63 only */ 2500 2501 xer_ca 2502 = binop( 2503 Iop_And64, 2504 binop(Iop_Sar64, argL, mkU8(63)), 2505 binop( Iop_And64, 2506 argL, 2507 binop( Iop_Sub64, 2508 binop(Iop_Shl64, mkU64(1), 2509 unop(Iop_64to8,argR)), 2510 mkU64(1) ) 2511 ) 2512 ); 2513 xer_ca 2514 = IRExpr_ITE( 2515 /* shift amt > 63 ? */ 2516 binop(Iop_CmpLT64U, mkU64(63), argR), 2517 /* yes -- get sign bit of argL */ 2518 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))), 2519 /* no -- be like sradi */ 2520 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))) 2521 ); 2522 break; 2523 2524 2525 case /* 13 */ PPCG_FLAG_OP_SRADI: 2526 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0. 2527 Since the shift amount is known to be in the range 0 .. 63 2528 inclusive, the following seems viable: 2529 xer.ca == 1 iff the following is nonzero: 2530 (argL >>s 63) -- either all 0s or all 1s 2531 & (argL & (1<<argR)-1) -- the stuff shifted out */ 2532 2533 xer_ca 2534 = binop( 2535 Iop_And64, 2536 binop(Iop_Sar64, argL, mkU8(63)), 2537 binop( Iop_And64, 2538 argL, 2539 binop( Iop_Sub64, 2540 binop(Iop_Shl64, mkU64(1), 2541 unop(Iop_64to8,argR)), 2542 mkU64(1) ) 2543 ) 2544 ); 2545 xer_ca 2546 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))); 2547 break; 2548 2549 default: 2550 vex_printf("set_XER_CA: op = %u\n", op); 2551 vpanic("set_XER_CA(ppc64)"); 2552 } 2553 2554 /* xer_ca MUST denote either 0 or 1, no other value allowed */ 2555 putXER_CA( unop(Iop_32to8, xer_ca) ); 2556 } 2557 2558 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res, 2559 IRExpr* argL, IRExpr* argR, IRExpr* oldca ) 2560 { 2561 if (ty == Ity_I32) 2562 set_XER_CA_32( op, res, argL, argR, oldca ); 2563 else 2564 set_XER_CA_64( op, res, argL, argR, oldca ); 2565 } 2566 2567 2568 2569 /*------------------------------------------------------------*/ 2570 /*--- Read/write to guest-state --- */ 2571 /*------------------------------------------------------------*/ 2572 2573 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg ) 2574 { 2575 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2576 switch (reg) { 2577 case PPC_GST_SPRG3_RO: 2578 return IRExpr_Get( OFFB_SPRG3_RO, ty ); 2579 2580 case PPC_GST_CIA: 2581 return IRExpr_Get( OFFB_CIA, ty ); 2582 2583 case PPC_GST_LR: 2584 return IRExpr_Get( OFFB_LR, ty ); 2585 2586 case PPC_GST_CTR: 2587 return IRExpr_Get( OFFB_CTR, ty ); 2588 2589 case PPC_GST_VRSAVE: 2590 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); 2591 2592 case PPC_GST_VSCR: 2593 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ), 2594 mkU32(MASK_VSCR_VALID)); 2595 2596 case PPC_GST_CR: { 2597 /* Synthesise the entire CR into a single word. Expensive. */ 2598 # define FIELD(_n) \ 2599 binop(Iop_Shl32, \ 2600 unop(Iop_8Uto32, \ 2601 binop(Iop_Or8, \ 2602 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ 2603 binop(Iop_And8, getCR0(_n), mkU8(1)) \ 2604 ) \ 2605 ), \ 2606 mkU8(4 * (7-(_n))) \ 2607 ) 2608 return binop(Iop_Or32, 2609 binop(Iop_Or32, 2610 binop(Iop_Or32, FIELD(0), FIELD(1)), 2611 binop(Iop_Or32, FIELD(2), FIELD(3)) 2612 ), 2613 binop(Iop_Or32, 2614 binop(Iop_Or32, FIELD(4), FIELD(5)), 2615 binop(Iop_Or32, FIELD(6), FIELD(7)) 2616 ) 2617 ); 2618 # undef FIELD 2619 } 2620 2621 case PPC_GST_XER: 2622 return binop(Iop_Or32, 2623 binop(Iop_Or32, 2624 binop( Iop_Shl32, getXER_SO32(), mkU8(31)), 2625 binop( Iop_Shl32, getXER_OV32(), mkU8(30))), 2626 binop(Iop_Or32, 2627 binop( Iop_Shl32, getXER_CA32(), mkU8(29)), 2628 getXER_BC32())); 2629 2630 case PPC_GST_TFHAR: 2631 return IRExpr_Get( OFFB_TFHAR, ty ); 2632 2633 case PPC_GST_TEXASR: 2634 return IRExpr_Get( OFFB_TEXASR, ty ); 2635 2636 case PPC_GST_TFIAR: 2637 return IRExpr_Get( OFFB_TFIAR, ty ); 2638 2639 default: 2640 vex_printf("getGST(ppc): reg = %u", reg); 2641 vpanic("getGST(ppc)"); 2642 } 2643 } 2644 2645 /* Get a masked word from the given reg */ 2646 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask ) 2647 { 2648 IRTemp val = newTemp(Ity_I32); 2649 vassert( reg < PPC_GST_MAX ); 2650 2651 switch (reg) { 2652 2653 case PPC_GST_FPSCR: { 2654 /* Vex-generated code expects the FPSCR to be set as follows: 2655 all exceptions masked, round-to-nearest. 2656 This corresponds to a FPSCR value of 0x0. */ 2657 2658 /* In the lower 32 bits of FPSCR, we're only keeping track of 2659 * the binary floating point rounding mode, so if the mask isn't 2660 * asking for this, just return 0x0. 2661 */ 2662 if (mask & MASK_FPSCR_RN) { 2663 assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) ); 2664 } else { 2665 assign( val, mkU32(0x0) ); 2666 } 2667 break; 2668 } 2669 2670 default: 2671 vex_printf("getGST_masked(ppc): reg = %u", reg); 2672 vpanic("getGST_masked(ppc)"); 2673 } 2674 2675 if (mask != 0xFFFFFFFF) { 2676 return binop(Iop_And32, mkexpr(val), mkU32(mask)); 2677 } else { 2678 return mkexpr(val); 2679 } 2680 } 2681 2682 /* Get a masked word from the given reg */ 2683 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) { 2684 IRExpr * val; 2685 vassert( reg < PPC_GST_MAX ); 2686 2687 switch (reg) { 2688 2689 case PPC_GST_FPSCR: { 2690 /* In the upper 32 bits of FPSCR, we're only keeping track 2691 * of the decimal floating point rounding mode, so if the mask 2692 * isn't asking for this, just return 0x0. 2693 */ 2694 if (mask & MASK_FPSCR_DRN) { 2695 val = binop( Iop_And32, 2696 unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ), 2697 unop( Iop_64HIto32, mkU64( mask ) ) ); 2698 } else { 2699 val = mkU32( 0x0ULL ); 2700 } 2701 break; 2702 } 2703 2704 default: 2705 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg ); 2706 vpanic( "getGST_masked_upper(ppc)" ); 2707 } 2708 return val; 2709 } 2710 2711 2712 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation) 2713 and return it at the bottom of an I32; the top 27 bits are 2714 guaranteed to be zero. */ 2715 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld ) 2716 { 2717 UInt shft, mask; 2718 2719 vassert( fld < 8 ); 2720 vassert( reg < PPC_GST_MAX ); 2721 2722 shft = 4*(7-fld); 2723 mask = 0xF<<shft; 2724 2725 switch (reg) { 2726 case PPC_GST_XER: 2727 vassert(fld ==7); 2728 return binop(Iop_Or32, 2729 binop(Iop_Or32, 2730 binop(Iop_Shl32, getXER_SO32(), mkU8(3)), 2731 binop(Iop_Shl32, getXER_OV32(), mkU8(2))), 2732 binop( Iop_Shl32, getXER_CA32(), mkU8(1))); 2733 break; 2734 2735 default: 2736 if (shft == 0) 2737 return getGST_masked( reg, mask ); 2738 else 2739 return binop(Iop_Shr32, 2740 getGST_masked( reg, mask ), 2741 mkU8(toUChar( shft ))); 2742 } 2743 } 2744 2745 static void putGST ( PPC_GST reg, IRExpr* src ) 2746 { 2747 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2748 IRType ty_src = typeOfIRExpr(irsb->tyenv,src ); 2749 vassert( reg < PPC_GST_MAX ); 2750 switch (reg) { 2751 case PPC_GST_IP_AT_SYSCALL: 2752 vassert( ty_src == ty ); 2753 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) ); 2754 break; 2755 case PPC_GST_CIA: 2756 vassert( ty_src == ty ); 2757 stmt( IRStmt_Put( OFFB_CIA, src ) ); 2758 break; 2759 case PPC_GST_LR: 2760 vassert( ty_src == ty ); 2761 stmt( IRStmt_Put( OFFB_LR, src ) ); 2762 break; 2763 case PPC_GST_CTR: 2764 vassert( ty_src == ty ); 2765 stmt( IRStmt_Put( OFFB_CTR, src ) ); 2766 break; 2767 case PPC_GST_VRSAVE: 2768 vassert( ty_src == Ity_I32 ); 2769 stmt( IRStmt_Put( OFFB_VRSAVE,src)); 2770 break; 2771 case PPC_GST_VSCR: 2772 vassert( ty_src == Ity_I32 ); 2773 stmt( IRStmt_Put( OFFB_VSCR, 2774 binop(Iop_And32, src, 2775 mkU32(MASK_VSCR_VALID)) ) ); 2776 break; 2777 case PPC_GST_XER: 2778 vassert( ty_src == Ity_I32 ); 2779 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) ); 2780 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) ); 2781 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) ); 2782 putXER_BC( unop(Iop_32to8, src) ); 2783 break; 2784 2785 case PPC_GST_EMWARN: 2786 vassert( ty_src == Ity_I32 ); 2787 stmt( IRStmt_Put( OFFB_EMNOTE,src) ); 2788 break; 2789 2790 case PPC_GST_CMSTART: 2791 vassert( ty_src == ty ); 2792 stmt( IRStmt_Put( OFFB_CMSTART, src) ); 2793 break; 2794 2795 case PPC_GST_CMLEN: 2796 vassert( ty_src == ty ); 2797 stmt( IRStmt_Put( OFFB_CMLEN, src) ); 2798 break; 2799 2800 case PPC_GST_TEXASR: 2801 vassert( ty_src == Ity_I64 ); 2802 stmt( IRStmt_Put( OFFB_TEXASR, src ) ); 2803 break; 2804 case PPC_GST_TFIAR: 2805 vassert( ty_src == Ity_I64 ); 2806 stmt( IRStmt_Put( OFFB_TFIAR, src ) ); 2807 break; 2808 case PPC_GST_TFHAR: 2809 vassert( ty_src == Ity_I64 ); 2810 stmt( IRStmt_Put( OFFB_TFHAR, src ) ); 2811 break; 2812 default: 2813 vex_printf("putGST(ppc): reg = %u", reg); 2814 vpanic("putGST(ppc)"); 2815 } 2816 } 2817 2818 /* Write masked src to the given reg */ 2819 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask ) 2820 { 2821 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2822 vassert( reg < PPC_GST_MAX ); 2823 vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 ); 2824 2825 switch (reg) { 2826 case PPC_GST_FPSCR: { 2827 /* Allow writes to either binary or decimal floating point 2828 * Rounding Mode 2829 */ 2830 if (mask & MASK_FPSCR_RN) { 2831 stmt( IRStmt_Put( OFFB_FPROUND, 2832 unop( Iop_32to8, 2833 binop( Iop_And32, 2834 unop( Iop_64to32, src ), 2835 mkU32( MASK_FPSCR_RN & mask ) ) ) ) ); 2836 } else if (mask & MASK_FPSCR_DRN) { 2837 stmt( IRStmt_Put( OFFB_DFPROUND, 2838 unop( Iop_32to8, 2839 binop( Iop_And32, 2840 unop( Iop_64HIto32, src ), 2841 mkU32( ( MASK_FPSCR_DRN & mask ) 2842 >> 32 ) ) ) ) ); 2843 } 2844 2845 /* Give EmNote for attempted writes to: 2846 - Exception Controls 2847 - Non-IEEE Mode 2848 */ 2849 if (mask & 0xFC) { // Exception Control, Non-IEE mode 2850 VexEmNote ew = EmWarn_PPCexns; 2851 2852 /* If any of the src::exception_control bits are actually set, 2853 side-exit to the next insn, reporting the warning, 2854 so that Valgrind's dispatcher sees the warning. */ 2855 putGST( PPC_GST_EMWARN, mkU32(ew) ); 2856 stmt( 2857 IRStmt_Exit( 2858 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)), 2859 Ijk_EmWarn, 2860 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 2861 } 2862 2863 /* Ignore all other writes */ 2864 break; 2865 } 2866 2867 default: 2868 vex_printf("putGST_masked(ppc): reg = %u", reg); 2869 vpanic("putGST_masked(ppc)"); 2870 } 2871 } 2872 2873 /* Write the least significant nibble of src to the specified 2874 REG[FLD] (as per IBM/hardware notation). */ 2875 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld ) 2876 { 2877 UInt shft; 2878 ULong mask; 2879 2880 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 ); 2881 vassert( fld < 16 ); 2882 vassert( reg < PPC_GST_MAX ); 2883 2884 if (fld < 8) 2885 shft = 4*(7-fld); 2886 else 2887 shft = 4*(15-fld); 2888 mask = 0xF; 2889 mask = mask << shft; 2890 2891 switch (reg) { 2892 case PPC_GST_CR: 2893 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src))); 2894 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src))); 2895 break; 2896 2897 default: 2898 { 2899 IRExpr * src64 = unop( Iop_32Uto64, src ); 2900 2901 if (shft == 0) { 2902 putGST_masked( reg, src64, mask ); 2903 } else { 2904 putGST_masked( reg, 2905 binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ), 2906 mask ); 2907 } 2908 } 2909 } 2910 } 2911 2912 /*------------------------------------------------------------*/ 2913 /* Helpers for VSX instructions that do floating point 2914 * operations and need to determine if a src contains a 2915 * special FP value. 2916 * 2917 *------------------------------------------------------------*/ 2918 2919 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL 2920 #define FP_FRAC_PART(x) binop( Iop_And64, \ 2921 mkexpr( x ), \ 2922 mkU64( NONZERO_FRAC_MASK ) ) 2923 2924 // Returns exponent part of a single precision floating point as I32 2925 static IRExpr * fp_exp_part_sp(IRTemp src) 2926 { 2927 return binop( Iop_And32, 2928 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 2929 mkU32( 0xff ) ); 2930 } 2931 2932 // Returns exponent part of floating point as I32 2933 static IRExpr * fp_exp_part(IRTemp src, Bool sp) 2934 { 2935 IRExpr * exp; 2936 if (sp) 2937 return fp_exp_part_sp(src); 2938 2939 if (!mode64) 2940 exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32, 2941 mkexpr( src ) ), 2942 mkU8( 20 ) ), mkU32( 0x7ff ) ); 2943 else 2944 exp = unop( Iop_64to32, 2945 binop( Iop_And64, 2946 binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ), 2947 mkU64( 0x7ff ) ) ); 2948 return exp; 2949 } 2950 2951 static IRExpr * is_Inf_sp(IRTemp src) 2952 { 2953 IRTemp frac_part = newTemp(Ity_I32); 2954 IRExpr * Inf_exp; 2955 2956 assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) ); 2957 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) ); 2958 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) ); 2959 } 2960 2961 2962 // Infinity: exp = 7ff and fraction is zero; s = 0/1 2963 static IRExpr * is_Inf(IRTemp src, Bool sp) 2964 { 2965 IRExpr * Inf_exp, * hi32, * low32; 2966 IRTemp frac_part; 2967 2968 if (sp) 2969 return is_Inf_sp(src); 2970 2971 frac_part = newTemp(Ity_I64); 2972 assign( frac_part, FP_FRAC_PART(src) ); 2973 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), mkU32( 0x7ff ) ); 2974 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 2975 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 2976 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 2977 mkU32( 0 ) ) ); 2978 } 2979 2980 static IRExpr * is_Zero_sp(IRTemp src) 2981 { 2982 IRTemp sign_less_part = newTemp(Ity_I32); 2983 assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) ); 2984 return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) ); 2985 } 2986 2987 // Zero: exp is zero and fraction is zero; s = 0/1 2988 static IRExpr * is_Zero(IRTemp src, Bool sp) 2989 { 2990 IRExpr * hi32, * low32; 2991 IRTemp sign_less_part; 2992 if (sp) 2993 return is_Zero_sp(src); 2994 2995 sign_less_part = newTemp(Ity_I64); 2996 2997 assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) ); 2998 hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) ); 2999 low32 = unop( Iop_64to32, mkexpr( sign_less_part ) ); 3000 return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ), 3001 mkU32( 0 ) ); 3002 } 3003 3004 /* SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1' 3005 * QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0' 3006 * This function returns an IRExpr value of '1' for any type of NaN. 3007 */ 3008 static IRExpr * is_NaN(IRTemp src) 3009 { 3010 IRExpr * NaN_exp, * hi32, * low32; 3011 IRTemp frac_part = newTemp(Ity_I64); 3012 3013 assign( frac_part, FP_FRAC_PART(src) ); 3014 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 3015 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 3016 NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), 3017 mkU32( 0x7ff ) ); 3018 3019 return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 3020 mkU32( 0 ) ) ); 3021 } 3022 3023 /* This function returns an IRExpr value of '1' for any type of NaN. 3024 * The passed 'src' argument is assumed to be Ity_I32. 3025 */ 3026 static IRExpr * is_NaN_32(IRTemp src) 3027 { 3028 #define NONZERO_FRAC_MASK32 0x007fffffULL 3029 #define FP_FRAC_PART32(x) binop( Iop_And32, \ 3030 mkexpr( x ), \ 3031 mkU32( NONZERO_FRAC_MASK32 ) ) 3032 3033 IRExpr * frac_part = FP_FRAC_PART32(src); 3034 IRExpr * exp_part = binop( Iop_And32, 3035 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ), 3036 mkU32( 0x0ff ) ); 3037 IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) ); 3038 3039 return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) ); 3040 } 3041 3042 /* This function takes an Ity_I32 input argument interpreted 3043 * as a single-precision floating point value. If src is a 3044 * SNaN, it is changed to a QNaN and returned; otherwise, 3045 * the original value is returned. 3046 */ 3047 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src) 3048 { 3049 #define SNAN_MASK32 0x00400000 3050 IRTemp tmp = newTemp(Ity_I32); 3051 IRTemp mask = newTemp(Ity_I32); 3052 IRTemp is_SNAN = newTemp(Ity_I1); 3053 3054 vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 ); 3055 assign(tmp, src); 3056 3057 /* check if input is SNaN, if it is convert to QNaN */ 3058 assign( is_SNAN, 3059 mkAND1( is_NaN_32( tmp ), 3060 binop( Iop_CmpEQ32, 3061 binop( Iop_And32, mkexpr( tmp ), 3062 mkU32( SNAN_MASK32 ) ), 3063 mkU32( 0 ) ) ) ); 3064 /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */ 3065 assign ( mask, binop( Iop_And32, 3066 unop( Iop_1Sto32, mkexpr( is_SNAN ) ), 3067 mkU32( SNAN_MASK32 ) ) ); 3068 return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) ); 3069 } 3070 3071 3072 /* This helper function performs the negation part of operations of the form: 3073 * "Negate Multiply-<op>" 3074 * where "<op>" is either "Add" or "Sub". 3075 * 3076 * This function takes one argument -- the floating point intermediate result (converted to 3077 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of 3078 * the operation described above. 3079 */ 3080 static IRTemp getNegatedResult(IRTemp intermediateResult) 3081 { 3082 ULong signbit_mask = 0x8000000000000000ULL; 3083 IRTemp signbit_32 = newTemp(Ity_I32); 3084 IRTemp resultantSignbit = newTemp(Ity_I1); 3085 IRTemp negatedResult = newTemp(Ity_I64); 3086 assign( signbit_32, binop( Iop_Shr32, 3087 unop( Iop_64HIto32, 3088 binop( Iop_And64, mkexpr( intermediateResult ), 3089 mkU64( signbit_mask ) ) ), 3090 mkU8( 31 ) ) ); 3091 /* We negate the signbit if and only if the intermediate result from the 3092 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 3093 */ 3094 assign( resultantSignbit, 3095 unop( Iop_Not1, 3096 binop( Iop_CmpEQ32, 3097 binop( Iop_Xor32, 3098 mkexpr( signbit_32 ), 3099 unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ), 3100 mkU32( 1 ) ) ) ); 3101 3102 assign( negatedResult, 3103 binop( Iop_Or64, 3104 binop( Iop_And64, 3105 mkexpr( intermediateResult ), 3106 mkU64( ~signbit_mask ) ), 3107 binop( Iop_32HLto64, 3108 binop( Iop_Shl32, 3109 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 3110 mkU8( 31 ) ), 3111 mkU32( 0 ) ) ) ); 3112 3113 return negatedResult; 3114 } 3115 3116 /* This helper function performs the negation part of operations of the form: 3117 * "Negate Multiply-<op>" 3118 * where "<op>" is either "Add" or "Sub". 3119 * 3120 * This function takes one argument -- the floating point intermediate result (converted to 3121 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of 3122 * the operation described above. 3123 */ 3124 static IRTemp getNegatedResult_32(IRTemp intermediateResult) 3125 { 3126 UInt signbit_mask = 0x80000000; 3127 IRTemp signbit_32 = newTemp(Ity_I32); 3128 IRTemp resultantSignbit = newTemp(Ity_I1); 3129 IRTemp negatedResult = newTemp(Ity_I32); 3130 assign( signbit_32, binop( Iop_Shr32, 3131 binop( Iop_And32, mkexpr( intermediateResult ), 3132 mkU32( signbit_mask ) ), 3133 mkU8( 31 ) ) ); 3134 /* We negate the signbit if and only if the intermediate result from the 3135 * multiply-<op> was NOT a NaN. This is an XNOR predicate. 3136 */ 3137 assign( resultantSignbit, 3138 unop( Iop_Not1, 3139 binop( Iop_CmpEQ32, 3140 binop( Iop_Xor32, 3141 mkexpr( signbit_32 ), 3142 unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ), 3143 mkU32( 1 ) ) ) ); 3144 3145 assign( negatedResult, 3146 binop( Iop_Or32, 3147 binop( Iop_And32, 3148 mkexpr( intermediateResult ), 3149 mkU32( ~signbit_mask ) ), 3150 binop( Iop_Shl32, 3151 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ), 3152 mkU8( 31 ) ) ) ); 3153 3154 return negatedResult; 3155 } 3156 3157 /*------------------------------------------------------------*/ 3158 /* Transactional memory helpers 3159 * 3160 *------------------------------------------------------------*/ 3161 3162 static ULong generate_TMreason( UInt failure_code, 3163 UInt persistant, 3164 UInt nest_overflow, 3165 UInt tm_exact ) 3166 { 3167 ULong tm_err_code = 3168 ( (ULong) 0) << (63-6) /* Failure code */ 3169 | ( (ULong) persistant) << (63-7) /* Failure persistant */ 3170 | ( (ULong) 0) << (63-8) /* Disallowed */ 3171 | ( (ULong) nest_overflow) << (63-9) /* Nesting Overflow */ 3172 | ( (ULong) 0) << (63-10) /* Footprint Overflow */ 3173 | ( (ULong) 0) << (63-11) /* Self-Induced Conflict */ 3174 | ( (ULong) 0) << (63-12) /* Non-Transactional Conflict */ 3175 | ( (ULong) 0) << (63-13) /* Transactional Conflict */ 3176 | ( (ULong) 0) << (63-14) /* Translation Invalidation Conflict */ 3177 | ( (ULong) 0) << (63-15) /* Implementation-specific */ 3178 | ( (ULong) 0) << (63-16) /* Instruction Fetch Conflict */ 3179 | ( (ULong) 0) << (63-30) /* Reserved */ 3180 | ( (ULong) 0) << (63-31) /* Abort */ 3181 | ( (ULong) 0) << (63-32) /* Suspend */ 3182 | ( (ULong) 0) << (63-33) /* Reserved */ 3183 | ( (ULong) 0) << (63-35) /* Privilege */ 3184 | ( (ULong) 0) << (63-36) /* Failure Summary */ 3185 | ( (ULong) tm_exact) << (63-37) /* TFIAR Exact */ 3186 | ( (ULong) 0) << (63-38) /* ROT */ 3187 | ( (ULong) 0) << (63-51) /* Reserved */ 3188 | ( (ULong) 0) << (63-63); /* Transaction Level */ 3189 3190 return tm_err_code; 3191 } 3192 3193 static void storeTMfailure( Addr64 err_address, ULong tm_reason, 3194 Addr64 handler_address ) 3195 { 3196 putGST( PPC_GST_TFIAR, mkU64( err_address ) ); 3197 putGST( PPC_GST_TEXASR, mkU64( tm_reason ) ); 3198 putGST( PPC_GST_TFHAR, mkU64( handler_address ) ); 3199 } 3200 3201 /*------------------------------------------------------------*/ 3202 /*--- Integer Instruction Translation --- */ 3203 /*------------------------------------------------------------*/ 3204 3205 /* 3206 Integer Arithmetic Instructions 3207 */ 3208 static Bool dis_int_arith ( UInt theInstr ) 3209 { 3210 /* D-Form, XO-Form */ 3211 UChar opc1 = ifieldOPC(theInstr); 3212 UChar rD_addr = ifieldRegDS(theInstr); 3213 UChar rA_addr = ifieldRegA(theInstr); 3214 UInt uimm16 = ifieldUIMM16(theInstr); 3215 UChar rB_addr = ifieldRegB(theInstr); 3216 UChar flag_OE = ifieldBIT10(theInstr); 3217 UInt opc2 = ifieldOPClo9(theInstr); 3218 UChar flag_rC = ifieldBIT0(theInstr); 3219 3220 Long simm16 = extend_s_16to64(uimm16); 3221 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3222 IRTemp rA = newTemp(ty); 3223 IRTemp rB = newTemp(ty); 3224 IRTemp rD = newTemp(ty); 3225 3226 Bool do_rc = False; 3227 3228 assign( rA, getIReg(rA_addr) ); 3229 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB 3230 3231 switch (opc1) { 3232 /* D-Form */ 3233 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 3234 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3235 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3236 mkSzExtendS16(ty, uimm16) ) ); 3237 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3238 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3239 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3240 break; 3241 3242 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) 3243 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3244 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3245 mkSzExtendS16(ty, uimm16) ) ); 3246 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3247 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3248 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3249 do_rc = True; // Always record to CR 3250 flag_rC = 1; 3251 break; 3252 3253 case 0x0E: // addi (Add Immediate, PPC32 p350) 3254 // li rD,val == addi rD,0,val 3255 // la disp(rA) == addi rD,rA,disp 3256 if ( rA_addr == 0 ) { 3257 DIP("li r%u,%d\n", rD_addr, (Int)simm16); 3258 assign( rD, mkSzExtendS16(ty, uimm16) ); 3259 } else { 3260 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3261 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3262 mkSzExtendS16(ty, uimm16) ) ); 3263 } 3264 break; 3265 3266 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353) 3267 // lis rD,val == addis rD,0,val 3268 if ( rA_addr == 0 ) { 3269 DIP("lis r%u,%d\n", rD_addr, (Int)simm16); 3270 assign( rD, mkSzExtendS32(ty, uimm16 << 16) ); 3271 } else { 3272 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16); 3273 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3274 mkSzExtendS32(ty, uimm16 << 16) ) ); 3275 } 3276 break; 3277 3278 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490) 3279 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3280 if (mode64) 3281 assign( rD, unop(Iop_128to64, 3282 binop(Iop_MullS64, mkexpr(rA), 3283 mkSzExtendS16(ty, uimm16))) ); 3284 else 3285 assign( rD, unop(Iop_64to32, 3286 binop(Iop_MullS32, mkexpr(rA), 3287 mkSzExtendS16(ty, uimm16))) ); 3288 break; 3289 3290 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540) 3291 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16); 3292 // rD = simm16 - rA 3293 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3294 mkSzExtendS16(ty, uimm16), 3295 mkexpr(rA)) ); 3296 set_XER_CA( ty, PPCG_FLAG_OP_SUBFI, 3297 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16), 3298 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3299 break; 3300 3301 /* XO-Form */ 3302 case 0x1F: 3303 do_rc = True; // All below record to CR 3304 3305 switch (opc2) { 3306 case 0x10A: // add (Add, PPC32 p347) 3307 DIP("add%s%s r%u,r%u,r%u\n", 3308 flag_OE ? "o" : "", flag_rC ? ".":"", 3309 rD_addr, rA_addr, rB_addr); 3310 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3311 mkexpr(rA), mkexpr(rB) ) ); 3312 if (flag_OE) { 3313 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3314 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3315 } 3316 break; 3317 3318 case 0x00A: // addc (Add Carrying, PPC32 p348) 3319 DIP("addc%s%s r%u,r%u,r%u\n", 3320 flag_OE ? "o" : "", flag_rC ? ".":"", 3321 rD_addr, rA_addr, rB_addr); 3322 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3323 mkexpr(rA), mkexpr(rB)) ); 3324 set_XER_CA( ty, PPCG_FLAG_OP_ADD, 3325 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3326 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3327 if (flag_OE) { 3328 set_XER_OV( ty, PPCG_FLAG_OP_ADD, 3329 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3330 } 3331 break; 3332 3333 case 0x08A: { // adde (Add Extended, PPC32 p349) 3334 IRTemp old_xer_ca = newTemp(ty); 3335 DIP("adde%s%s r%u,r%u,r%u\n", 3336 flag_OE ? "o" : "", flag_rC ? ".":"", 3337 rD_addr, rA_addr, rB_addr); 3338 // rD = rA + rB + XER[CA] 3339 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3340 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3341 binop( mkSzOp(ty, Iop_Add8), 3342 mkexpr(rB), mkexpr(old_xer_ca))) ); 3343 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3344 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3345 mkexpr(old_xer_ca) ); 3346 if (flag_OE) { 3347 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3348 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3349 } 3350 break; 3351 } 3352 3353 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354) 3354 IRTemp old_xer_ca = newTemp(ty); 3355 IRExpr *min_one; 3356 if (rB_addr != 0) { 3357 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n"); 3358 return False; 3359 } 3360 DIP("addme%s%s r%u,r%u,r%u\n", 3361 flag_OE ? "o" : "", flag_rC ? ".":"", 3362 rD_addr, rA_addr, rB_addr); 3363 // rD = rA + (-1) + XER[CA] 3364 // => Just another form of adde 3365 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3366 min_one = mkSzImm(ty, (Long)-1); 3367 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA), 3368 binop( mkSzOp(ty, Iop_Add8), 3369 min_one, mkexpr(old_xer_ca)) )); 3370 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3371 mkexpr(rD), mkexpr(rA), min_one, 3372 mkexpr(old_xer_ca) ); 3373 if (flag_OE) { 3374 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3375 mkexpr(rD), mkexpr(rA), min_one ); 3376 } 3377 break; 3378 } 3379 3380 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355) 3381 IRTemp old_xer_ca = newTemp(ty); 3382 if (rB_addr != 0) { 3383 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n"); 3384 return False; 3385 } 3386 DIP("addze%s%s r%u,r%u,r%u\n", 3387 flag_OE ? "o" : "", flag_rC ? ".":"", 3388 rD_addr, rA_addr, rB_addr); 3389 // rD = rA + (0) + XER[CA] 3390 // => Just another form of adde 3391 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3392 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3393 mkexpr(rA), mkexpr(old_xer_ca)) ); 3394 set_XER_CA( ty, PPCG_FLAG_OP_ADDE, 3395 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3396 mkexpr(old_xer_ca) ); 3397 if (flag_OE) { 3398 set_XER_OV( ty, PPCG_FLAG_OP_ADDE, 3399 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3400 } 3401 break; 3402 } 3403 3404 case 0x1EB: // divw (Divide Word, PPC32 p388) 3405 DIP("divw%s%s r%u,r%u,r%u\n", 3406 flag_OE ? "o" : "", flag_rC ? ".":"", 3407 rD_addr, rA_addr, rB_addr); 3408 if (mode64) { 3409 /* Note: 3410 XER settings are mode independent, and reflect the 3411 overflow of the low-order 32bit result 3412 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3413 */ 3414 /* rD[hi32] are undefined: setting them to sign of lo32 3415 - makes set_CR0 happy */ 3416 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) ); 3417 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) ); 3418 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend, 3419 divisor) ) ); 3420 if (flag_OE) { 3421 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3422 mkexpr(rD), dividend, divisor ); 3423 } 3424 } else { 3425 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) ); 3426 if (flag_OE) { 3427 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3428 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3429 } 3430 } 3431 /* Note: 3432 if (0x8000_0000 / -1) or (x / 0) 3433 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3434 => But _no_ exception raised. */ 3435 break; 3436 3437 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389) 3438 DIP("divwu%s%s r%u,r%u,r%u\n", 3439 flag_OE ? "o" : "", flag_rC ? ".":"", 3440 rD_addr, rA_addr, rB_addr); 3441 if (mode64) { 3442 /* Note: 3443 XER settings are mode independent, and reflect the 3444 overflow of the low-order 32bit result 3445 CR0[LT|GT|EQ] are undefined if flag_rC && mode64 3446 */ 3447 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) ); 3448 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) ); 3449 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend, 3450 divisor) ) ); 3451 if (flag_OE) { 3452 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3453 mkexpr(rD), dividend, divisor ); 3454 } 3455 } else { 3456 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) ); 3457 if (flag_OE) { 3458 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3459 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3460 } 3461 } 3462 /* Note: ditto comment divw, for (x / 0) */ 3463 break; 3464 3465 case 0x04B: // mulhw (Multiply High Word, PPC32 p488) 3466 if (flag_OE != 0) { 3467 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n"); 3468 return False; 3469 } 3470 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3471 rD_addr, rA_addr, rB_addr); 3472 if (mode64) { 3473 /* rD[hi32] are undefined: setting them to sign of lo32 3474 - makes set_CR0 happy */ 3475 assign( rD, binop(Iop_Sar64, 3476 binop(Iop_Mul64, 3477 mk64lo32Sto64( mkexpr(rA) ), 3478 mk64lo32Sto64( mkexpr(rB) )), 3479 mkU8(32)) ); 3480 } else { 3481 assign( rD, unop(Iop_64HIto32, 3482 binop(Iop_MullS32, 3483 mkexpr(rA), mkexpr(rB))) ); 3484 } 3485 break; 3486 3487 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489) 3488 if (flag_OE != 0) { 3489 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n"); 3490 return False; 3491 } 3492 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3493 rD_addr, rA_addr, rB_addr); 3494 if (mode64) { 3495 /* rD[hi32] are undefined: setting them to sign of lo32 3496 - makes set_CR0 happy */ 3497 assign( rD, binop(Iop_Sar64, 3498 binop(Iop_Mul64, 3499 mk64lo32Uto64( mkexpr(rA) ), 3500 mk64lo32Uto64( mkexpr(rB) ) ), 3501 mkU8(32)) ); 3502 } else { 3503 assign( rD, unop(Iop_64HIto32, 3504 binop(Iop_MullU32, 3505 mkexpr(rA), mkexpr(rB))) ); 3506 } 3507 break; 3508 3509 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491) 3510 DIP("mullw%s%s r%u,r%u,r%u\n", 3511 flag_OE ? "o" : "", flag_rC ? ".":"", 3512 rD_addr, rA_addr, rB_addr); 3513 if (mode64) { 3514 /* rD[hi32] are undefined: setting them to sign of lo32 3515 - set_XER_OV() and set_CR0() depend on this */ 3516 IRExpr *a = unop(Iop_64to32, mkexpr(rA) ); 3517 IRExpr *b = unop(Iop_64to32, mkexpr(rB) ); 3518 assign( rD, binop(Iop_MullS32, a, b) ); 3519 if (flag_OE) { 3520 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3521 mkexpr(rD), 3522 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) ); 3523 } 3524 } else { 3525 assign( rD, unop(Iop_64to32, 3526 binop(Iop_MullU32, 3527 mkexpr(rA), mkexpr(rB))) ); 3528 if (flag_OE) { 3529 set_XER_OV( ty, PPCG_FLAG_OP_MULLW, 3530 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3531 } 3532 } 3533 break; 3534 3535 case 0x068: // neg (Negate, PPC32 p493) 3536 if (rB_addr != 0) { 3537 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n"); 3538 return False; 3539 } 3540 DIP("neg%s%s r%u,r%u\n", 3541 flag_OE ? "o" : "", flag_rC ? ".":"", 3542 rD_addr, rA_addr); 3543 // rD = (~rA) + 1 3544 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3545 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ), 3546 mkSzImm(ty, 1)) ); 3547 if (flag_OE) { 3548 set_XER_OV( ty, PPCG_FLAG_OP_NEG, 3549 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3550 } 3551 break; 3552 3553 case 0x028: // subf (Subtract From, PPC32 p537) 3554 DIP("subf%s%s r%u,r%u,r%u\n", 3555 flag_OE ? "o" : "", flag_rC ? ".":"", 3556 rD_addr, rA_addr, rB_addr); 3557 // rD = rB - rA 3558 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3559 mkexpr(rB), mkexpr(rA)) ); 3560 if (flag_OE) { 3561 set_XER_OV( ty, PPCG_FLAG_OP_SUBF, 3562 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3563 } 3564 break; 3565 3566 case 0x008: // subfc (Subtract from Carrying, PPC32 p538) 3567 DIP("subfc%s%s r%u,r%u,r%u\n", 3568 flag_OE ? "o" : "", flag_rC ? ".":"", 3569 rD_addr, rA_addr, rB_addr); 3570 // rD = rB - rA 3571 assign( rD, binop( mkSzOp(ty, Iop_Sub8), 3572 mkexpr(rB), mkexpr(rA)) ); 3573 set_XER_CA( ty, PPCG_FLAG_OP_SUBFC, 3574 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3575 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ ); 3576 if (flag_OE) { 3577 set_XER_OV( ty, PPCG_FLAG_OP_SUBFC, 3578 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3579 } 3580 break; 3581 3582 case 0x088: {// subfe (Subtract from Extended, PPC32 p539) 3583 IRTemp old_xer_ca = newTemp(ty); 3584 DIP("subfe%s%s r%u,r%u,r%u\n", 3585 flag_OE ? "o" : "", flag_rC ? ".":"", 3586 rD_addr, rA_addr, rB_addr); 3587 // rD = (log not)rA + rB + XER[CA] 3588 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3589 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3590 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3591 binop( mkSzOp(ty, Iop_Add8), 3592 mkexpr(rB), mkexpr(old_xer_ca))) ); 3593 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3594 mkexpr(rD), mkexpr(rA), mkexpr(rB), 3595 mkexpr(old_xer_ca) ); 3596 if (flag_OE) { 3597 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3598 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3599 } 3600 break; 3601 } 3602 3603 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541) 3604 IRTemp old_xer_ca = newTemp(ty); 3605 IRExpr *min_one; 3606 if (rB_addr != 0) { 3607 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n"); 3608 return False; 3609 } 3610 DIP("subfme%s%s r%u,r%u\n", 3611 flag_OE ? "o" : "", flag_rC ? ".":"", 3612 rD_addr, rA_addr); 3613 // rD = (log not)rA + (-1) + XER[CA] 3614 // => Just another form of subfe 3615 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3616 min_one = mkSzImm(ty, (Long)-1); 3617 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3618 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)), 3619 binop( mkSzOp(ty, Iop_Add8), 3620 min_one, mkexpr(old_xer_ca))) ); 3621 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3622 mkexpr(rD), mkexpr(rA), min_one, 3623 mkexpr(old_xer_ca) ); 3624 if (flag_OE) { 3625 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3626 mkexpr(rD), mkexpr(rA), min_one ); 3627 } 3628 break; 3629 } 3630 3631 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542) 3632 IRTemp old_xer_ca = newTemp(ty); 3633 if (rB_addr != 0) { 3634 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n"); 3635 return False; 3636 } 3637 DIP("subfze%s%s r%u,r%u\n", 3638 flag_OE ? "o" : "", flag_rC ? ".":"", 3639 rD_addr, rA_addr); 3640 // rD = (log not)rA + (0) + XER[CA] 3641 // => Just another form of subfe 3642 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) ); 3643 assign( rD, binop( mkSzOp(ty, Iop_Add8), 3644 unop( mkSzOp(ty, Iop_Not8), 3645 mkexpr(rA)), mkexpr(old_xer_ca)) ); 3646 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE, 3647 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0), 3648 mkexpr(old_xer_ca) ); 3649 if (flag_OE) { 3650 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE, 3651 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) ); 3652 } 3653 break; 3654 } 3655 3656 3657 /* 64bit Arithmetic */ 3658 case 0x49: // mulhd (Multiply High DWord, PPC64 p539) 3659 if (flag_OE != 0) { 3660 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n"); 3661 return False; 3662 } 3663 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3664 rD_addr, rA_addr, rB_addr); 3665 assign( rD, unop(Iop_128HIto64, 3666 binop(Iop_MullS64, 3667 mkexpr(rA), mkexpr(rB))) ); 3668 3669 break; 3670 3671 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540) 3672 if (flag_OE != 0) { 3673 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n"); 3674 return False; 3675 } 3676 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"", 3677 rD_addr, rA_addr, rB_addr); 3678 assign( rD, unop(Iop_128HIto64, 3679 binop(Iop_MullU64, 3680 mkexpr(rA), mkexpr(rB))) ); 3681 break; 3682 3683 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543) 3684 DIP("mulld%s%s r%u,r%u,r%u\n", 3685 flag_OE ? "o" : "", flag_rC ? ".":"", 3686 rD_addr, rA_addr, rB_addr); 3687 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) ); 3688 if (flag_OE) { 3689 set_XER_OV( ty, PPCG_FLAG_OP_MULLD, 3690 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3691 } 3692 break; 3693 3694 case 0x1E9: // divd (Divide DWord, PPC64 p419) 3695 DIP("divd%s%s r%u,r%u,r%u\n", 3696 flag_OE ? "o" : "", flag_rC ? ".":"", 3697 rD_addr, rA_addr, rB_addr); 3698 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) ); 3699 if (flag_OE) { 3700 set_XER_OV( ty, PPCG_FLAG_OP_DIVW, 3701 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3702 } 3703 break; 3704 /* Note: 3705 if (0x8000_0000_0000_0000 / -1) or (x / 0) 3706 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1 3707 => But _no_ exception raised. */ 3708 3709 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420) 3710 DIP("divdu%s%s r%u,r%u,r%u\n", 3711 flag_OE ? "o" : "", flag_rC ? ".":"", 3712 rD_addr, rA_addr, rB_addr); 3713 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) ); 3714 if (flag_OE) { 3715 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU, 3716 mkexpr(rD), mkexpr(rA), mkexpr(rB) ); 3717 } 3718 break; 3719 /* Note: ditto comment divd, for (x / 0) */ 3720 3721 case 0x18B: // divweu (Divide Word Extended Unsigned) 3722 { 3723 /* 3724 * If (RA) >= (RB), or if an attempt is made to perform the division 3725 * <anything> / 0 3726 * then the contents of register RD are undefined as are (if Rc=1) the contents of 3727 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set 3728 * to 1. 3729 */ 3730 IRTemp res = newTemp(Ity_I32); 3731 IRExpr * dividend, * divisor; 3732 DIP("divweu%s%s r%u,r%u,r%u\n", 3733 flag_OE ? "o" : "", flag_rC ? ".":"", 3734 rD_addr, rA_addr, rB_addr); 3735 if (mode64) { 3736 dividend = unop( Iop_64to32, mkexpr( rA ) ); 3737 divisor = unop( Iop_64to32, mkexpr( rB ) ); 3738 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 3739 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 3740 } else { 3741 dividend = mkexpr( rA ); 3742 divisor = mkexpr( rB ); 3743 assign( res, binop( Iop_DivU32E, dividend, divisor ) ); 3744 assign( rD, mkexpr( res) ); 3745 } 3746 3747 if (flag_OE) { 3748 set_XER_OV_32( PPCG_FLAG_OP_DIVWEU, 3749 mkexpr(res), dividend, divisor ); 3750 } 3751 break; 3752 } 3753 3754 case 0x1AB: // divwe (Divide Word Extended) 3755 { 3756 /* 3757 * If the quotient cannot be represented in 32 bits, or if an 3758 * attempt is made to perform the division 3759 * <anything> / 0 3760 * then the contents of register RD are undefined as are (if 3761 * Rc=1) the contents of the LT, GT, and EQ bits of CR 3762 * Field 0. In these cases, if OE=1 then OV is set to 1. 3763 */ 3764 3765 IRTemp res = newTemp(Ity_I32); 3766 IRExpr * dividend, * divisor; 3767 DIP("divwe%s%s r%u,r%u,r%u\n", 3768 flag_OE ? "o" : "", flag_rC ? ".":"", 3769 rD_addr, rA_addr, rB_addr); 3770 if (mode64) { 3771 dividend = unop( Iop_64to32, mkexpr( rA ) ); 3772 divisor = unop( Iop_64to32, mkexpr( rB ) ); 3773 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 3774 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) ); 3775 } else { 3776 dividend = mkexpr( rA ); 3777 divisor = mkexpr( rB ); 3778 assign( res, binop( Iop_DivS32E, dividend, divisor ) ); 3779 assign( rD, mkexpr( res) ); 3780 } 3781 3782 if (flag_OE) { 3783 set_XER_OV_32( PPCG_FLAG_OP_DIVWE, 3784 mkexpr(res), dividend, divisor ); 3785 } 3786 break; 3787 } 3788 3789 3790 case 0x1A9: // divde (Divide Doubleword Extended) 3791 /* 3792 * If the quotient cannot be represented in 64 bits, or if an 3793 * attempt is made to perform the division 3794 * <anything> / 0 3795 * then the contents of register RD are undefined as are (if 3796 * Rc=1) the contents of the LT, GT, and EQ bits of CR 3797 * Field 0. In these cases, if OE=1 then OV is set to 1. 3798 */ 3799 DIP("divde%s%s r%u,r%u,r%u\n", 3800 flag_OE ? "o" : "", flag_rC ? ".":"", 3801 rD_addr, rA_addr, rB_addr); 3802 assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) ); 3803 if (flag_OE) { 3804 set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ), 3805 mkexpr( rA ), mkexpr( rB ) ); 3806 } 3807 break; 3808 3809 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned) 3810 // Same CR and OV rules as given for divweu above 3811 DIP("divdeu%s%s r%u,r%u,r%u\n", 3812 flag_OE ? "o" : "", flag_rC ? ".":"", 3813 rD_addr, rA_addr, rB_addr); 3814 assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) ); 3815 if (flag_OE) { 3816 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ), 3817 mkexpr( rA ), mkexpr( rB ) ); 3818 } 3819 break; 3820 3821 default: 3822 vex_printf("dis_int_arith(ppc)(opc2)\n"); 3823 return False; 3824 } 3825 break; 3826 3827 default: 3828 vex_printf("dis_int_arith(ppc)(opc1)\n"); 3829 return False; 3830 } 3831 3832 putIReg( rD_addr, mkexpr(rD) ); 3833 3834 if (do_rc && flag_rC) { 3835 set_CR0( mkexpr(rD) ); 3836 } 3837 return True; 3838 } 3839 3840 3841 3842 /* 3843 Integer Compare Instructions 3844 */ 3845 static Bool dis_int_cmp ( UInt theInstr ) 3846 { 3847 /* D-Form, X-Form */ 3848 UChar opc1 = ifieldOPC(theInstr); 3849 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 3850 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) ); 3851 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) ); 3852 UChar rA_addr = ifieldRegA(theInstr); 3853 UInt uimm16 = ifieldUIMM16(theInstr); 3854 UChar rB_addr = ifieldRegB(theInstr); 3855 UInt opc2 = ifieldOPClo10(theInstr); 3856 UChar b0 = ifieldBIT0(theInstr); 3857 3858 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3859 IRExpr *a = getIReg(rA_addr); 3860 IRExpr *b; 3861 3862 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit. 3863 vex_printf("dis_int_cmp(ppc)(flag_L)\n"); 3864 return False; 3865 } 3866 3867 if (b22 != 0) { 3868 vex_printf("dis_int_cmp(ppc)(b22)\n"); 3869 return False; 3870 } 3871 3872 switch (opc1) { 3873 case 0x0B: // cmpi (Compare Immediate, PPC32 p368) 3874 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr, 3875 (Int)extend_s_16to32(uimm16)); 3876 b = mkSzExtendS16( ty, uimm16 ); 3877 if (flag_L == 1) { 3878 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 3879 } else { 3880 a = mkNarrowTo32( ty, a ); 3881 b = mkNarrowTo32( ty, b ); 3882 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b))); 3883 } 3884 putCR0( crfD, getXER_SO() ); 3885 break; 3886 3887 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370) 3888 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16); 3889 b = mkSzImm( ty, uimm16 ); 3890 if (flag_L == 1) { 3891 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 3892 } else { 3893 a = mkNarrowTo32( ty, a ); 3894 b = mkNarrowTo32( ty, b ); 3895 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 3896 } 3897 putCR0( crfD, getXER_SO() ); 3898 break; 3899 3900 /* X Form */ 3901 case 0x1F: 3902 if (b0 != 0) { 3903 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n"); 3904 return False; 3905 } 3906 b = getIReg(rB_addr); 3907 3908 switch (opc2) { 3909 case 0x000: // cmp (Compare, PPC32 p367) 3910 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 3911 /* Comparing a reg with itself produces a result which 3912 doesn't depend on the contents of the reg. Therefore 3913 remove the false dependency, which has been known to cause 3914 memcheck to produce false errors. */ 3915 if (rA_addr == rB_addr) 3916 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 3917 ? mkU64(0) : mkU32(0); 3918 if (flag_L == 1) { 3919 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b))); 3920 } else { 3921 a = mkNarrowTo32( ty, a ); 3922 b = mkNarrowTo32( ty, b ); 3923 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b))); 3924 } 3925 putCR0( crfD, getXER_SO() ); 3926 break; 3927 3928 case 0x020: // cmpl (Compare Logical, PPC32 p369) 3929 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr); 3930 /* Comparing a reg with itself produces a result which 3931 doesn't depend on the contents of the reg. Therefore 3932 remove the false dependency, which has been known to cause 3933 memcheck to produce false errors. */ 3934 if (rA_addr == rB_addr) 3935 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64 3936 ? mkU64(0) : mkU32(0); 3937 if (flag_L == 1) { 3938 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b))); 3939 } else { 3940 a = mkNarrowTo32( ty, a ); 3941 b = mkNarrowTo32( ty, b ); 3942 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b))); 3943 } 3944 putCR0( crfD, getXER_SO() ); 3945 break; 3946 3947 default: 3948 vex_printf("dis_int_cmp(ppc)(opc2)\n"); 3949 return False; 3950 } 3951 break; 3952 3953 default: 3954 vex_printf("dis_int_cmp(ppc)(opc1)\n"); 3955 return False; 3956 } 3957 3958 return True; 3959 } 3960 3961 3962 /* 3963 Integer Logical Instructions 3964 */ 3965 static Bool dis_int_logic ( UInt theInstr ) 3966 { 3967 /* D-Form, X-Form */ 3968 UChar opc1 = ifieldOPC(theInstr); 3969 UChar rS_addr = ifieldRegDS(theInstr); 3970 UChar rA_addr = ifieldRegA(theInstr); 3971 UInt uimm16 = ifieldUIMM16(theInstr); 3972 UChar rB_addr = ifieldRegB(theInstr); 3973 UInt opc2 = ifieldOPClo10(theInstr); 3974 UChar flag_rC = ifieldBIT0(theInstr); 3975 3976 IRType ty = mode64 ? Ity_I64 : Ity_I32; 3977 IRTemp rS = newTemp(ty); 3978 IRTemp rA = newTemp(ty); 3979 IRTemp rB = newTemp(ty); 3980 IRExpr* irx; 3981 Bool do_rc = False; 3982 3983 assign( rS, getIReg(rS_addr) ); 3984 assign( rB, getIReg(rB_addr) ); 3985 3986 switch (opc1) { 3987 case 0x1C: // andi. (AND Immediate, PPC32 p358) 3988 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3989 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 3990 mkSzImm(ty, uimm16)) ); 3991 do_rc = True; // Always record to CR 3992 flag_rC = 1; 3993 break; 3994 3995 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359) 3996 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 3997 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 3998 mkSzImm(ty, uimm16 << 16)) ); 3999 do_rc = True; // Always record to CR 4000 flag_rC = 1; 4001 break; 4002 4003 case 0x18: // ori (OR Immediate, PPC32 p497) 4004 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4005 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4006 mkSzImm(ty, uimm16)) ); 4007 break; 4008 4009 case 0x19: // oris (OR Immediate Shifted, PPC32 p498) 4010 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4011 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4012 mkSzImm(ty, uimm16 << 16)) ); 4013 break; 4014 4015 case 0x1A: // xori (XOR Immediate, PPC32 p550) 4016 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4017 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 4018 mkSzImm(ty, uimm16)) ); 4019 break; 4020 4021 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551) 4022 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16); 4023 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS), 4024 mkSzImm(ty, uimm16 << 16)) ); 4025 break; 4026 4027 /* X Form */ 4028 case 0x1F: 4029 do_rc = True; // All below record to CR, except for where we return at case end. 4030 4031 switch (opc2) { 4032 case 0x01C: // and (AND, PPC32 p356) 4033 DIP("and%s r%u,r%u,r%u\n", 4034 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4035 assign(rA, binop( mkSzOp(ty, Iop_And8), 4036 mkexpr(rS), mkexpr(rB))); 4037 break; 4038 4039 case 0x03C: // andc (AND with Complement, PPC32 p357) 4040 DIP("andc%s r%u,r%u,r%u\n", 4041 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4042 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS), 4043 unop( mkSzOp(ty, Iop_Not8), 4044 mkexpr(rB)))); 4045 break; 4046 4047 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371) 4048 IRExpr* lo32; 4049 if (rB_addr!=0) { 4050 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n"); 4051 return False; 4052 } 4053 DIP("cntlzw%s r%u,r%u\n", 4054 flag_rC ? ".":"", rA_addr, rS_addr); 4055 4056 // mode64: count in low word only 4057 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS); 4058 4059 // Iop_Clz32 undefined for arg==0, so deal with that case: 4060 irx = binop(Iop_CmpNE32, lo32, mkU32(0)); 4061 assign(rA, mkWidenFrom32(ty, 4062 IRExpr_ITE( irx, 4063 unop(Iop_Clz32, lo32), 4064 mkU32(32)), 4065 False)); 4066 4067 // TODO: alternatively: assign(rA, verbose_Clz32(rS)); 4068 break; 4069 } 4070 4071 case 0x11C: // eqv (Equivalent, PPC32 p396) 4072 DIP("eqv%s r%u,r%u,r%u\n", 4073 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4074 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4075 binop( mkSzOp(ty, Iop_Xor8), 4076 mkexpr(rS), mkexpr(rB))) ); 4077 break; 4078 4079 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397 4080 if (rB_addr!=0) { 4081 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n"); 4082 return False; 4083 } 4084 DIP("extsb%s r%u,r%u\n", 4085 flag_rC ? ".":"", rA_addr, rS_addr); 4086 if (mode64) 4087 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) ); 4088 else 4089 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) ); 4090 break; 4091 4092 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398) 4093 if (rB_addr!=0) { 4094 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n"); 4095 return False; 4096 } 4097 DIP("extsh%s r%u,r%u\n", 4098 flag_rC ? ".":"", rA_addr, rS_addr); 4099 if (mode64) 4100 assign( rA, unop(Iop_16Sto64, 4101 unop(Iop_64to16, mkexpr(rS))) ); 4102 else 4103 assign( rA, unop(Iop_16Sto32, 4104 unop(Iop_32to16, mkexpr(rS))) ); 4105 break; 4106 4107 case 0x1DC: // nand (NAND, PPC32 p492) 4108 DIP("nand%s r%u,r%u,r%u\n", 4109 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4110 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4111 binop( mkSzOp(ty, Iop_And8), 4112 mkexpr(rS), mkexpr(rB))) ); 4113 break; 4114 4115 case 0x07C: // nor (NOR, PPC32 p494) 4116 DIP("nor%s r%u,r%u,r%u\n", 4117 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4118 assign( rA, unop( mkSzOp(ty, Iop_Not8), 4119 binop( mkSzOp(ty, Iop_Or8), 4120 mkexpr(rS), mkexpr(rB))) ); 4121 break; 4122 4123 case 0x1BC: // or (OR, PPC32 p495) 4124 if ((!flag_rC) && rS_addr == rB_addr) { 4125 DIP("mr r%u,r%u\n", rA_addr, rS_addr); 4126 assign( rA, mkexpr(rS) ); 4127 } else { 4128 DIP("or%s r%u,r%u,r%u\n", 4129 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4130 assign( rA, binop( mkSzOp(ty, Iop_Or8), 4131 mkexpr(rS), mkexpr(rB)) ); 4132 } 4133 break; 4134 4135 case 0x19C: // orc (OR with Complement, PPC32 p496) 4136 DIP("orc%s r%u,r%u,r%u\n", 4137 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4138 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS), 4139 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB)))); 4140 break; 4141 4142 case 0x13C: // xor (XOR, PPC32 p549) 4143 DIP("xor%s r%u,r%u,r%u\n", 4144 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 4145 assign( rA, binop( mkSzOp(ty, Iop_Xor8), 4146 mkexpr(rS), mkexpr(rB)) ); 4147 break; 4148 4149 4150 /* 64bit Integer Logical Instructions */ 4151 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430) 4152 if (rB_addr!=0) { 4153 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n"); 4154 return False; 4155 } 4156 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr); 4157 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS)))); 4158 break; 4159 4160 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401) 4161 if (rB_addr!=0) { 4162 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n"); 4163 return False; 4164 } 4165 DIP("cntlzd%s r%u,r%u\n", 4166 flag_rC ? ".":"", rA_addr, rS_addr); 4167 // Iop_Clz64 undefined for arg==0, so deal with that case: 4168 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0)); 4169 assign(rA, IRExpr_ITE( irx, 4170 unop(Iop_Clz64, mkexpr(rS)), 4171 mkU64(64) )); 4172 // TODO: alternatively: assign(rA, verbose_Clz64(rS)); 4173 break; 4174 4175 case 0x1FC: // cmpb (Power6: compare bytes) 4176 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 4177 4178 if (mode64) 4179 assign( rA, unop( Iop_V128to64, 4180 binop( Iop_CmpEQ8x16, 4181 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ), 4182 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) ) 4183 )) ); 4184 else 4185 assign( rA, unop( Iop_V128to32, 4186 binop( Iop_CmpEQ8x16, 4187 unop( Iop_32UtoV128, mkexpr(rS) ), 4188 unop( Iop_32UtoV128, mkexpr(rB) ) 4189 )) ); 4190 break; 4191 4192 case 0x2DF: { // mftgpr (move floating-point to general purpose register) 4193 IRTemp frB = newTemp(Ity_F64); 4194 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr); 4195 4196 assign( frB, getFReg(rB_addr)); // always F64 4197 if (mode64) 4198 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 4199 else 4200 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) ); 4201 4202 putIReg( rS_addr, mkexpr(rA)); 4203 return True; 4204 } 4205 4206 case 0x25F: { // mffgpr (move floating-point from general purpose register) 4207 IRTemp frA = newTemp(Ity_F64); 4208 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr); 4209 4210 if (mode64) 4211 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) ); 4212 else 4213 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) ); 4214 4215 putFReg( rS_addr, mkexpr(frA)); 4216 return True; 4217 } 4218 case 0x1FA: // popcntd (population count doubleword 4219 { 4220 DIP("popcntd r%u,r%u\n", rA_addr, rS_addr); 4221 IRTemp result = gen_POPCOUNT(ty, rS, DWORD); 4222 putIReg( rA_addr, mkexpr(result) ); 4223 return True; 4224 } 4225 case 0x17A: // popcntw (Population Count Words) 4226 { 4227 DIP("popcntw r%u,r%u\n", rA_addr, rS_addr); 4228 if (mode64) { 4229 IRTemp resultHi, resultLo; 4230 IRTemp argLo = newTemp(Ity_I32); 4231 IRTemp argHi = newTemp(Ity_I32); 4232 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4233 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4234 resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD); 4235 resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD); 4236 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo))); 4237 } else { 4238 IRTemp result = gen_POPCOUNT(ty, rS, WORD); 4239 putIReg( rA_addr, mkexpr(result) ); 4240 } 4241 return True; 4242 } 4243 case 0x7A: // popcntb (Population Count Byte) 4244 { 4245 DIP("popcntb r%u,r%u\n", rA_addr, rS_addr); 4246 4247 if (mode64) { 4248 IRTemp resultHi, resultLo; 4249 IRTemp argLo = newTemp(Ity_I32); 4250 IRTemp argHi = newTemp(Ity_I32); 4251 assign(argLo, unop(Iop_64to32, mkexpr(rS))); 4252 assign(argHi, unop(Iop_64HIto32, mkexpr(rS))); 4253 resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE); 4254 resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE); 4255 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), 4256 mkexpr(resultLo))); 4257 } else { 4258 IRTemp result = gen_POPCOUNT(ty, rS, BYTE); 4259 putIReg( rA_addr, mkexpr(result) ); 4260 } 4261 return True; 4262 } 4263 case 0x0FC: // bpermd (Bit Permute Doubleword) 4264 { 4265 /* This is a lot of rigmarole to emulate bpermd like this, as it 4266 * could be done much faster by implementing a call to the native 4267 * instruction. However, where possible I want to avoid using new 4268 * native instructions so that we can use valgrind to emulate those 4269 * instructions on older PPC64 hardware. 4270 */ 4271 #define BPERMD_IDX_MASK 0x00000000000000FFULL 4272 #define BPERMD_BIT_MASK 0x8000000000000000ULL 4273 int i; 4274 IRExpr * rS_expr = mkexpr(rS); 4275 IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0)); 4276 DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr); 4277 for (i = 0; i < 8; i++) { 4278 IRTemp idx_tmp = newTemp( Ity_I64 ); 4279 IRTemp perm_bit = newTemp( Ity_I64 ); 4280 IRTemp idx = newTemp( Ity_I8 ); 4281 IRTemp idx_LT64 = newTemp( Ity_I1 ); 4282 IRTemp idx_LT64_ity64 = newTemp( Ity_I64 ); 4283 4284 assign( idx_tmp, 4285 binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) ); 4286 assign( idx_LT64, 4287 binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) ); 4288 assign( idx, 4289 binop( Iop_And8, 4290 unop( Iop_1Sto8, 4291 mkexpr(idx_LT64) ), 4292 unop( Iop_64to8, mkexpr( idx_tmp ) ) ) ); 4293 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx 4294 * to determine which bit of rB to use for the perm bit, and then we shift 4295 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64 4296 * to set the final perm bit. 4297 */ 4298 assign( idx_LT64_ity64, 4299 unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) ); 4300 assign( perm_bit, 4301 binop( Iop_And64, 4302 mkexpr( idx_LT64_ity64 ), 4303 binop( Iop_Shr64, 4304 binop( Iop_And64, 4305 mkU64( BPERMD_BIT_MASK ), 4306 binop( Iop_Shl64, 4307 mkexpr( rB ), 4308 mkexpr( idx ) ) ), 4309 mkU8( 63 ) ) ) ); 4310 res = binop( Iop_Or64, 4311 res, 4312 binop( Iop_Shl64, 4313 mkexpr( perm_bit ), 4314 mkU8( i ) ) ); 4315 rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) ); 4316 } 4317 putIReg(rA_addr, res); 4318 return True; 4319 } 4320 4321 default: 4322 vex_printf("dis_int_logic(ppc)(opc2)\n"); 4323 return False; 4324 } 4325 break; 4326 4327 default: 4328 vex_printf("dis_int_logic(ppc)(opc1)\n"); 4329 return False; 4330 } 4331 4332 putIReg( rA_addr, mkexpr(rA) ); 4333 4334 if (do_rc && flag_rC) { 4335 set_CR0( mkexpr(rA) ); 4336 } 4337 return True; 4338 } 4339 4340 /* 4341 Integer Parity Instructions 4342 */ 4343 static Bool dis_int_parity ( UInt theInstr ) 4344 { 4345 /* X-Form */ 4346 UChar opc1 = ifieldOPC(theInstr); 4347 UChar rS_addr = ifieldRegDS(theInstr); 4348 UChar rA_addr = ifieldRegA(theInstr); 4349 UChar rB_addr = ifieldRegB(theInstr); 4350 UInt opc2 = ifieldOPClo10(theInstr); 4351 UChar b0 = ifieldBIT0(theInstr); 4352 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4353 4354 IRTemp rS = newTemp(ty); 4355 IRTemp rA = newTemp(ty); 4356 IRTemp iTot1 = newTemp(Ity_I32); 4357 IRTemp iTot2 = newTemp(Ity_I32); 4358 IRTemp iTot3 = newTemp(Ity_I32); 4359 IRTemp iTot4 = newTemp(Ity_I32); 4360 IRTemp iTot5 = newTemp(Ity_I32); 4361 IRTemp iTot6 = newTemp(Ity_I32); 4362 IRTemp iTot7 = newTemp(Ity_I32); 4363 IRTemp iTot8 = newTemp(Ity_I32); 4364 IRTemp rS1 = newTemp(ty); 4365 IRTemp rS2 = newTemp(ty); 4366 IRTemp rS3 = newTemp(ty); 4367 IRTemp rS4 = newTemp(ty); 4368 IRTemp rS5 = newTemp(ty); 4369 IRTemp rS6 = newTemp(ty); 4370 IRTemp rS7 = newTemp(ty); 4371 IRTemp iHi = newTemp(Ity_I32); 4372 IRTemp iLo = newTemp(Ity_I32); 4373 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1); 4374 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32); 4375 4376 if (opc1 != 0x1f || rB_addr || b0) { 4377 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n"); 4378 return False; 4379 } 4380 4381 assign( rS, getIReg(rS_addr) ); 4382 4383 switch (opc2) { 4384 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320) 4385 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr); 4386 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4387 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4388 assign( iTot2, binop(Iop_Add32, 4389 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4390 mkexpr(iTot1)) ); 4391 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4392 assign( iTot3, binop(Iop_Add32, 4393 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4394 mkexpr(iTot2)) ); 4395 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4396 assign( iTot4, binop(Iop_Add32, 4397 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4398 mkexpr(iTot3)) ); 4399 if (mode64) { 4400 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4401 assign( iTot5, binop(Iop_Add32, 4402 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))), 4403 mkexpr(iTot4)) ); 4404 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4405 assign( iTot6, binop(Iop_Add32, 4406 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4407 mkexpr(iTot5)) ); 4408 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4409 assign( iTot7, binop(Iop_Add32, 4410 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4411 mkexpr(iTot6)) ); 4412 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) ); 4413 assign( iTot8, binop(Iop_Add32, 4414 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4415 mkexpr(iTot7)) ); 4416 assign( rA, unop(Iop_32Uto64, 4417 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) ); 4418 } else 4419 assign( rA, mkexpr(iTot4) ); 4420 4421 break; 4422 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320) 4423 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) ); 4424 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) ); 4425 assign( iTot2, binop(Iop_Add32, 4426 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))), 4427 mkexpr(iTot1)) ); 4428 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) ); 4429 assign( iTot3, binop(Iop_Add32, 4430 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))), 4431 mkexpr(iTot2)) ); 4432 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) ); 4433 assign( iTot4, binop(Iop_Add32, 4434 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))), 4435 mkexpr(iTot3)) ); 4436 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) ); 4437 4438 if (mode64) { 4439 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) ); 4440 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) ); 4441 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) ); 4442 assign( iTot6, binop(Iop_Add32, 4443 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))), 4444 mkexpr(iTot5)) ); 4445 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) ); 4446 assign( iTot7, binop(Iop_Add32, 4447 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))), 4448 mkexpr(iTot6)) ); 4449 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8))); 4450 assign( iTot8, binop(Iop_Add32, 4451 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))), 4452 mkexpr(iTot7)) ); 4453 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ), 4454 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) ); 4455 } else 4456 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) ); 4457 break; 4458 default: 4459 vex_printf("dis_int_parity(ppc)(opc2)\n"); 4460 return False; 4461 } 4462 4463 putIReg( rA_addr, mkexpr(rA) ); 4464 4465 return True; 4466 } 4467 4468 4469 /* 4470 Integer Rotate Instructions 4471 */ 4472 static Bool dis_int_rot ( UInt theInstr ) 4473 { 4474 /* M-Form, MDS-Form */ 4475 UChar opc1 = ifieldOPC(theInstr); 4476 UChar rS_addr = ifieldRegDS(theInstr); 4477 UChar rA_addr = ifieldRegA(theInstr); 4478 UChar rB_addr = ifieldRegB(theInstr); 4479 UChar sh_imm = rB_addr; 4480 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) ); 4481 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) ); 4482 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) ); 4483 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) ); 4484 UChar b1 = ifieldBIT1(theInstr); 4485 UChar flag_rC = ifieldBIT0(theInstr); 4486 4487 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4488 IRTemp rS = newTemp(ty); 4489 IRTemp rA = newTemp(ty); 4490 IRTemp rB = newTemp(ty); 4491 IRTemp rot = newTemp(ty); 4492 IRExpr *r; 4493 UInt mask32; 4494 ULong mask64; 4495 4496 assign( rS, getIReg(rS_addr) ); 4497 assign( rB, getIReg(rB_addr) ); 4498 4499 switch (opc1) { 4500 case 0x14: { 4501 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500) 4502 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4503 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4504 if (mode64) { 4505 // tmp32 = (ROTL(rS_Lo32, Imm) 4506 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64) 4507 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4508 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4509 r = unop(Iop_32Uto64, r); 4510 assign( rot, binop(Iop_Or64, r, 4511 binop(Iop_Shl64, r, mkU8(32))) ); 4512 assign( rA, 4513 binop(Iop_Or64, 4514 binop(Iop_And64, mkexpr(rot), mkU64(mask64)), 4515 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) ); 4516 } 4517 else { 4518 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask); 4519 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4520 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4521 assign( rA, 4522 binop(Iop_Or32, 4523 binop(Iop_And32, mkU32(mask32), r), 4524 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) ); 4525 } 4526 break; 4527 } 4528 4529 case 0x15: { 4530 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501) 4531 vassert(MaskBeg < 32); 4532 vassert(MaskEnd < 32); 4533 vassert(sh_imm < 32); 4534 4535 if (mode64) { 4536 IRTemp rTmp = newTemp(Ity_I64); 4537 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4538 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4539 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4540 // tmp32 = (ROTL(rS_Lo32, Imm) 4541 // rA = ((tmp32 || tmp32) & mask64) 4542 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) ); 4543 r = unop(Iop_32Uto64, r); 4544 assign( rTmp, r ); 4545 r = NULL; 4546 assign( rot, binop(Iop_Or64, mkexpr(rTmp), 4547 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) ); 4548 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4549 } 4550 else { 4551 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) { 4552 /* Special-case the ,n,0,31-n form as that is just n-bit 4553 shift left, PPC32 p501 */ 4554 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4555 rA_addr, rS_addr, sh_imm); 4556 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) ); 4557 } 4558 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) { 4559 /* Special-case the ,32-n,n,31 form as that is just n-bit 4560 unsigned shift right, PPC32 p501 */ 4561 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"", 4562 rA_addr, rS_addr, MaskBeg); 4563 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) ); 4564 } 4565 else { 4566 /* General case. */ 4567 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4568 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"", 4569 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd); 4570 // rA = ROTL(rS, Imm) & mask 4571 assign( rA, binop(Iop_And32, 4572 ROTL(mkexpr(rS), mkU8(sh_imm)), 4573 mkU32(mask32)) ); 4574 } 4575 } 4576 break; 4577 } 4578 4579 case 0x17: { 4580 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503 4581 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"", 4582 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd); 4583 if (mode64) { 4584 mask64 = MASK64(31-MaskEnd, 31-MaskBeg); 4585 /* weird insn alert! 4586 tmp32 = (ROTL(rS_Lo32, rB[0-4]) 4587 rA = ((tmp32 || tmp32) & mask64) 4588 */ 4589 // note, ROTL does the masking, so we don't do it here 4590 r = ROTL( unop(Iop_64to32, mkexpr(rS)), 4591 unop(Iop_64to8, mkexpr(rB)) ); 4592 r = unop(Iop_32Uto64, r); 4593 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)))); 4594 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) ); 4595 } else { 4596 mask32 = MASK32(31-MaskEnd, 31-MaskBeg); 4597 // rA = ROTL(rS, rB[0-4]) & mask 4598 // note, ROTL does the masking, so we don't do it here 4599 assign( rA, binop(Iop_And32, 4600 ROTL(mkexpr(rS), 4601 unop(Iop_32to8, mkexpr(rB))), 4602 mkU32(mask32)) ); 4603 } 4604 break; 4605 } 4606 4607 /* 64bit Integer Rotates */ 4608 case 0x1E: { 4609 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1); 4610 sh_imm |= b1 << 5; 4611 4612 vassert( msk_imm < 64 ); 4613 vassert( sh_imm < 64 ); 4614 4615 switch (opc2) { 4616 case 0x4: { 4617 /* r = ROTL64( rS, rB_lo6) */ 4618 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) ); 4619 4620 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555) 4621 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4622 rA_addr, rS_addr, rB_addr, msk_imm); 4623 // note, ROTL does the masking, so we don't do it here 4624 mask64 = MASK64(0, 63-msk_imm); 4625 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4626 break; 4627 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556) 4628 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"", 4629 rA_addr, rS_addr, rB_addr, msk_imm); 4630 mask64 = MASK64(63-msk_imm, 63); 4631 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4632 break; 4633 } 4634 break; 4635 } 4636 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557) 4637 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4638 rA_addr, rS_addr, sh_imm, msk_imm); 4639 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4640 mask64 = MASK64(sh_imm, 63-msk_imm); 4641 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4642 break; 4643 // later: deal with special case: (msk_imm==0) => SHL(sh_imm) 4644 /* 4645 Hmm... looks like this'll do the job more simply: 4646 r = SHL(rS, sh_imm) 4647 m = ~(1 << (63-msk_imm)) 4648 assign(rA, r & m); 4649 */ 4650 4651 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558) 4652 if (mode64 4653 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) { 4654 /* special-case the ,64-n,n form as that is just 4655 unsigned shift-right by n */ 4656 DIP("srdi%s r%u,r%u,%u\n", 4657 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm); 4658 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) ); 4659 } else { 4660 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4661 rA_addr, rS_addr, sh_imm, msk_imm); 4662 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4663 mask64 = MASK64(0, 63-msk_imm); 4664 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4665 } 4666 break; 4667 4668 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559) 4669 if (mode64 4670 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) { 4671 /* special-case the ,n,63-n form as that is just 4672 shift-left by n */ 4673 DIP("sldi%s r%u,r%u,%u\n", 4674 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 4675 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) ); 4676 } else { 4677 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4678 rA_addr, rS_addr, sh_imm, msk_imm); 4679 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4680 mask64 = MASK64(63-msk_imm, 63); 4681 assign( rA, binop(Iop_And64, r, mkU64(mask64)) ); 4682 } 4683 break; 4684 4685 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560) 4686 IRTemp rA_orig = newTemp(ty); 4687 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"", 4688 rA_addr, rS_addr, sh_imm, msk_imm); 4689 r = ROTL(mkexpr(rS), mkU8(sh_imm)); 4690 mask64 = MASK64(sh_imm, 63-msk_imm); 4691 assign( rA_orig, getIReg(rA_addr) ); 4692 assign( rA, binop(Iop_Or64, 4693 binop(Iop_And64, mkU64(mask64), r), 4694 binop(Iop_And64, mkU64(~mask64), 4695 mkexpr(rA_orig))) ); 4696 break; 4697 } 4698 default: 4699 vex_printf("dis_int_rot(ppc)(opc2)\n"); 4700 return False; 4701 } 4702 break; 4703 } 4704 4705 default: 4706 vex_printf("dis_int_rot(ppc)(opc1)\n"); 4707 return False; 4708 } 4709 4710 putIReg( rA_addr, mkexpr(rA) ); 4711 4712 if (flag_rC) { 4713 set_CR0( mkexpr(rA) ); 4714 } 4715 return True; 4716 } 4717 4718 4719 /* 4720 Integer Load Instructions 4721 */ 4722 static Bool dis_int_load ( UInt theInstr ) 4723 { 4724 /* D-Form, X-Form, DS-Form */ 4725 UChar opc1 = ifieldOPC(theInstr); 4726 UChar rD_addr = ifieldRegDS(theInstr); 4727 UChar rA_addr = ifieldRegA(theInstr); 4728 UInt uimm16 = ifieldUIMM16(theInstr); 4729 UChar rB_addr = ifieldRegB(theInstr); 4730 UInt opc2 = ifieldOPClo10(theInstr); 4731 UChar b1 = ifieldBIT1(theInstr); 4732 UChar b0 = ifieldBIT0(theInstr); 4733 4734 Int simm16 = extend_s_16to32(uimm16); 4735 IRType ty = mode64 ? Ity_I64 : Ity_I32; 4736 IRTemp EA = newTemp(ty); 4737 IRExpr* val; 4738 4739 switch (opc1) { 4740 case 0x1F: // register offset 4741 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 4742 break; 4743 case 0x38: // immediate offset: 64bit: lq: maskoff 4744 // lowest 4 bits of immediate before forming EA 4745 simm16 = simm16 & 0xFFFFFFF0; 4746 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4747 break; 4748 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off 4749 // lowest 2 bits of immediate before forming EA 4750 simm16 = simm16 & 0xFFFFFFFC; 4751 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4752 break; 4753 default: // immediate offset 4754 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 4755 break; 4756 } 4757 4758 switch (opc1) { 4759 case 0x22: // lbz (Load B & Zero, PPC32 p433) 4760 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4761 val = loadBE(Ity_I8, mkexpr(EA)); 4762 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4763 break; 4764 4765 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434) 4766 if (rA_addr == 0 || rA_addr == rD_addr) { 4767 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n"); 4768 return False; 4769 } 4770 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4771 val = loadBE(Ity_I8, mkexpr(EA)); 4772 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4773 putIReg( rA_addr, mkexpr(EA) ); 4774 break; 4775 4776 case 0x2A: // lha (Load HW Alg, PPC32 p445) 4777 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4778 val = loadBE(Ity_I16, mkexpr(EA)); 4779 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4780 break; 4781 4782 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446) 4783 if (rA_addr == 0 || rA_addr == rD_addr) { 4784 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n"); 4785 return False; 4786 } 4787 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4788 val = loadBE(Ity_I16, mkexpr(EA)); 4789 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4790 putIReg( rA_addr, mkexpr(EA) ); 4791 break; 4792 4793 case 0x28: // lhz (Load HW & Zero, PPC32 p450) 4794 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4795 val = loadBE(Ity_I16, mkexpr(EA)); 4796 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4797 break; 4798 4799 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451) 4800 if (rA_addr == 0 || rA_addr == rD_addr) { 4801 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n"); 4802 return False; 4803 } 4804 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4805 val = loadBE(Ity_I16, mkexpr(EA)); 4806 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4807 putIReg( rA_addr, mkexpr(EA) ); 4808 break; 4809 4810 case 0x20: // lwz (Load W & Zero, PPC32 p460) 4811 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4812 val = loadBE(Ity_I32, mkexpr(EA)); 4813 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4814 break; 4815 4816 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461)) 4817 if (rA_addr == 0 || rA_addr == rD_addr) { 4818 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n"); 4819 return False; 4820 } 4821 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr); 4822 val = loadBE(Ity_I32, mkexpr(EA)); 4823 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4824 putIReg( rA_addr, mkexpr(EA) ); 4825 break; 4826 4827 /* X Form */ 4828 case 0x1F: 4829 if (b0 != 0) { 4830 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n"); 4831 return False; 4832 } 4833 4834 switch (opc2) { 4835 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435) 4836 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4837 if (rA_addr == 0 || rA_addr == rD_addr) { 4838 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 4839 return False; 4840 } 4841 val = loadBE(Ity_I8, mkexpr(EA)); 4842 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4843 putIReg( rA_addr, mkexpr(EA) ); 4844 break; 4845 4846 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436) 4847 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4848 val = loadBE(Ity_I8, mkexpr(EA)); 4849 putIReg( rD_addr, mkWidenFrom8(ty, val, False) ); 4850 break; 4851 4852 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447) 4853 if (rA_addr == 0 || rA_addr == rD_addr) { 4854 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n"); 4855 return False; 4856 } 4857 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4858 val = loadBE(Ity_I16, mkexpr(EA)); 4859 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4860 putIReg( rA_addr, mkexpr(EA) ); 4861 break; 4862 4863 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448) 4864 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4865 val = loadBE(Ity_I16, mkexpr(EA)); 4866 putIReg( rD_addr, mkWidenFrom16(ty, val, True) ); 4867 break; 4868 4869 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452) 4870 if (rA_addr == 0 || rA_addr == rD_addr) { 4871 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n"); 4872 return False; 4873 } 4874 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4875 val = loadBE(Ity_I16, mkexpr(EA)); 4876 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4877 putIReg( rA_addr, mkexpr(EA) ); 4878 break; 4879 4880 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453) 4881 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4882 val = loadBE(Ity_I16, mkexpr(EA)); 4883 putIReg( rD_addr, mkWidenFrom16(ty, val, False) ); 4884 break; 4885 4886 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462) 4887 if (rA_addr == 0 || rA_addr == rD_addr) { 4888 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n"); 4889 return False; 4890 } 4891 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4892 val = loadBE(Ity_I32, mkexpr(EA)); 4893 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4894 putIReg( rA_addr, mkexpr(EA) ); 4895 break; 4896 4897 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463) 4898 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4899 val = loadBE(Ity_I32, mkexpr(EA)); 4900 putIReg( rD_addr, mkWidenFrom32(ty, val, False) ); 4901 break; 4902 4903 4904 /* 64bit Loads */ 4905 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475) 4906 if (rA_addr == 0 || rA_addr == rD_addr) { 4907 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n"); 4908 return False; 4909 } 4910 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4911 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4912 putIReg( rA_addr, mkexpr(EA) ); 4913 break; 4914 4915 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476) 4916 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4917 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4918 break; 4919 4920 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501) 4921 if (rA_addr == 0 || rA_addr == rD_addr) { 4922 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n"); 4923 return False; 4924 } 4925 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4926 putIReg( rD_addr, 4927 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 4928 putIReg( rA_addr, mkexpr(EA) ); 4929 break; 4930 4931 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502) 4932 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 4933 putIReg( rD_addr, 4934 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 4935 break; 4936 4937 default: 4938 vex_printf("dis_int_load(ppc)(opc2)\n"); 4939 return False; 4940 } 4941 break; 4942 4943 /* DS Form - 64bit Loads. In each case EA will have been formed 4944 with the lowest 2 bits masked off the immediate offset. */ 4945 case 0x3A: 4946 switch ((b1<<1) | b0) { 4947 case 0x0: // ld (Load DWord, PPC64 p472) 4948 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4949 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4950 break; 4951 4952 case 0x1: // ldu (Load DWord, Update, PPC64 p474) 4953 if (rA_addr == 0 || rA_addr == rD_addr) { 4954 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n"); 4955 return False; 4956 } 4957 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4958 putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) ); 4959 putIReg( rA_addr, mkexpr(EA) ); 4960 break; 4961 4962 case 0x2: // lwa (Load Word Alg, PPC64 p499) 4963 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4964 putIReg( rD_addr, 4965 unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) ); 4966 break; 4967 4968 default: 4969 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 4970 return False; 4971 } 4972 break; 4973 4974 case 0x38: { 4975 IRTemp high = newTemp(ty); 4976 IRTemp low = newTemp(ty); 4977 /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */ 4978 DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 4979 /* NOTE: there are some changes to XER[41:42] that have not been 4980 * implemented. 4981 */ 4982 // trap if EA misaligned on 16 byte address 4983 if (mode64) { 4984 assign(high, loadBE(ty, mkexpr( EA ) ) ); 4985 assign(low, loadBE(ty, binop( Iop_Add64, 4986 mkexpr( EA ), 4987 mkU64( 8 ) ) ) ); 4988 } else { 4989 assign(high, loadBE(ty, binop( Iop_Add32, 4990 mkexpr( EA ), 4991 mkU32( 4 ) ) ) ); 4992 assign(low, loadBE(ty, binop( Iop_Add32, 4993 mkexpr( EA ), 4994 mkU32( 12 ) ) ) ); 4995 } 4996 gen_SIGBUS_if_misaligned( EA, 16 ); 4997 putIReg( rD_addr, mkexpr( high) ); 4998 putIReg( rD_addr+1, mkexpr( low) ); 4999 break; 5000 } 5001 default: 5002 vex_printf("dis_int_load(ppc)(opc1)\n"); 5003 return False; 5004 } 5005 return True; 5006 } 5007 5008 5009 5010 /* 5011 Integer Store Instructions 5012 */ 5013 static Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi ) 5014 { 5015 /* D-Form, X-Form, DS-Form */ 5016 UChar opc1 = ifieldOPC(theInstr); 5017 UInt rS_addr = ifieldRegDS(theInstr); 5018 UInt rA_addr = ifieldRegA(theInstr); 5019 UInt uimm16 = ifieldUIMM16(theInstr); 5020 UInt rB_addr = ifieldRegB(theInstr); 5021 UInt opc2 = ifieldOPClo10(theInstr); 5022 UChar b1 = ifieldBIT1(theInstr); 5023 UChar b0 = ifieldBIT0(theInstr); 5024 5025 Int simm16 = extend_s_16to32(uimm16); 5026 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5027 IRTemp rS = newTemp(ty); 5028 IRTemp rB = newTemp(ty); 5029 IRTemp EA = newTemp(ty); 5030 5031 assign( rB, getIReg(rB_addr) ); 5032 assign( rS, getIReg(rS_addr) ); 5033 5034 switch (opc1) { 5035 case 0x1F: // register offset 5036 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 5037 break; 5038 case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off 5039 // lowest 2 bits of immediate before forming EA 5040 simm16 = simm16 & 0xFFFFFFFC; 5041 default: // immediate offset 5042 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5043 break; 5044 } 5045 5046 switch (opc1) { 5047 case 0x26: // stb (Store B, PPC32 p509) 5048 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5049 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5050 break; 5051 5052 case 0x27: // stbu (Store B, Update, PPC32 p510) 5053 if (rA_addr == 0 ) { 5054 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n"); 5055 return False; 5056 } 5057 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5058 putIReg( rA_addr, mkexpr(EA) ); 5059 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5060 break; 5061 5062 case 0x2C: // sth (Store HW, PPC32 p522) 5063 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5064 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5065 break; 5066 5067 case 0x2D: // sthu (Store HW, Update, PPC32 p524) 5068 if (rA_addr == 0) { 5069 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n"); 5070 return False; 5071 } 5072 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5073 putIReg( rA_addr, mkexpr(EA) ); 5074 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5075 break; 5076 5077 case 0x24: // stw (Store W, PPC32 p530) 5078 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5079 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5080 break; 5081 5082 case 0x25: // stwu (Store W, Update, PPC32 p534) 5083 if (rA_addr == 0) { 5084 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n"); 5085 return False; 5086 } 5087 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5088 putIReg( rA_addr, mkexpr(EA) ); 5089 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5090 break; 5091 5092 /* X Form : all these use EA_indexed */ 5093 case 0x1F: 5094 if (b0 != 0) { 5095 vex_printf("dis_int_store(ppc)(0x1F,b0)\n"); 5096 return False; 5097 } 5098 5099 switch (opc2) { 5100 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511) 5101 if (rA_addr == 0) { 5102 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n"); 5103 return False; 5104 } 5105 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5106 putIReg( rA_addr, mkexpr(EA) ); 5107 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5108 break; 5109 5110 case 0x0D7: // stbx (Store B Indexed, PPC32 p512) 5111 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5112 storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) ); 5113 break; 5114 5115 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525) 5116 if (rA_addr == 0) { 5117 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n"); 5118 return False; 5119 } 5120 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5121 putIReg( rA_addr, mkexpr(EA) ); 5122 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5123 break; 5124 5125 case 0x197: // sthx (Store HW Indexed, PPC32 p526) 5126 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5127 storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) ); 5128 break; 5129 5130 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535) 5131 if (rA_addr == 0) { 5132 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n"); 5133 return False; 5134 } 5135 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5136 putIReg( rA_addr, mkexpr(EA) ); 5137 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5138 break; 5139 5140 case 0x097: // stwx (Store W Indexed, PPC32 p536) 5141 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5142 storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) ); 5143 break; 5144 5145 5146 /* 64bit Stores */ 5147 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584) 5148 if (rA_addr == 0) { 5149 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n"); 5150 return False; 5151 } 5152 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5153 putIReg( rA_addr, mkexpr(EA) ); 5154 storeBE( mkexpr(EA), mkexpr(rS) ); 5155 break; 5156 5157 case 0x095: // stdx (Store DWord Indexed, PPC64 p585) 5158 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5159 storeBE( mkexpr(EA), mkexpr(rS) ); 5160 break; 5161 5162 default: 5163 vex_printf("dis_int_store(ppc)(opc2)\n"); 5164 return False; 5165 } 5166 break; 5167 5168 /* DS Form - 64bit Stores. In each case EA will have been formed 5169 with the lowest 2 bits masked off the immediate offset. */ 5170 case 0x3E: 5171 switch ((b1<<1) | b0) { 5172 case 0x0: // std (Store DWord, PPC64 p580) 5173 if (!mode64) 5174 return False; 5175 5176 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5177 storeBE( mkexpr(EA), mkexpr(rS) ); 5178 break; 5179 5180 case 0x1: // stdu (Store DWord, Update, PPC64 p583) 5181 if (!mode64) 5182 return False; 5183 5184 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5185 putIReg( rA_addr, mkexpr(EA) ); 5186 storeBE( mkexpr(EA), mkexpr(rS) ); 5187 break; 5188 5189 case 0x2: { // stq (Store QuadWord, Update, PPC64 p583) 5190 IRTemp EA_hi = newTemp(ty); 5191 IRTemp EA_lo = newTemp(ty); 5192 DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5193 5194 if (mode64) { 5195 /* upper 64-bits */ 5196 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 5197 5198 /* lower 64-bits */ 5199 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) ); 5200 } else { 5201 /* upper half of upper 64-bits */ 5202 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) ); 5203 5204 /* lower half of upper 64-bits */ 5205 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) ); 5206 } 5207 putIReg( rA_addr, mkexpr(EA_hi) ); 5208 storeBE( mkexpr(EA_hi), mkexpr(rS) ); 5209 putIReg( rA_addr, mkexpr( EA_lo) ); 5210 storeBE( mkexpr(EA_lo), getIReg( rS_addr+1 ) ); 5211 break; 5212 } 5213 default: 5214 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n"); 5215 return False; 5216 } 5217 break; 5218 5219 default: 5220 vex_printf("dis_int_store(ppc)(opc1)\n"); 5221 return False; 5222 } 5223 return True; 5224 } 5225 5226 5227 5228 /* 5229 Integer Load/Store Multiple Instructions 5230 */ 5231 static Bool dis_int_ldst_mult ( UInt theInstr ) 5232 { 5233 /* D-Form */ 5234 UChar opc1 = ifieldOPC(theInstr); 5235 UChar rD_addr = ifieldRegDS(theInstr); 5236 UChar rS_addr = rD_addr; 5237 UChar rA_addr = ifieldRegA(theInstr); 5238 UInt uimm16 = ifieldUIMM16(theInstr); 5239 5240 Int simm16 = extend_s_16to32(uimm16); 5241 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5242 IROp mkAdd = mode64 ? Iop_Add64 : Iop_Add32; 5243 IRTemp EA = newTemp(ty); 5244 UInt r = 0; 5245 UInt ea_off = 0; 5246 IRExpr* irx_addr; 5247 5248 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) ); 5249 5250 switch (opc1) { 5251 case 0x2E: // lmw (Load Multiple Word, PPC32 p454) 5252 if (rA_addr >= rD_addr) { 5253 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n"); 5254 return False; 5255 } 5256 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr); 5257 for (r = rD_addr; r <= 31; r++) { 5258 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 5259 putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ), 5260 False) ); 5261 ea_off += 4; 5262 } 5263 break; 5264 5265 case 0x2F: // stmw (Store Multiple Word, PPC32 p527) 5266 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr); 5267 for (r = rS_addr; r <= 31; r++) { 5268 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off)); 5269 storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) ); 5270 ea_off += 4; 5271 } 5272 break; 5273 5274 default: 5275 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n"); 5276 return False; 5277 } 5278 return True; 5279 } 5280 5281 5282 5283 /* 5284 Integer Load/Store String Instructions 5285 */ 5286 static 5287 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5288 IRTemp EA, // EA 5289 Int rD, // first dst register 5290 Int maxBytes ) // 32 or 128 5291 { 5292 Int i, shift = 24; 5293 IRExpr* e_nbytes = mkexpr(tNBytes); 5294 IRExpr* e_EA = mkexpr(EA); 5295 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5296 5297 vassert(rD >= 0 && rD < 32); 5298 rD--; if (rD < 0) rD = 31; 5299 5300 for (i = 0; i < maxBytes; i++) { 5301 /* if (nBytes < (i+1)) goto NIA; */ 5302 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5303 Ijk_Boring, 5304 mkSzConst( ty, nextInsnAddr()), OFFB_CIA )); 5305 /* when crossing into a new dest register, set it to zero. */ 5306 if ((i % 4) == 0) { 5307 rD++; if (rD == 32) rD = 0; 5308 putIReg(rD, mkSzImm(ty, 0)); 5309 shift = 24; 5310 } 5311 /* rD |= (8Uto32(*(EA+i))) << shift */ 5312 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5313 putIReg( 5314 rD, 5315 mkWidenFrom32( 5316 ty, 5317 binop( 5318 Iop_Or32, 5319 mkNarrowTo32(ty, getIReg(rD)), 5320 binop( 5321 Iop_Shl32, 5322 unop( 5323 Iop_8Uto32, 5324 loadBE(Ity_I8, 5325 binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i))) 5326 ), 5327 mkU8(toUChar(shift)) 5328 ) 5329 ), 5330 /*Signed*/False 5331 ) 5332 ); 5333 shift -= 8; 5334 } 5335 } 5336 5337 static 5338 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32 5339 IRTemp EA, // EA 5340 Int rS, // first src register 5341 Int maxBytes ) // 32 or 128 5342 { 5343 Int i, shift = 24; 5344 IRExpr* e_nbytes = mkexpr(tNBytes); 5345 IRExpr* e_EA = mkexpr(EA); 5346 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5347 5348 vassert(rS >= 0 && rS < 32); 5349 rS--; if (rS < 0) rS = 31; 5350 5351 for (i = 0; i < maxBytes; i++) { 5352 /* if (nBytes < (i+1)) goto NIA; */ 5353 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)), 5354 Ijk_Boring, 5355 mkSzConst( ty, nextInsnAddr() ), OFFB_CIA )); 5356 /* check for crossing into a new src register. */ 5357 if ((i % 4) == 0) { 5358 rS++; if (rS == 32) rS = 0; 5359 shift = 24; 5360 } 5361 /* *(EA+i) = 32to8(rS >> shift) */ 5362 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24); 5363 storeBE( 5364 binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)), 5365 unop(Iop_32to8, 5366 binop(Iop_Shr32, 5367 mkNarrowTo32(ty, getIReg(rS)), 5368 mkU8(toUChar(shift)))) 5369 ); 5370 shift -= 8; 5371 } 5372 } 5373 5374 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) 5375 { 5376 /* X-Form */ 5377 UChar opc1 = ifieldOPC(theInstr); 5378 UChar rD_addr = ifieldRegDS(theInstr); 5379 UChar rS_addr = rD_addr; 5380 UChar rA_addr = ifieldRegA(theInstr); 5381 UChar rB_addr = ifieldRegB(theInstr); 5382 UChar NumBytes = rB_addr; 5383 UInt opc2 = ifieldOPClo10(theInstr); 5384 UChar b0 = ifieldBIT0(theInstr); 5385 5386 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5387 IRTemp t_EA = newTemp(ty); 5388 IRTemp t_nbytes = IRTemp_INVALID; 5389 5390 *stopHere = False; 5391 5392 if (opc1 != 0x1F || b0 != 0) { 5393 vex_printf("dis_int_ldst_str(ppc)(opc1)\n"); 5394 return False; 5395 } 5396 5397 switch (opc2) { 5398 case 0x255: // lswi (Load String Word Immediate, PPC32 p455) 5399 /* NB: does not reject the case where RA is in the range of 5400 registers to be loaded. It should. */ 5401 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes); 5402 assign( t_EA, ea_rAor0(rA_addr) ); 5403 if (NumBytes == 8 && !mode64) { 5404 /* Special case hack */ 5405 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */ 5406 putIReg( rD_addr, 5407 loadBE(Ity_I32, mkexpr(t_EA)) ); 5408 putIReg( (rD_addr+1) % 32, 5409 loadBE(Ity_I32, 5410 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) ); 5411 } else { 5412 t_nbytes = newTemp(Ity_I32); 5413 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5414 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5415 *stopHere = True; 5416 } 5417 return True; 5418 5419 case 0x215: // lswx (Load String Word Indexed, PPC32 p456) 5420 /* NB: does not reject the case where RA is in the range of 5421 registers to be loaded. It should. Although considering 5422 that that can only be detected at run time, it's not easy to 5423 do so. */ 5424 if (rD_addr == rA_addr || rD_addr == rB_addr) 5425 return False; 5426 if (rD_addr == 0 && rA_addr == 0) 5427 return False; 5428 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 5429 t_nbytes = newTemp(Ity_I32); 5430 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5431 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5432 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 ); 5433 *stopHere = True; 5434 return True; 5435 5436 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528) 5437 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes); 5438 assign( t_EA, ea_rAor0(rA_addr) ); 5439 if (NumBytes == 8 && !mode64) { 5440 /* Special case hack */ 5441 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */ 5442 storeBE( mkexpr(t_EA), 5443 getIReg(rD_addr) ); 5444 storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)), 5445 getIReg((rD_addr+1) % 32) ); 5446 } else { 5447 t_nbytes = newTemp(Ity_I32); 5448 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) ); 5449 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 ); 5450 *stopHere = True; 5451 } 5452 return True; 5453 5454 case 0x295: // stswx (Store String Word Indexed, PPC32 p529) 5455 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 5456 t_nbytes = newTemp(Ity_I32); 5457 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) ); 5458 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); 5459 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 ); 5460 *stopHere = True; 5461 return True; 5462 5463 default: 5464 vex_printf("dis_int_ldst_str(ppc)(opc2)\n"); 5465 return False; 5466 } 5467 return True; 5468 } 5469 5470 5471 /* ------------------------------------------------------------------ 5472 Integer Branch Instructions 5473 ------------------------------------------------------------------ */ 5474 5475 /* 5476 Branch helper function 5477 ok = BO[2] | ((CTR[0] != 0) ^ BO[1]) 5478 Returns an I32 which is 0x00000000 if the ctr condition failed 5479 and 0xFFFFFFFF otherwise. 5480 */ 5481 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO ) 5482 { 5483 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5484 IRTemp ok = newTemp(Ity_I32); 5485 5486 if ((BO >> 2) & 1) { // independent of ctr 5487 assign( ok, mkU32(0xFFFFFFFF) ); 5488 } else { 5489 if ((BO >> 1) & 1) { // ctr == 0 ? 5490 assign( ok, unop( Iop_1Sto32, 5491 binop( mkSzOp(ty, Iop_CmpEQ8), 5492 getGST( PPC_GST_CTR ), 5493 mkSzImm(ty,0))) ); 5494 } else { // ctr != 0 ? 5495 assign( ok, unop( Iop_1Sto32, 5496 binop( mkSzOp(ty, Iop_CmpNE8), 5497 getGST( PPC_GST_CTR ), 5498 mkSzImm(ty,0))) ); 5499 } 5500 } 5501 return mkexpr(ok); 5502 } 5503 5504 5505 /* 5506 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3]) 5507 Returns an I32 which is either 0 if the condition failed or 5508 some arbitrary nonzero value otherwise. */ 5509 5510 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) 5511 { 5512 Int where; 5513 IRTemp res = newTemp(Ity_I32); 5514 IRTemp cr_bi = newTemp(Ity_I32); 5515 5516 if ((BO >> 4) & 1) { 5517 assign( res, mkU32(1) ); 5518 } else { 5519 // ok = (CR[BI] == BO[3]) Note, the following relies on 5520 // getCRbit_anywhere returning a value which 5521 // is either zero or has exactly 1 bit set. 5522 assign( cr_bi, getCRbit_anywhere( BI, &where ) ); 5523 5524 if ((BO >> 3) & 1) { 5525 /* We can use cr_bi as-is. */ 5526 assign( res, mkexpr(cr_bi) ); 5527 } else { 5528 /* We have to invert the sense of the information held in 5529 cr_bi. For that we need to know which bit 5530 getCRbit_anywhere regards as significant. */ 5531 assign( res, binop(Iop_Xor32, mkexpr(cr_bi), 5532 mkU32(1<<where)) ); 5533 } 5534 } 5535 return mkexpr(res); 5536 } 5537 5538 5539 /* 5540 Integer Branch Instructions 5541 */ 5542 static Bool dis_branch ( UInt theInstr, 5543 VexAbiInfo* vbi, 5544 /*OUT*/DisResult* dres, 5545 Bool (*resteerOkFn)(void*,Addr64), 5546 void* callback_opaque ) 5547 { 5548 UChar opc1 = ifieldOPC(theInstr); 5549 UChar BO = ifieldRegDS(theInstr); 5550 UChar BI = ifieldRegA(theInstr); 5551 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */ 5552 UChar b11to15 = ifieldRegB(theInstr); 5553 UInt opc2 = ifieldOPClo10(theInstr); 5554 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */ 5555 UChar flag_AA = ifieldBIT1(theInstr); 5556 UChar flag_LK = ifieldBIT0(theInstr); 5557 5558 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5559 Addr64 tgt = 0; 5560 Int BD = extend_s_16to32(BD_u16); 5561 IRTemp do_branch = newTemp(Ity_I32); 5562 IRTemp ctr_ok = newTemp(Ity_I32); 5563 IRTemp cond_ok = newTemp(Ity_I32); 5564 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr()); 5565 IRConst* c_nia = mkSzConst(ty, nextInsnAddr()); 5566 IRTemp lr_old = newTemp(ty); 5567 5568 /* Hack to pass through code that just wants to read the PC */ 5569 if (theInstr == 0x429F0005) { 5570 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI); 5571 putGST( PPC_GST_LR, e_nia ); 5572 return True; 5573 } 5574 5575 /* The default what-next. Individual cases can override it. */ 5576 dres->whatNext = Dis_StopHere; 5577 vassert(dres->jk_StopHere == Ijk_INVALID); 5578 5579 switch (opc1) { 5580 case 0x12: // b (Branch, PPC32 p360) 5581 if (flag_AA) { 5582 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) ); 5583 } else { 5584 tgt = mkSzAddr( ty, guest_CIA_curr_instr + 5585 (Long)extend_s_26to64(LI_u26) ); 5586 } 5587 if (mode64) { 5588 DIP("b%s%s 0x%llx\n", 5589 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt); 5590 } else { 5591 DIP("b%s%s 0x%x\n", 5592 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt); 5593 } 5594 5595 if (flag_LK) { 5596 putGST( PPC_GST_LR, e_nia ); 5597 if (vbi->guest_ppc_zap_RZ_at_bl 5598 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) { 5599 IRTemp t_tgt = newTemp(ty); 5600 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) ); 5601 make_redzone_AbiHint( vbi, t_tgt, 5602 "branch-and-link (unconditional call)" ); 5603 } 5604 } 5605 5606 if (resteerOkFn( callback_opaque, tgt )) { 5607 dres->whatNext = Dis_ResteerU; 5608 dres->continueAt = tgt; 5609 } else { 5610 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ; 5611 putGST( PPC_GST_CIA, mkSzImm(ty, tgt) ); 5612 } 5613 break; 5614 5615 case 0x10: // bc (Branch Conditional, PPC32 p361) 5616 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", 5617 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); 5618 5619 if (!(BO & 0x4)) { 5620 putGST( PPC_GST_CTR, 5621 binop(mkSzOp(ty, Iop_Sub8), 5622 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5623 } 5624 5625 /* This is a bit subtle. ctr_ok is either all 0s or all 1s. 5626 cond_ok is either zero or nonzero, since that's the cheapest 5627 way to compute it. Anding them together gives a value which 5628 is either zero or non zero and so that's what we must test 5629 for in the IRStmt_Exit. */ 5630 assign( ctr_ok, branch_ctr_ok( BO ) ); 5631 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5632 assign( do_branch, 5633 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5634 5635 if (flag_AA) { 5636 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16)); 5637 } else { 5638 tgt = mkSzAddr(ty, guest_CIA_curr_instr + 5639 (Long)extend_s_16to64(BD_u16)); 5640 } 5641 if (flag_LK) 5642 putGST( PPC_GST_LR, e_nia ); 5643 5644 stmt( IRStmt_Exit( 5645 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)), 5646 flag_LK ? Ijk_Call : Ijk_Boring, 5647 mkSzConst(ty, tgt), OFFB_CIA ) ); 5648 5649 dres->jk_StopHere = Ijk_Boring; 5650 putGST( PPC_GST_CIA, e_nia ); 5651 break; 5652 5653 case 0x13: 5654 /* For bclr and bcctr, it appears that the lowest two bits of 5655 b11to15 are a branch hint, and so we only need to ensure it's 5656 of the form 000XX. */ 5657 if ((b11to15 & ~3) != 0) { 5658 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15); 5659 return False; 5660 } 5661 5662 switch (opc2) { 5663 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363) 5664 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid 5665 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n"); 5666 return False; 5667 } 5668 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5669 5670 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5671 5672 /* FIXME: this is confusing. lr_old holds the old value 5673 of ctr, not lr :-) */ 5674 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 )); 5675 5676 if (flag_LK) 5677 putGST( PPC_GST_LR, e_nia ); 5678 5679 stmt( IRStmt_Exit( 5680 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)), 5681 Ijk_Boring, 5682 c_nia, OFFB_CIA )); 5683 5684 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) { 5685 make_redzone_AbiHint( vbi, lr_old, 5686 "b-ctr-l (indirect call)" ); 5687 } 5688 5689 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;; 5690 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 5691 break; 5692 5693 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365) 5694 Bool vanilla_return = False; 5695 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) { 5696 DIP("blr\n"); 5697 vanilla_return = True; 5698 } else { 5699 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI); 5700 } 5701 5702 if (!(BO & 0x4)) { 5703 putGST( PPC_GST_CTR, 5704 binop(mkSzOp(ty, Iop_Sub8), 5705 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) ); 5706 } 5707 5708 /* See comments above for 'bc' about this */ 5709 assign( ctr_ok, branch_ctr_ok( BO ) ); 5710 assign( cond_ok, branch_cond_ok( BO, BI ) ); 5711 assign( do_branch, 5712 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) ); 5713 5714 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 )); 5715 5716 if (flag_LK) 5717 putGST( PPC_GST_LR, e_nia ); 5718 5719 stmt( IRStmt_Exit( 5720 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)), 5721 Ijk_Boring, 5722 c_nia, OFFB_CIA )); 5723 5724 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) { 5725 make_redzone_AbiHint( vbi, lr_old, 5726 "branch-to-lr (unconditional return)" ); 5727 } 5728 5729 /* blrl is pretty strange; it's like a return that sets the 5730 return address of its caller to the insn following this 5731 one. Mark it as a return. */ 5732 dres->jk_StopHere = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */ 5733 putGST( PPC_GST_CIA, mkexpr(lr_old) ); 5734 break; 5735 } 5736 default: 5737 vex_printf("dis_int_branch(ppc)(opc2)\n"); 5738 return False; 5739 } 5740 break; 5741 5742 default: 5743 vex_printf("dis_int_branch(ppc)(opc1)\n"); 5744 return False; 5745 } 5746 5747 return True; 5748 } 5749 5750 5751 5752 /* 5753 Condition Register Logical Instructions 5754 */ 5755 static Bool dis_cond_logic ( UInt theInstr ) 5756 { 5757 /* XL-Form */ 5758 UChar opc1 = ifieldOPC(theInstr); 5759 UChar crbD_addr = ifieldRegDS(theInstr); 5760 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) ); 5761 UChar crbA_addr = ifieldRegA(theInstr); 5762 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) ); 5763 UChar crbB_addr = ifieldRegB(theInstr); 5764 UInt opc2 = ifieldOPClo10(theInstr); 5765 UChar b0 = ifieldBIT0(theInstr); 5766 5767 IRTemp crbD = newTemp(Ity_I32); 5768 IRTemp crbA = newTemp(Ity_I32); 5769 IRTemp crbB = newTemp(Ity_I32); 5770 5771 if (opc1 != 19 || b0 != 0) { 5772 vex_printf("dis_cond_logic(ppc)(opc1)\n"); 5773 return False; 5774 } 5775 5776 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464) 5777 if (((crbD_addr & 0x3) != 0) || 5778 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) { 5779 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n"); 5780 return False; 5781 } 5782 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr); 5783 putCR0( crfD_addr, getCR0( crfS_addr) ); 5784 putCR321( crfD_addr, getCR321(crfS_addr) ); 5785 } else { 5786 assign( crbA, getCRbit(crbA_addr) ); 5787 if (crbA_addr == crbB_addr) 5788 crbB = crbA; 5789 else 5790 assign( crbB, getCRbit(crbB_addr) ); 5791 5792 switch (opc2) { 5793 case 0x101: // crand (Cond Reg AND, PPC32 p372) 5794 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5795 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) ); 5796 break; 5797 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373) 5798 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5799 assign( crbD, binop(Iop_And32, 5800 mkexpr(crbA), 5801 unop(Iop_Not32, mkexpr(crbB))) ); 5802 break; 5803 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374) 5804 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5805 assign( crbD, unop(Iop_Not32, 5806 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) ); 5807 break; 5808 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375) 5809 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5810 assign( crbD, unop(Iop_Not32, 5811 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) ); 5812 break; 5813 case 0x021: // crnor (Cond Reg NOR, PPC32 p376) 5814 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5815 assign( crbD, unop(Iop_Not32, 5816 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) ); 5817 break; 5818 case 0x1C1: // cror (Cond Reg OR, PPC32 p377) 5819 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5820 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) ); 5821 break; 5822 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378) 5823 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5824 assign( crbD, binop(Iop_Or32, 5825 mkexpr(crbA), 5826 unop(Iop_Not32, mkexpr(crbB))) ); 5827 break; 5828 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379) 5829 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr); 5830 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) ); 5831 break; 5832 default: 5833 vex_printf("dis_cond_logic(ppc)(opc2)\n"); 5834 return False; 5835 } 5836 5837 putCRbit( crbD_addr, mkexpr(crbD) ); 5838 } 5839 return True; 5840 } 5841 5842 5843 /* 5844 Trap instructions 5845 */ 5846 5847 /* Do the code generation for a trap. Returned Bool is true iff 5848 this is an unconditional trap. If the two arg IRExpr*s are 5849 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s 5850 then they are 64-bit, and we must be disassembling 64-bit 5851 instructions. */ 5852 static Bool do_trap ( UChar TO, 5853 IRExpr* argL0, IRExpr* argR0, Addr64 cia ) 5854 { 5855 IRTemp argL, argR; 5856 IRExpr *argLe, *argRe, *cond, *tmp; 5857 5858 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32; 5859 5860 IROp opAND = is32bit ? Iop_And32 : Iop_And64; 5861 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64; 5862 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S; 5863 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U; 5864 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64; 5865 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64; 5866 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0); 5867 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2); 5868 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4); 5869 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8); 5870 5871 const UChar b11100 = 0x1C; 5872 const UChar b00111 = 0x07; 5873 5874 if (is32bit) { 5875 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 ); 5876 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 ); 5877 } else { 5878 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 ); 5879 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 ); 5880 vassert( mode64 ); 5881 } 5882 5883 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) { 5884 /* Unconditional trap. Just do the exit without 5885 testing the arguments. */ 5886 stmt( IRStmt_Exit( 5887 binop(opCMPEQ, const0, const0), 5888 Ijk_SigTRAP, 5889 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 5890 OFFB_CIA 5891 )); 5892 return True; /* unconditional trap */ 5893 } 5894 5895 if (is32bit) { 5896 argL = newTemp(Ity_I32); 5897 argR = newTemp(Ity_I32); 5898 } else { 5899 argL = newTemp(Ity_I64); 5900 argR = newTemp(Ity_I64); 5901 } 5902 5903 assign( argL, argL0 ); 5904 assign( argR, argR0 ); 5905 5906 argLe = mkexpr(argL); 5907 argRe = mkexpr(argR); 5908 5909 cond = const0; 5910 if (TO & 16) { // L <s R 5911 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8); 5912 cond = binop(opOR, tmp, cond); 5913 } 5914 if (TO & 8) { // L >s R 5915 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4); 5916 cond = binop(opOR, tmp, cond); 5917 } 5918 if (TO & 4) { // L == R 5919 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2); 5920 cond = binop(opOR, tmp, cond); 5921 } 5922 if (TO & 2) { // L <u R 5923 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8); 5924 cond = binop(opOR, tmp, cond); 5925 } 5926 if (TO & 1) { // L >u R 5927 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4); 5928 cond = binop(opOR, tmp, cond); 5929 } 5930 stmt( IRStmt_Exit( 5931 binop(opCMPNE, cond, const0), 5932 Ijk_SigTRAP, 5933 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia), 5934 OFFB_CIA 5935 )); 5936 return False; /* not an unconditional trap */ 5937 } 5938 5939 static Bool dis_trapi ( UInt theInstr, 5940 /*OUT*/DisResult* dres ) 5941 { 5942 /* D-Form */ 5943 UChar opc1 = ifieldOPC(theInstr); 5944 UChar TO = ifieldRegDS(theInstr); 5945 UChar rA_addr = ifieldRegA(theInstr); 5946 UInt uimm16 = ifieldUIMM16(theInstr); 5947 ULong simm16 = extend_s_16to64(uimm16); 5948 Addr64 cia = guest_CIA_curr_instr; 5949 IRType ty = mode64 ? Ity_I64 : Ity_I32; 5950 Bool uncond = False; 5951 5952 switch (opc1) { 5953 case 0x03: // twi (Trap Word Immediate, PPC32 p548) 5954 uncond = do_trap( TO, 5955 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 5956 : getIReg(rA_addr), 5957 mkU32( (UInt)simm16 ), 5958 cia ); 5959 if (TO == 4) { 5960 DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 5961 } else { 5962 DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 5963 } 5964 break; 5965 case 0x02: // tdi 5966 if (!mode64) 5967 return False; 5968 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia ); 5969 if (TO == 4) { 5970 DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); 5971 } else { 5972 DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); 5973 } 5974 break; 5975 default: 5976 return False; 5977 } 5978 5979 if (uncond) { 5980 /* If the trap shows signs of being unconditional, don't 5981 continue decoding past it. */ 5982 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 5983 dres->jk_StopHere = Ijk_Boring; 5984 dres->whatNext = Dis_StopHere; 5985 } 5986 5987 return True; 5988 } 5989 5990 static Bool dis_trap ( UInt theInstr, 5991 /*OUT*/DisResult* dres ) 5992 { 5993 /* X-Form */ 5994 UInt opc2 = ifieldOPClo10(theInstr); 5995 UChar TO = ifieldRegDS(theInstr); 5996 UChar rA_addr = ifieldRegA(theInstr); 5997 UChar rB_addr = ifieldRegB(theInstr); 5998 Addr64 cia = guest_CIA_curr_instr; 5999 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6000 Bool uncond = False; 6001 6002 if (ifieldBIT0(theInstr) != 0) 6003 return False; 6004 6005 switch (opc2) { 6006 case 0x004: // tw (Trap Word, PPC64 p540) 6007 uncond = do_trap( TO, 6008 mode64 ? unop(Iop_64to32, getIReg(rA_addr)) 6009 : getIReg(rA_addr), 6010 mode64 ? unop(Iop_64to32, getIReg(rB_addr)) 6011 : getIReg(rB_addr), 6012 cia ); 6013 if (TO == 4) { 6014 DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 6015 } else { 6016 DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 6017 } 6018 break; 6019 case 0x044: // td (Trap Doubleword, PPC64 p534) 6020 if (!mode64) 6021 return False; 6022 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia ); 6023 if (TO == 4) { 6024 DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr); 6025 } else { 6026 DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr); 6027 } 6028 break; 6029 default: 6030 return False; 6031 } 6032 6033 if (uncond) { 6034 /* If the trap shows signs of being unconditional, don't 6035 continue decoding past it. */ 6036 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() )); 6037 dres->jk_StopHere = Ijk_Boring; 6038 dres->whatNext = Dis_StopHere; 6039 } 6040 6041 return True; 6042 } 6043 6044 6045 /* 6046 System Linkage Instructions 6047 */ 6048 static Bool dis_syslink ( UInt theInstr, 6049 VexAbiInfo* abiinfo, DisResult* dres ) 6050 { 6051 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6052 6053 if (theInstr != 0x44000002) { 6054 vex_printf("dis_syslink(ppc)(theInstr)\n"); 6055 return False; 6056 } 6057 6058 // sc (System Call, PPC32 p504) 6059 DIP("sc\n"); 6060 6061 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX 6062 Valgrind can back the guest up to this instruction if it needs 6063 to restart the syscall. */ 6064 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) ); 6065 6066 /* It's important that all ArchRegs carry their up-to-date value 6067 at this point. So we declare an end-of-block here, which 6068 forces any TempRegs caching ArchRegs to be flushed. */ 6069 putGST( PPC_GST_CIA, abiinfo->guest_ppc_sc_continues_at_LR 6070 ? getGST( PPC_GST_LR ) 6071 : mkSzImm( ty, nextInsnAddr() )); 6072 6073 dres->whatNext = Dis_StopHere; 6074 dres->jk_StopHere = Ijk_Sys_syscall; 6075 return True; 6076 } 6077 6078 6079 /* 6080 Memory Synchronization Instructions 6081 6082 Note on Reservations: 6083 We rely on the assumption that V will in fact only allow one thread at 6084 once to run. In effect, a thread can make a reservation, but we don't 6085 check any stores it does. Instead, the reservation is cancelled when 6086 the scheduler switches to another thread (run_thread_for_a_while()). 6087 */ 6088 static Bool dis_memsync ( UInt theInstr ) 6089 { 6090 /* X-Form, XL-Form */ 6091 UChar opc1 = ifieldOPC(theInstr); 6092 UInt b11to25 = IFIELD(theInstr, 11, 15); 6093 UChar flag_L = ifieldRegDS(theInstr); 6094 UInt b11to20 = IFIELD(theInstr, 11, 10); 6095 UChar rD_addr = ifieldRegDS(theInstr); 6096 UChar rS_addr = rD_addr; 6097 UChar rA_addr = ifieldRegA(theInstr); 6098 UChar rB_addr = ifieldRegB(theInstr); 6099 UInt opc2 = ifieldOPClo10(theInstr); 6100 UChar b0 = ifieldBIT0(theInstr); 6101 6102 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6103 IRTemp EA = newTemp(ty); 6104 6105 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6106 6107 switch (opc1) { 6108 /* XL-Form */ 6109 case 0x13: // isync (Instruction Synchronize, PPC32 p432) 6110 if (opc2 != 0x096) { 6111 vex_printf("dis_memsync(ppc)(0x13,opc2)\n"); 6112 return False; 6113 } 6114 if (b11to25 != 0 || b0 != 0) { 6115 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n"); 6116 return False; 6117 } 6118 DIP("isync\n"); 6119 stmt( IRStmt_MBE(Imbe_Fence) ); 6120 break; 6121 6122 /* X-Form */ 6123 case 0x1F: 6124 switch (opc2) { 6125 case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394) 6126 if (b11to25 != 0 || b0 != 0) { 6127 vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n"); 6128 return False; 6129 } 6130 DIP("eieio\n"); 6131 /* Insert a memory fence, just to be on the safe side. */ 6132 stmt( IRStmt_MBE(Imbe_Fence) ); 6133 break; 6134 6135 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458) 6136 IRTemp res; 6137 /* According to the PowerPC ISA version 2.05, b0 (called EH 6138 in the documentation) is merely a hint bit to the 6139 hardware, I think as to whether or not contention is 6140 likely. So we can just ignore it. */ 6141 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6142 6143 // trap if misaligned 6144 gen_SIGBUS_if_misaligned( EA, 4 ); 6145 6146 // and actually do the load 6147 res = newTemp(Ity_I32); 6148 stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) ); 6149 6150 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) ); 6151 break; 6152 } 6153 6154 case 0x096: { 6155 // stwcx. (Store Word Conditional Indexed, PPC32 p532) 6156 // Note this has to handle stwcx. in both 32- and 64-bit modes, 6157 // so isn't quite as straightforward as it might otherwise be. 6158 IRTemp rS = newTemp(Ity_I32); 6159 IRTemp resSC; 6160 if (b0 != 1) { 6161 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n"); 6162 return False; 6163 } 6164 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6165 6166 // trap if misaligned 6167 gen_SIGBUS_if_misaligned( EA, 4 ); 6168 6169 // Get the data to be stored, and narrow to 32 bits if necessary 6170 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6171 6172 // Do the store, and get success/failure bit into resSC 6173 resSC = newTemp(Ity_I1); 6174 stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) ); 6175 6176 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6177 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6178 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6179 putCR0(0, getXER_SO()); 6180 6181 /* Note: 6182 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 6183 whether rS is stored is dependent on that value. */ 6184 /* So I guess we can just ignore this case? */ 6185 break; 6186 } 6187 6188 case 0x256: // sync (Synchronize, PPC32 p543), 6189 // also lwsync (L==1), ptesync (L==2) 6190 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html 6191 6192 The PowerPC architecture used in IBM chips has expanded 6193 the sync instruction into two variants: lightweight sync 6194 and heavyweight sync. The original sync instruction is 6195 the new heavyweight sync and lightweight sync is a strict 6196 subset of the heavyweight sync functionality. This allows 6197 the programmer to specify a less expensive operation on 6198 high-end systems when the full sync functionality is not 6199 necessary. 6200 6201 The basic "sync" mnemonic now utilizes an operand. "sync" 6202 without an operand now becomes a extended mnemonic for 6203 heavyweight sync. Processors without the lwsync 6204 instruction will not decode the L field and will perform a 6205 heavyweight sync. Everything is backward compatible. 6206 6207 sync = sync 0 6208 lwsync = sync 1 6209 ptesync = sync 2 *** TODO - not implemented *** 6210 */ 6211 if (b11to20 != 0 || b0 != 0) { 6212 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n"); 6213 return False; 6214 } 6215 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) { 6216 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n"); 6217 return False; 6218 } 6219 DIP("%ssync\n", flag_L == 1 ? "lw" : ""); 6220 /* Insert a memory fence. It's sometimes important that these 6221 are carried through to the generated code. */ 6222 stmt( IRStmt_MBE(Imbe_Fence) ); 6223 break; 6224 6225 /* 64bit Memsync */ 6226 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473) 6227 IRTemp res; 6228 /* According to the PowerPC ISA version 2.05, b0 (called EH 6229 in the documentation) is merely a hint bit to the 6230 hardware, I think as to whether or not contention is 6231 likely. So we can just ignore it. */ 6232 if (!mode64) 6233 return False; 6234 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6235 6236 // trap if misaligned 6237 gen_SIGBUS_if_misaligned( EA, 8 ); 6238 6239 // and actually do the load 6240 res = newTemp(Ity_I64); 6241 stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) ); 6242 6243 putIReg( rD_addr, mkexpr(res) ); 6244 break; 6245 } 6246 6247 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581) 6248 // A marginally simplified version of the stwcx. case 6249 IRTemp rS = newTemp(Ity_I64); 6250 IRTemp resSC; 6251 if (b0 != 1) { 6252 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n"); 6253 return False; 6254 } 6255 if (!mode64) 6256 return False; 6257 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6258 6259 // trap if misaligned 6260 gen_SIGBUS_if_misaligned( EA, 8 ); 6261 6262 // Get the data to be stored 6263 assign( rS, getIReg(rS_addr) ); 6264 6265 // Do the store, and get success/failure bit into resSC 6266 resSC = newTemp(Ity_I1); 6267 stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) ); 6268 6269 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6270 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6271 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1))); 6272 putCR0(0, getXER_SO()); 6273 6274 /* Note: 6275 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and 6276 whether rS is stored is dependent on that value. */ 6277 /* So I guess we can just ignore this case? */ 6278 break; 6279 } 6280 6281 /* 128bit Memsync */ 6282 case 0x114: { // lqarx (Load QuadWord and Reserve Indexed) 6283 IRTemp res_hi = newTemp(ty); 6284 IRTemp res_lo = newTemp(ty); 6285 6286 /* According to the PowerPC ISA version 2.07, b0 (called EH 6287 in the documentation) is merely a hint bit to the 6288 hardware, I think as to whether or not contention is 6289 likely. So we can just ignore it. */ 6290 DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0); 6291 6292 // trap if misaligned 6293 gen_SIGBUS_if_misaligned( EA, 16 ); 6294 6295 // and actually do the load 6296 if (mode64) { 6297 stmt( IRStmt_LLSC( Iend_BE, res_hi, 6298 mkexpr(EA), NULL/*this is a load*/) ); 6299 stmt( IRStmt_LLSC( Iend_BE, res_lo, 6300 binop(Iop_Add64, mkexpr(EA), mkU64(8) ), 6301 NULL/*this is a load*/) ); 6302 } else { 6303 stmt( IRStmt_LLSC( Iend_BE, res_hi, 6304 binop( Iop_Add32, mkexpr(EA), mkU32(4) ), 6305 NULL/*this is a load*/) ); 6306 stmt( IRStmt_LLSC( Iend_BE, res_lo, 6307 binop( Iop_Add32, mkexpr(EA), mkU32(12) ), 6308 NULL/*this is a load*/) ); 6309 } 6310 putIReg( rD_addr, mkexpr(res_hi) ); 6311 putIReg( rD_addr+1, mkexpr(res_lo) ); 6312 break; 6313 } 6314 6315 case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64) 6316 // A marginally simplified version of the stwcx. case 6317 IRTemp rS_hi = newTemp(ty); 6318 IRTemp rS_lo = newTemp(ty); 6319 IRTemp resSC; 6320 if (b0 != 1) { 6321 vex_printf("dis_memsync(ppc)(stqcx.,b0)\n"); 6322 return False; 6323 } 6324 6325 DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6326 6327 // trap if misaligned 6328 gen_SIGBUS_if_misaligned( EA, 16 ); 6329 // Get the data to be stored 6330 assign( rS_hi, getIReg(rS_addr) ); 6331 assign( rS_lo, getIReg(rS_addr+1) ); 6332 6333 // Do the store, and get success/failure bit into resSC 6334 resSC = newTemp(Ity_I1); 6335 6336 if (mode64) { 6337 stmt( IRStmt_LLSC( Iend_BE, resSC, mkexpr(EA), mkexpr(rS_hi) ) ); 6338 storeBE(binop( Iop_Add64, mkexpr(EA), mkU64(8) ), mkexpr(rS_lo) ); 6339 } else { 6340 stmt( IRStmt_LLSC( Iend_BE, resSC, binop( Iop_Add32, 6341 mkexpr(EA), 6342 mkU32(4) ), 6343 mkexpr(rS_hi) ) ); 6344 storeBE(binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) ); 6345 } 6346 6347 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure 6348 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success 6349 putCR321(0, binop( Iop_Shl8, 6350 unop(Iop_1Uto8, mkexpr(resSC) ), 6351 mkU8(1))); 6352 putCR0(0, getXER_SO()); 6353 break; 6354 } 6355 6356 default: 6357 vex_printf("dis_memsync(ppc)(opc2)\n"); 6358 return False; 6359 } 6360 break; 6361 6362 default: 6363 vex_printf("dis_memsync(ppc)(opc1)\n"); 6364 return False; 6365 } 6366 return True; 6367 } 6368 6369 6370 6371 /* 6372 Integer Shift Instructions 6373 */ 6374 static Bool dis_int_shift ( UInt theInstr ) 6375 { 6376 /* X-Form, XS-Form */ 6377 UChar opc1 = ifieldOPC(theInstr); 6378 UChar rS_addr = ifieldRegDS(theInstr); 6379 UChar rA_addr = ifieldRegA(theInstr); 6380 UChar rB_addr = ifieldRegB(theInstr); 6381 UChar sh_imm = rB_addr; 6382 UInt opc2 = ifieldOPClo10(theInstr); 6383 UChar b1 = ifieldBIT1(theInstr); 6384 UChar flag_rC = ifieldBIT0(theInstr); 6385 6386 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6387 IRTemp rA = newTemp(ty); 6388 IRTemp rS = newTemp(ty); 6389 IRTemp rB = newTemp(ty); 6390 IRTemp outofrange = newTemp(Ity_I1); 6391 IRTemp rS_lo32 = newTemp(Ity_I32); 6392 IRTemp rB_lo32 = newTemp(Ity_I32); 6393 IRExpr* e_tmp; 6394 6395 assign( rS, getIReg(rS_addr) ); 6396 assign( rB, getIReg(rB_addr) ); 6397 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) ); 6398 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) ); 6399 6400 if (opc1 == 0x1F) { 6401 switch (opc2) { 6402 case 0x018: { // slw (Shift Left Word, PPC32 p505) 6403 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6404 rA_addr, rS_addr, rB_addr); 6405 /* rA = rS << rB */ 6406 /* ppc32 semantics are: 6407 slw(x,y) = (x << (y & 31)) -- primary result 6408 & ~((y << 26) >>s 31) -- make result 0 6409 for y in 32 .. 63 6410 */ 6411 e_tmp = 6412 binop( Iop_And32, 6413 binop( Iop_Shl32, 6414 mkexpr(rS_lo32), 6415 unop( Iop_32to8, 6416 binop(Iop_And32, 6417 mkexpr(rB_lo32), mkU32(31)))), 6418 unop( Iop_Not32, 6419 binop( Iop_Sar32, 6420 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)), 6421 mkU8(31))) ); 6422 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6423 break; 6424 } 6425 6426 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506) 6427 IRTemp sh_amt = newTemp(Ity_I32); 6428 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6429 rA_addr, rS_addr, rB_addr); 6430 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is: 6431 amt = rB & 63 6432 rA = Sar32( rS, amt > 31 ? 31 : amt ) 6433 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi) 6434 */ 6435 assign( sh_amt, binop(Iop_And32, mkU32(0x3F), 6436 mkexpr(rB_lo32)) ); 6437 assign( outofrange, 6438 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) ); 6439 e_tmp = binop( Iop_Sar32, 6440 mkexpr(rS_lo32), 6441 unop( Iop_32to8, 6442 IRExpr_ITE( mkexpr(outofrange), 6443 mkU32(31), 6444 mkexpr(sh_amt)) ) ); 6445 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) ); 6446 6447 set_XER_CA( ty, PPCG_FLAG_OP_SRAW, 6448 mkexpr(rA), 6449 mkWidenFrom32(ty, mkexpr(rS_lo32), True), 6450 mkWidenFrom32(ty, mkexpr(sh_amt), True ), 6451 mkWidenFrom32(ty, getXER_CA32(), True) ); 6452 break; 6453 } 6454 6455 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507) 6456 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"", 6457 rA_addr, rS_addr, sh_imm); 6458 vassert(sh_imm < 32); 6459 if (mode64) { 6460 assign( rA, binop(Iop_Sar64, 6461 binop(Iop_Shl64, getIReg(rS_addr), 6462 mkU8(32)), 6463 mkU8(32 + sh_imm)) ); 6464 } else { 6465 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32), 6466 mkU8(sh_imm)) ); 6467 } 6468 6469 set_XER_CA( ty, PPCG_FLAG_OP_SRAWI, 6470 mkexpr(rA), 6471 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True), 6472 mkSzImm(ty, sh_imm), 6473 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6474 break; 6475 6476 case 0x218: // srw (Shift Right Word, PPC32 p508) 6477 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"", 6478 rA_addr, rS_addr, rB_addr); 6479 /* rA = rS >>u rB */ 6480 /* ppc32 semantics are: 6481 srw(x,y) = (x >>u (y & 31)) -- primary result 6482 & ~((y << 26) >>s 31) -- make result 0 6483 for y in 32 .. 63 6484 */ 6485 e_tmp = 6486 binop( 6487 Iop_And32, 6488 binop( Iop_Shr32, 6489 mkexpr(rS_lo32), 6490 unop( Iop_32to8, 6491 binop(Iop_And32, mkexpr(rB_lo32), 6492 mkU32(31)))), 6493 unop( Iop_Not32, 6494 binop( Iop_Sar32, 6495 binop(Iop_Shl32, mkexpr(rB_lo32), 6496 mkU8(26)), 6497 mkU8(31)))); 6498 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) ); 6499 break; 6500 6501 6502 /* 64bit Shifts */ 6503 case 0x01B: // sld (Shift Left DWord, PPC64 p568) 6504 DIP("sld%s r%u,r%u,r%u\n", 6505 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6506 /* rA = rS << rB */ 6507 /* ppc64 semantics are: 6508 slw(x,y) = (x << (y & 63)) -- primary result 6509 & ~((y << 57) >>s 63) -- make result 0 6510 for y in 64 .. 6511 */ 6512 assign( rA, 6513 binop( 6514 Iop_And64, 6515 binop( Iop_Shl64, 6516 mkexpr(rS), 6517 unop( Iop_64to8, 6518 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6519 unop( Iop_Not64, 6520 binop( Iop_Sar64, 6521 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6522 mkU8(63)))) ); 6523 break; 6524 6525 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570) 6526 IRTemp sh_amt = newTemp(Ity_I64); 6527 DIP("srad%s r%u,r%u,r%u\n", 6528 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6529 /* amt = rB & 127 6530 rA = Sar64( rS, amt > 63 ? 63 : amt ) 6531 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi) 6532 */ 6533 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) ); 6534 assign( outofrange, 6535 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) ); 6536 assign( rA, 6537 binop( Iop_Sar64, 6538 mkexpr(rS), 6539 unop( Iop_64to8, 6540 IRExpr_ITE( mkexpr(outofrange), 6541 mkU64(63), 6542 mkexpr(sh_amt)) )) 6543 ); 6544 set_XER_CA( ty, PPCG_FLAG_OP_SRAD, 6545 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt), 6546 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6547 break; 6548 } 6549 6550 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571) 6551 sh_imm |= b1<<5; 6552 vassert(sh_imm < 64); 6553 DIP("sradi%s r%u,r%u,%u\n", 6554 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm); 6555 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) ); 6556 6557 set_XER_CA( ty, PPCG_FLAG_OP_SRADI, 6558 mkexpr(rA), 6559 getIReg(rS_addr), 6560 mkU64(sh_imm), 6561 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) ); 6562 break; 6563 6564 case 0x21B: // srd (Shift Right DWord, PPC64 p574) 6565 DIP("srd%s r%u,r%u,r%u\n", 6566 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr); 6567 /* rA = rS >>u rB */ 6568 /* ppc semantics are: 6569 srw(x,y) = (x >>u (y & 63)) -- primary result 6570 & ~((y << 57) >>s 63) -- make result 0 6571 for y in 64 .. 127 6572 */ 6573 assign( rA, 6574 binop( 6575 Iop_And64, 6576 binop( Iop_Shr64, 6577 mkexpr(rS), 6578 unop( Iop_64to8, 6579 binop(Iop_And64, mkexpr(rB), mkU64(63)))), 6580 unop( Iop_Not64, 6581 binop( Iop_Sar64, 6582 binop(Iop_Shl64, mkexpr(rB), mkU8(57)), 6583 mkU8(63)))) ); 6584 break; 6585 6586 default: 6587 vex_printf("dis_int_shift(ppc)(opc2)\n"); 6588 return False; 6589 } 6590 } else { 6591 vex_printf("dis_int_shift(ppc)(opc1)\n"); 6592 return False; 6593 } 6594 6595 putIReg( rA_addr, mkexpr(rA) ); 6596 6597 if (flag_rC) { 6598 set_CR0( mkexpr(rA) ); 6599 } 6600 return True; 6601 } 6602 6603 6604 6605 /* 6606 Integer Load/Store Reverse Instructions 6607 */ 6608 /* Generates code to swap the byte order in an Ity_I32. */ 6609 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t ) 6610 { 6611 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 6612 return 6613 binop(Iop_Or32, 6614 binop(Iop_Shl32, mkexpr(t), mkU8(24)), 6615 binop(Iop_Or32, 6616 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 6617 mkU32(0x00FF0000)), 6618 binop(Iop_Or32, 6619 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 6620 mkU32(0x0000FF00)), 6621 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)), 6622 mkU32(0x000000FF) ) 6623 ))); 6624 } 6625 6626 /* Generates code to swap the byte order in the lower half of an Ity_I32, 6627 and zeroes the upper half. */ 6628 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t ) 6629 { 6630 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32); 6631 return 6632 binop(Iop_Or32, 6633 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)), 6634 mkU32(0x0000FF00)), 6635 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)), 6636 mkU32(0x000000FF)) 6637 ); 6638 } 6639 6640 static Bool dis_int_ldst_rev ( UInt theInstr ) 6641 { 6642 /* X-Form */ 6643 UChar opc1 = ifieldOPC(theInstr); 6644 UChar rD_addr = ifieldRegDS(theInstr); 6645 UChar rS_addr = rD_addr; 6646 UChar rA_addr = ifieldRegA(theInstr); 6647 UChar rB_addr = ifieldRegB(theInstr); 6648 UInt opc2 = ifieldOPClo10(theInstr); 6649 UChar b0 = ifieldBIT0(theInstr); 6650 6651 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6652 IRTemp EA = newTemp(ty); 6653 IRTemp w1 = newTemp(Ity_I32); 6654 IRTemp w2 = newTemp(Ity_I32); 6655 6656 if (opc1 != 0x1F || b0 != 0) { 6657 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n"); 6658 return False; 6659 } 6660 6661 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 6662 6663 switch (opc2) { 6664 6665 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449) 6666 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6667 assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) ); 6668 assign( w2, gen_byterev16(w1) ); 6669 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 6670 /* Signed */False) ); 6671 break; 6672 6673 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459) 6674 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6675 assign( w1, loadBE(Ity_I32, mkexpr(EA)) ); 6676 assign( w2, gen_byterev32(w1) ); 6677 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2), 6678 /* Signed */False) ); 6679 break; 6680 6681 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed) 6682 { 6683 IRExpr * nextAddr; 6684 IRTemp w3 = newTemp( Ity_I32 ); 6685 IRTemp w4 = newTemp( Ity_I32 ); 6686 DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr); 6687 assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) ); 6688 assign( w2, gen_byterev32( w1 ) ); 6689 nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 6690 ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) ); 6691 assign( w3, loadBE( Ity_I32, nextAddr ) ); 6692 assign( w4, gen_byterev32( w3 ) ); 6693 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) ); 6694 break; 6695 } 6696 6697 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523) 6698 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6699 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6700 storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) ); 6701 break; 6702 6703 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531) 6704 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6705 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) ); 6706 storeBE( mkexpr(EA), gen_byterev32(w1) ); 6707 break; 6708 6709 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed) 6710 { 6711 IRTemp lo = newTemp(Ity_I32); 6712 IRTemp hi = newTemp(Ity_I32); 6713 IRTemp rS = newTemp(Ity_I64); 6714 assign( rS, getIReg( rS_addr ) ); 6715 DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr); 6716 assign(lo, unop(Iop_64HIto32, mkexpr(rS))); 6717 assign(hi, unop(Iop_64to32, mkexpr(rS))); 6718 storeBE( mkexpr( EA ), 6719 binop( Iop_32HLto64, gen_byterev32( hi ), gen_byterev32( lo ) ) ); 6720 break; 6721 } 6722 6723 default: 6724 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n"); 6725 return False; 6726 } 6727 return True; 6728 } 6729 6730 6731 6732 /* 6733 Processor Control Instructions 6734 */ 6735 static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr ) 6736 { 6737 UChar opc1 = ifieldOPC(theInstr); 6738 6739 /* X-Form */ 6740 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 6741 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 6742 UChar rD_addr = ifieldRegDS(theInstr); 6743 UInt b11to20 = IFIELD( theInstr, 11, 10 ); 6744 6745 /* XFX-Form */ 6746 UChar rS_addr = rD_addr; 6747 UInt SPR = b11to20; 6748 UInt TBR = b11to20; 6749 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) ); 6750 UInt CRM = IFIELD( theInstr, 12, 8 ); 6751 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 6752 6753 UInt opc2 = ifieldOPClo10(theInstr); 6754 UChar b0 = ifieldBIT0(theInstr); 6755 6756 IRType ty = mode64 ? Ity_I64 : Ity_I32; 6757 IRTemp rS = newTemp(ty); 6758 assign( rS, getIReg(rS_addr) ); 6759 6760 /* Reorder SPR field as per PPC32 p470 */ 6761 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); 6762 /* Reorder TBR field as per PPC32 p475 */ 6763 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31); 6764 6765 /* b0 = 0, inst is treated as floating point inst for reservation purposes 6766 * b0 = 1, inst is treated as vector inst for reservation purposes 6767 */ 6768 if (opc1 != 0x1F) { 6769 vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0); 6770 return False; 6771 } 6772 6773 switch (opc2) { 6774 /* X-Form */ 6775 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466) 6776 if (b21to22 != 0 || b11to20 != 0) { 6777 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n"); 6778 return False; 6779 } 6780 DIP("mcrxr crf%d\n", crfD); 6781 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */ 6782 putGST_field( PPC_GST_CR, 6783 getGST_field( PPC_GST_XER, 7 ), 6784 crfD ); 6785 6786 // Clear XER[0-3] 6787 putXER_SO( mkU8(0) ); 6788 putXER_OV( mkU8(0) ); 6789 putXER_CA( mkU8(0) ); 6790 break; 6791 } 6792 6793 case 0x013: 6794 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467) 6795 // b20==1 & b11==0: mfocrf (Move from One CR Field) 6796 // However it seems that the 'mfcr' behaviour is an acceptable 6797 // implementation of mfocr (from the 2.02 arch spec) 6798 if (b11to20 == 0) { 6799 DIP("mfcr r%u\n", rD_addr); 6800 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 6801 /* Signed */False) ); 6802 break; 6803 } 6804 if (b20 == 1 && b11 == 0) { 6805 DIP("mfocrf r%u,%u\n", rD_addr, CRM); 6806 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ), 6807 /* Signed */False) ); 6808 break; 6809 } 6810 /* not decodable */ 6811 return False; 6812 6813 /* XFX-Form */ 6814 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470) 6815 6816 switch (SPR) { // Choose a register... 6817 case 0x1: 6818 DIP("mfxer r%u\n", rD_addr); 6819 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ), 6820 /* Signed */False) ); 6821 break; 6822 case 0x8: 6823 DIP("mflr r%u\n", rD_addr); 6824 putIReg( rD_addr, getGST( PPC_GST_LR ) ); 6825 break; 6826 case 0x9: 6827 DIP("mfctr r%u\n", rD_addr); 6828 putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 6829 break; 6830 case 0x80: // 128 6831 DIP("mfspr r%u (TFHAR)\n", rD_addr); 6832 putIReg( rD_addr, getGST( PPC_GST_TFHAR) ); 6833 break; 6834 case 0x81: // 129 6835 DIP("mfspr r%u (TFIAR)\n", rD_addr); 6836 putIReg( rD_addr, getGST( PPC_GST_TFIAR) ); 6837 break; 6838 case 0x82: // 130 6839 DIP("mfspr r%u (TEXASR)\n", rD_addr); 6840 putIReg( rD_addr, getGST( PPC_GST_TEXASR) ); 6841 break; 6842 case 0x100: 6843 DIP("mfvrsave r%u\n", rD_addr); 6844 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ), 6845 /* Signed */False) ); 6846 break; 6847 6848 case 0x103: 6849 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr); 6850 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) ); 6851 break; 6852 6853 /* Even a lowly PPC7400 can run the associated helper, so no 6854 obvious need for feature testing at this point. */ 6855 case 268 /* 0x10C */: 6856 case 269 /* 0x10D */: { 6857 UInt arg = SPR==268 ? 0 : 1; 6858 IRTemp val = newTemp(Ity_I32); 6859 IRExpr** args = mkIRExprVec_1( mkU32(arg) ); 6860 IRDirty* d = unsafeIRDirty_1_N( 6861 val, 6862 0/*regparms*/, 6863 "ppc32g_dirtyhelper_MFSPR_268_269", 6864 fnptr_to_fnentry 6865 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269), 6866 args 6867 ); 6868 /* execute the dirty call, dumping the result in val. */ 6869 stmt( IRStmt_Dirty(d) ); 6870 putIReg( rD_addr, 6871 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 6872 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 6873 break; 6874 } 6875 6876 /* Again, runs natively on PPC7400 (7447, really). Not 6877 bothering with a feature test. */ 6878 case 287: /* 0x11F */ { 6879 IRTemp val = newTemp(Ity_I32); 6880 IRExpr** args = mkIRExprVec_0(); 6881 IRDirty* d = unsafeIRDirty_1_N( 6882 val, 6883 0/*regparms*/, 6884 "ppc32g_dirtyhelper_MFSPR_287", 6885 fnptr_to_fnentry 6886 (vbi, &ppc32g_dirtyhelper_MFSPR_287), 6887 args 6888 ); 6889 /* execute the dirty call, dumping the result in val. */ 6890 stmt( IRStmt_Dirty(d) ); 6891 putIReg( rD_addr, 6892 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) ); 6893 DIP("mfspr r%u,%u", rD_addr, (UInt)SPR); 6894 break; 6895 } 6896 6897 default: 6898 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR); 6899 return False; 6900 } 6901 break; 6902 6903 case 0x173: { // mftb (Move from Time Base, PPC32 p475) 6904 IRTemp val = newTemp(Ity_I64); 6905 IRExpr** args = mkIRExprVec_0(); 6906 IRDirty* d = unsafeIRDirty_1_N( 6907 val, 6908 0/*regparms*/, 6909 "ppcg_dirtyhelper_MFTB", 6910 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB), 6911 args ); 6912 /* execute the dirty call, dumping the result in val. */ 6913 stmt( IRStmt_Dirty(d) ); 6914 6915 switch (TBR) { 6916 case 269: 6917 DIP("mftbu r%u", rD_addr); 6918 putIReg( rD_addr, 6919 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)), 6920 /* Signed */False) ); 6921 break; 6922 case 268: 6923 DIP("mftb r%u", rD_addr); 6924 putIReg( rD_addr, (mode64) ? mkexpr(val) : 6925 unop(Iop_64to32, mkexpr(val)) ); 6926 break; 6927 default: 6928 return False; /* illegal instruction */ 6929 } 6930 break; 6931 } 6932 6933 case 0x090: { 6934 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477) 6935 // b20==1: mtocrf (Move to One Cond Reg Field) 6936 Int cr; 6937 UChar shft; 6938 if (b11 != 0) 6939 return False; 6940 if (b20 == 1) { 6941 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if > 6942 1 field is written. It seems more robust to decline to 6943 decode the insn if so. */ 6944 switch (CRM) { 6945 case 0x01: case 0x02: case 0x04: case 0x08: 6946 case 0x10: case 0x20: case 0x40: case 0x80: 6947 break; 6948 default: 6949 return False; 6950 } 6951 } 6952 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf", 6953 CRM, rS_addr); 6954 /* Write to each field specified by CRM */ 6955 for (cr = 0; cr < 8; cr++) { 6956 if ((CRM & (1 << (7-cr))) == 0) 6957 continue; 6958 shft = 4*(7-cr); 6959 putGST_field( PPC_GST_CR, 6960 binop(Iop_Shr32, 6961 mkNarrowTo32(ty, mkexpr(rS)), 6962 mkU8(shft)), cr ); 6963 } 6964 break; 6965 } 6966 6967 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483) 6968 6969 switch (SPR) { // Choose a register... 6970 case 0x1: 6971 DIP("mtxer r%u\n", rS_addr); 6972 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) ); 6973 break; 6974 case 0x8: 6975 DIP("mtlr r%u\n", rS_addr); 6976 putGST( PPC_GST_LR, mkexpr(rS) ); 6977 break; 6978 case 0x9: 6979 DIP("mtctr r%u\n", rS_addr); 6980 putGST( PPC_GST_CTR, mkexpr(rS) ); 6981 break; 6982 case 0x100: 6983 DIP("mtvrsave r%u\n", rS_addr); 6984 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) ); 6985 break; 6986 case 0x80: // 128 6987 DIP("mtspr r%u (TFHAR)\n", rS_addr); 6988 putGST( PPC_GST_TFHAR, mkexpr(rS) ); 6989 break; 6990 case 0x81: // 129 6991 DIP("mtspr r%u (TFIAR)\n", rS_addr); 6992 putGST( PPC_GST_TFIAR, mkexpr(rS) ); 6993 break; 6994 case 0x82: // 130 6995 DIP("mtspr r%u (TEXASR)\n", rS_addr); 6996 putGST( PPC_GST_TEXASR, mkexpr(rS) ); 6997 break; 6998 default: 6999 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR); 7000 return False; 7001 } 7002 break; 7003 7004 case 0x33: // mfvsrd 7005 { 7006 UChar XS = ifieldRegXS( theInstr ); 7007 UChar rA_addr = ifieldRegA(theInstr); 7008 IRExpr * high64; 7009 IRTemp vS = newTemp( Ity_V128 ); 7010 DIP("mfvsrd r%u,vsr%d\n", rA_addr, (UInt)XS); 7011 7012 /* XS = SX || S 7013 * For SX=0, mfvsrd is treated as a Floating-Point 7014 * instruction in terms of resource availability. 7015 * For SX=1, mfvsrd is treated as a Vector instruction in 7016 * terms of resource availability. 7017 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7018 */ 7019 assign( vS, getVSReg( XS ) ); 7020 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 7021 putIReg( rA_addr, (mode64) ? high64 : 7022 unop( Iop_64to32, high64 ) ); 7023 break; 7024 } 7025 7026 case 0x73: // mfvsrwz 7027 { 7028 UChar XS = ifieldRegXS( theInstr ); 7029 UChar rA_addr = ifieldRegA(theInstr); 7030 IRExpr * high64; 7031 IRTemp vS = newTemp( Ity_V128 ); 7032 DIP("mfvsrwz r%u,vsr%d\n", rA_addr, (UInt)XS); 7033 /* XS = SX || S 7034 * For SX=0, mfvsrwz is treated as a Floating-Point 7035 * instruction in terms of resource availability. 7036 * For SX=1, mfvsrwz is treated as a Vector instruction in 7037 * terms of resource availability. 7038 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7039 */ 7040 7041 assign( vS, getVSReg( XS ) ); 7042 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 7043 /* move value to the destination setting the upper 32-bits to zero */ 7044 putIReg( rA_addr, (mode64) ? 7045 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) : 7046 unop( Iop_64to32, 7047 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) ); 7048 break; 7049 } 7050 7051 case 0xB3: // mtvsrd 7052 { 7053 UChar XT = ifieldRegXT( theInstr ); 7054 UChar rA_addr = ifieldRegA(theInstr); 7055 IRTemp rA = newTemp(ty); 7056 DIP("mtvsrd vsr%d,r%u\n", (UInt)XT, rA_addr); 7057 /* XS = SX || S 7058 * For SX=0, mfvsrd is treated as a Floating-Point 7059 * instruction in terms of resource availability. 7060 * For SX=1, mfvsrd is treated as a Vector instruction in 7061 * terms of resource availability. 7062 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7063 */ 7064 assign( rA, getIReg(rA_addr) ); 7065 7066 if (mode64) 7067 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) ); 7068 else 7069 putVSReg( XT, binop( Iop_64HLtoV128, 7070 binop( Iop_32HLto64, 7071 mkU32( 0 ), 7072 mkexpr( rA ) ), 7073 mkU64( 0 ) ) ); 7074 break; 7075 } 7076 7077 case 0xD3: // mtvsrwa 7078 { 7079 UChar XT = ifieldRegXT( theInstr ); 7080 UChar rA_addr = ifieldRegA(theInstr); 7081 IRTemp rA = newTemp( Ity_I32 ); 7082 DIP("mtvsrwa vsr%d,r%u\n", (UInt)XT, rA_addr); 7083 /* XS = SX || S 7084 * For SX=0, mtvsrwa is treated as a Floating-Point 7085 * instruction in terms of resource availability. 7086 * For SX=1, mtvsrwa is treated as a Vector instruction in 7087 * terms of resource availability. 7088 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7089 */ 7090 if (mode64) 7091 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 7092 else 7093 assign( rA, getIReg(rA_addr) ); 7094 7095 putVSReg( XT, binop( Iop_64HLtoV128, 7096 unop( Iop_32Sto64, mkexpr( rA ) ), 7097 mkU64( 0 ) ) ); 7098 break; 7099 } 7100 7101 case 0xF3: // mtvsrwz 7102 { 7103 UChar XT = ifieldRegXT( theInstr ); 7104 UChar rA_addr = ifieldRegA(theInstr); 7105 IRTemp rA = newTemp( Ity_I32 ); 7106 DIP("mtvsrwz vsr%d,r%u\n", rA_addr, (UInt)XT); 7107 /* XS = SX || S 7108 * For SX=0, mtvsrwz is treated as a Floating-Point 7109 * instruction in terms of resource availability. 7110 * For SX=1, mtvsrwz is treated as a Vector instruction in 7111 * terms of resource availability. 7112 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART 7113 */ 7114 if (mode64) 7115 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) ); 7116 else 7117 assign( rA, getIReg(rA_addr) ); 7118 7119 putVSReg( XT, binop( Iop_64HLtoV128, 7120 binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ), 7121 mkU64( 0 ) ) ); 7122 break; 7123 } 7124 7125 default: 7126 vex_printf("dis_proc_ctl(ppc)(opc2)\n"); 7127 return False; 7128 } 7129 return True; 7130 } 7131 7132 7133 /* 7134 Cache Management Instructions 7135 */ 7136 static Bool dis_cache_manage ( UInt theInstr, 7137 DisResult* dres, 7138 VexArchInfo* guest_archinfo ) 7139 { 7140 /* X-Form */ 7141 UChar opc1 = ifieldOPC(theInstr); 7142 UChar b21to25 = ifieldRegDS(theInstr); 7143 UChar rA_addr = ifieldRegA(theInstr); 7144 UChar rB_addr = ifieldRegB(theInstr); 7145 UInt opc2 = ifieldOPClo10(theInstr); 7146 UChar b0 = ifieldBIT0(theInstr); 7147 UInt lineszB = guest_archinfo->ppc_icache_line_szB; 7148 Bool is_dcbzl = False; 7149 7150 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7151 7152 // Check for valid hint values for dcbt and dcbtst as currently described in 7153 // ISA 2.07. If valid, then we simply set b21to25 to zero since we have no 7154 // means of modeling the hint anyway. 7155 if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) { 7156 if (b21to25 == 0x10 || b21to25 < 0x10) 7157 b21to25 = 0; 7158 } 7159 if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11) 7160 b21to25 = 0; 7161 7162 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz 7163 if (b21to25 == 1) { 7164 is_dcbzl = True; 7165 b21to25 = 0; 7166 if (!(guest_archinfo->ppc_dcbzl_szB)) { 7167 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n"); 7168 return False; 7169 } 7170 } 7171 } 7172 7173 if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) { 7174 if (0) vex_printf("dis_cache_manage %d %d %d\n", 7175 (Int)opc1, (Int)b21to25, (Int)b0); 7176 vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n"); 7177 return False; 7178 } 7179 7180 /* stay sane .. */ 7181 vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128); 7182 7183 switch (opc2) { 7184 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380) 7185 //zz vassert(0); /* AWAITING TEST CASE */ 7186 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr); 7187 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n"); 7188 //zz break; 7189 7190 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382) 7191 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr); 7192 /* nop as far as vex is concerned */ 7193 break; 7194 7195 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384) 7196 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr); 7197 /* nop as far as vex is concerned */ 7198 break; 7199 7200 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385) 7201 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr); 7202 /* nop as far as vex is concerned */ 7203 break; 7204 7205 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386) 7206 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr); 7207 /* nop as far as vex is concerned */ 7208 break; 7209 7210 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387) 7211 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264) 7212 /* Clear all bytes in cache block at (rA|0) + rB. */ 7213 IRTemp EA = newTemp(ty); 7214 IRTemp addr = newTemp(ty); 7215 IRExpr* irx_addr; 7216 UInt i; 7217 UInt clearszB; 7218 if (is_dcbzl) { 7219 clearszB = guest_archinfo->ppc_dcbzl_szB; 7220 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr); 7221 } 7222 else { 7223 clearszB = guest_archinfo->ppc_dcbz_szB; 7224 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr); 7225 } 7226 7227 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7228 7229 if (mode64) { 7230 /* Round EA down to the start of the containing block. */ 7231 assign( addr, binop( Iop_And64, 7232 mkexpr(EA), 7233 mkU64( ~((ULong)clearszB-1) )) ); 7234 7235 for (i = 0; i < clearszB / 8; i++) { 7236 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) ); 7237 storeBE( irx_addr, mkU64(0) ); 7238 } 7239 } else { 7240 /* Round EA down to the start of the containing block. */ 7241 assign( addr, binop( Iop_And32, 7242 mkexpr(EA), 7243 mkU32( ~(clearszB-1) )) ); 7244 7245 for (i = 0; i < clearszB / 4; i++) { 7246 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) ); 7247 storeBE( irx_addr, mkU32(0) ); 7248 } 7249 } 7250 break; 7251 } 7252 7253 case 0x3D6: { 7254 // icbi (Instruction Cache Block Invalidate, PPC32 p431) 7255 /* Invalidate all translations containing code from the cache 7256 block at (rA|0) + rB. */ 7257 IRTemp EA = newTemp(ty); 7258 IRTemp addr = newTemp(ty); 7259 DIP("icbi r%u,r%u\n", rA_addr, rB_addr); 7260 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7261 7262 /* Round EA down to the start of the containing block. */ 7263 assign( addr, binop( mkSzOp(ty, Iop_And8), 7264 mkexpr(EA), 7265 mkSzImm(ty, ~(((ULong)lineszB)-1) )) ); 7266 putGST( PPC_GST_CMSTART, mkexpr(addr) ); 7267 putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) ); 7268 7269 /* be paranoid ... */ 7270 stmt( IRStmt_MBE(Imbe_Fence) ); 7271 7272 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr())); 7273 dres->jk_StopHere = Ijk_InvalICache; 7274 dres->whatNext = Dis_StopHere; 7275 break; 7276 } 7277 7278 default: 7279 vex_printf("dis_cache_manage(ppc)(opc2)\n"); 7280 return False; 7281 } 7282 return True; 7283 } 7284 7285 7286 /*------------------------------------------------------------*/ 7287 /*--- Floating Point Helpers ---*/ 7288 /*------------------------------------------------------------*/ 7289 7290 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */ 7291 /* Produces a value in 0 .. 3, which is encoded as per the type 7292 IRRoundingMode. PPCRoundingMode encoding is different to 7293 IRRoundingMode, so need to map it. 7294 */ 7295 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void ) 7296 { 7297 /* 7298 rounding mode | PPC | IR 7299 ------------------------ 7300 to nearest | 00 | 00 7301 to zero | 01 | 11 7302 to +infinity | 10 | 10 7303 to -infinity | 11 | 01 7304 */ 7305 IRTemp rm_PPC32 = newTemp(Ity_I32); 7306 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) ); 7307 7308 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 7309 return binop( Iop_Xor32, 7310 mkexpr(rm_PPC32), 7311 binop( Iop_And32, 7312 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)), 7313 mkU32(2) )); 7314 } 7315 7316 /* The DFP IR rounding modes were chosen such that the existing PPC to IR 7317 * mapping would still work with the extended three bit DFP rounding 7318 * mode designator. 7319 7320 * rounding mode | PPC | IR 7321 * ----------------------------------------------- 7322 * to nearest, ties to even | 000 | 000 7323 * to zero | 001 | 011 7324 * to +infinity | 010 | 010 7325 * to -infinity | 011 | 001 7326 * to nearest, ties away from 0 | 100 | 100 7327 * to nearest, ties toward 0 | 101 | 111 7328 * to away from 0 | 110 | 110 7329 * to prepare for shorter precision | 111 | 101 7330 */ 7331 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void ) 7332 { 7333 IRTemp rm_PPC32 = newTemp( Ity_I32 ); 7334 assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) ); 7335 7336 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) 7337 return binop( Iop_Xor32, 7338 mkexpr( rm_PPC32 ), 7339 binop( Iop_And32, 7340 binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ), 7341 mkU32( 2 ) ) ); 7342 } 7343 7344 #define NANmaskSingle 0x7F800000 7345 #define NANmaskDouble 0x7FF00000 7346 7347 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask ) 7348 { 7349 IRTemp exp_zero = newTemp(Ity_I8); 7350 IRTemp frac_mask = newTemp(Ity_I32); 7351 IRTemp frac_not_zero = newTemp(Ity_I8); 7352 7353 /* Check if the result is QNAN or SNAN and not +infinity or -infinity. 7354 * The input value is always 64-bits, for single precision values, the 7355 * lower 32 bits must be zero. 7356 * 7357 * Single Pricision 7358 * [62:54] exponent field is equal to 0xFF for NAN and Infinity. 7359 * [53:32] fraction field is zero for Infinity and non-zero for NAN 7360 * [31:0] unused for single precision representation 7361 * 7362 * Double Pricision 7363 * [62:51] exponent field is equal to 0xFF for NAN and Infinity. 7364 * [50:0] fraction field is zero for Infinity and non-zero for NAN 7365 * 7366 * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise. 7367 */ 7368 assign( frac_mask, unop( Iop_Not32, 7369 binop( Iop_Or32, 7370 mkU32( 0x80000000ULL ), Hi32Mask) ) ); 7371 7372 assign( exp_zero, 7373 unop( Iop_1Sto8, 7374 binop( Iop_CmpEQ32, 7375 binop( Iop_And32, 7376 unop( Iop_64HIto32, 7377 unop( Iop_ReinterpF64asI64, 7378 value ) ), 7379 Hi32Mask ), 7380 Hi32Mask ) ) ); 7381 assign( frac_not_zero, 7382 binop( Iop_Or8, 7383 unop( Iop_1Sto8, 7384 binop( Iop_CmpNE32, 7385 binop( Iop_And32, 7386 unop( Iop_64HIto32, 7387 unop( Iop_ReinterpF64asI64, 7388 value ) ), 7389 mkexpr( frac_mask ) ), 7390 mkU32( 0x0 ) ) ), 7391 unop( Iop_1Sto8, 7392 binop( Iop_CmpNE32, 7393 binop( Iop_And32, 7394 unop( Iop_64to32, 7395 unop( Iop_ReinterpF64asI64, 7396 value ) ), 7397 mkU32( 0xFFFFFFFF ) ), 7398 mkU32( 0x0 ) ) ) ) ); 7399 return unop( Iop_8Sto32, 7400 binop( Iop_And8, 7401 mkexpr( exp_zero ), 7402 mkexpr( frac_not_zero ) ) ); 7403 } 7404 7405 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask ) 7406 { 7407 /* This function will only complement the 64-bit floating point value if it 7408 * is not Nan. NaN is not a signed value. Need to do computations using 7409 * 32-bit operands to ensure it will run in 32-bit mode. 7410 */ 7411 return binop( Iop_32HLto64, 7412 binop( Iop_Or32, 7413 binop( Iop_And32, 7414 nan_mask, 7415 unop( Iop_64HIto32, 7416 unop( Iop_ReinterpF64asI64, 7417 value ) ) ), 7418 binop( Iop_And32, 7419 unop( Iop_Not32, 7420 nan_mask ), 7421 unop( Iop_64HIto32, 7422 unop( Iop_ReinterpF64asI64, 7423 unop( Iop_NegF64, 7424 value ) ) ) ) ), 7425 unop( Iop_64to32, 7426 unop( Iop_ReinterpF64asI64, value ) ) ); 7427 } 7428 7429 /*------------------------------------------------------------*/ 7430 /*--- Floating Point Instruction Translation ---*/ 7431 /*------------------------------------------------------------*/ 7432 7433 /* 7434 Floating Point Load Instructions 7435 */ 7436 static Bool dis_fp_load ( UInt theInstr ) 7437 { 7438 /* X-Form, D-Form */ 7439 UChar opc1 = ifieldOPC(theInstr); 7440 UChar frD_addr = ifieldRegDS(theInstr); 7441 UChar rA_addr = ifieldRegA(theInstr); 7442 UChar rB_addr = ifieldRegB(theInstr); 7443 UInt opc2 = ifieldOPClo10(theInstr); 7444 UChar b0 = ifieldBIT0(theInstr); 7445 UInt uimm16 = ifieldUIMM16(theInstr); 7446 7447 Int simm16 = extend_s_16to32(uimm16); 7448 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7449 IRTemp EA = newTemp(ty); 7450 IRTemp rA = newTemp(ty); 7451 IRTemp rB = newTemp(ty); 7452 IRTemp iHi = newTemp(Ity_I32); 7453 IRTemp iLo = newTemp(Ity_I32); 7454 7455 assign( rA, getIReg(rA_addr) ); 7456 assign( rB, getIReg(rB_addr) ); 7457 7458 /* These are completely straightforward from a rounding and status 7459 bits perspective: no rounding involved and no funny status or CR 7460 bits affected. */ 7461 7462 switch (opc1) { 7463 case 0x30: // lfs (Load Float Single, PPC32 p441) 7464 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7465 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7466 putFReg( frD_addr, 7467 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 7468 break; 7469 7470 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442) 7471 if (rA_addr == 0) 7472 return False; 7473 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7474 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7475 putFReg( frD_addr, 7476 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 7477 putIReg( rA_addr, mkexpr(EA) ); 7478 break; 7479 7480 case 0x32: // lfd (Load Float Double, PPC32 p437) 7481 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7482 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7483 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 7484 break; 7485 7486 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438) 7487 if (rA_addr == 0) 7488 return False; 7489 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr); 7490 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7491 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 7492 putIReg( rA_addr, mkexpr(EA) ); 7493 break; 7494 7495 case 0x1F: 7496 if (b0 != 0) { 7497 vex_printf("dis_fp_load(ppc)(instr,b0)\n"); 7498 return False; 7499 } 7500 7501 switch(opc2) { 7502 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444) 7503 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7504 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7505 putFReg( frD_addr, unop( Iop_F32toF64, 7506 loadBE(Ity_F32, mkexpr(EA))) ); 7507 break; 7508 7509 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443) 7510 if (rA_addr == 0) 7511 return False; 7512 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7513 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7514 putFReg( frD_addr, 7515 unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) ); 7516 putIReg( rA_addr, mkexpr(EA) ); 7517 break; 7518 7519 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440) 7520 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7521 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7522 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 7523 break; 7524 7525 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439) 7526 if (rA_addr == 0) 7527 return False; 7528 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7529 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7530 putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) ); 7531 putIReg( rA_addr, mkexpr(EA) ); 7532 break; 7533 7534 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120) 7535 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7536 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7537 assign( iLo, loadBE(Ity_I32, mkexpr(EA)) ); 7538 assign( iHi, binop(Iop_Sub32, 7539 mkU32(0), 7540 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) ); 7541 putFReg( frD_addr, unop(Iop_ReinterpI64asF64, 7542 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) ); 7543 break; 7544 7545 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed 7546 { 7547 IRTemp dw = newTemp( Ity_I64 ); 7548 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr); 7549 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 7550 assign( iLo, loadBE(Ity_I32, mkexpr(EA)) ); 7551 assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) ); 7552 putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) ); 7553 break; 7554 } 7555 7556 default: 7557 vex_printf("dis_fp_load(ppc)(opc2)\n"); 7558 return False; 7559 } 7560 break; 7561 7562 default: 7563 vex_printf("dis_fp_load(ppc)(opc1)\n"); 7564 return False; 7565 } 7566 return True; 7567 } 7568 7569 7570 7571 /* 7572 Floating Point Store Instructions 7573 */ 7574 static Bool dis_fp_store ( UInt theInstr ) 7575 { 7576 /* X-Form, D-Form */ 7577 UChar opc1 = ifieldOPC(theInstr); 7578 UChar frS_addr = ifieldRegDS(theInstr); 7579 UChar rA_addr = ifieldRegA(theInstr); 7580 UChar rB_addr = ifieldRegB(theInstr); 7581 UInt opc2 = ifieldOPClo10(theInstr); 7582 UChar b0 = ifieldBIT0(theInstr); 7583 Int uimm16 = ifieldUIMM16(theInstr); 7584 7585 Int simm16 = extend_s_16to32(uimm16); 7586 IRTemp frS = newTemp(Ity_F64); 7587 IRType ty = mode64 ? Ity_I64 : Ity_I32; 7588 IRTemp EA = newTemp(ty); 7589 IRTemp rA = newTemp(ty); 7590 IRTemp rB = newTemp(ty); 7591 7592 assign( frS, getFReg(frS_addr) ); 7593 assign( rA, getIReg(rA_addr) ); 7594 assign( rB, getIReg(rB_addr) ); 7595 7596 /* These are straightforward from a status bits perspective: no 7597 funny status or CR bits affected. For single precision stores, 7598 the values are truncated and denormalised (not rounded) to turn 7599 them into single precision values. */ 7600 7601 switch (opc1) { 7602 7603 case 0x34: // stfs (Store Float Single, PPC32 p518) 7604 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7605 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7606 /* Use Iop_TruncF64asF32 to truncate and possible denormalise 7607 the value to be stored in the correct way, without any 7608 rounding. */ 7609 storeBE( mkexpr(EA), 7610 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7611 break; 7612 7613 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519) 7614 if (rA_addr == 0) 7615 return False; 7616 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7617 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7618 /* See comment for stfs */ 7619 storeBE( mkexpr(EA), 7620 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7621 putIReg( rA_addr, mkexpr(EA) ); 7622 break; 7623 7624 case 0x36: // stfd (Store Float Double, PPC32 p513) 7625 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7626 assign( EA, ea_rAor0_simm(rA_addr, simm16) ); 7627 storeBE( mkexpr(EA), mkexpr(frS) ); 7628 break; 7629 7630 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514) 7631 if (rA_addr == 0) 7632 return False; 7633 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr); 7634 assign( EA, ea_rA_simm(rA_addr, simm16) ); 7635 storeBE( mkexpr(EA), mkexpr(frS) ); 7636 putIReg( rA_addr, mkexpr(EA) ); 7637 break; 7638 7639 case 0x1F: 7640 if (b0 != 0) { 7641 vex_printf("dis_fp_store(ppc)(instr,b0)\n"); 7642 return False; 7643 } 7644 switch(opc2) { 7645 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521) 7646 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7647 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7648 /* See note for stfs */ 7649 storeBE( mkexpr(EA), 7650 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7651 break; 7652 7653 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520) 7654 if (rA_addr == 0) 7655 return False; 7656 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7657 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7658 /* See note for stfs */ 7659 storeBE( mkexpr(EA), 7660 unop(Iop_TruncF64asF32, mkexpr(frS)) ); 7661 putIReg( rA_addr, mkexpr(EA) ); 7662 break; 7663 7664 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516) 7665 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7666 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7667 storeBE( mkexpr(EA), mkexpr(frS) ); 7668 break; 7669 7670 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515) 7671 if (rA_addr == 0) 7672 return False; 7673 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7674 assign( EA, ea_rA_idxd(rA_addr, rB_addr) ); 7675 storeBE( mkexpr(EA), mkexpr(frS) ); 7676 putIReg( rA_addr, mkexpr(EA) ); 7677 break; 7678 7679 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517) 7680 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7681 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr); 7682 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 7683 storeBE( mkexpr(EA), 7684 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) ); 7685 break; 7686 7687 default: 7688 vex_printf("dis_fp_store(ppc)(opc2)\n"); 7689 return False; 7690 } 7691 break; 7692 7693 default: 7694 vex_printf("dis_fp_store(ppc)(opc1)\n"); 7695 return False; 7696 } 7697 return True; 7698 } 7699 7700 7701 7702 /* 7703 Floating Point Arith Instructions 7704 */ 7705 static Bool dis_fp_arith ( UInt theInstr ) 7706 { 7707 /* A-Form */ 7708 UChar opc1 = ifieldOPC(theInstr); 7709 UChar frD_addr = ifieldRegDS(theInstr); 7710 UChar frA_addr = ifieldRegA(theInstr); 7711 UChar frB_addr = ifieldRegB(theInstr); 7712 UChar frC_addr = ifieldRegC(theInstr); 7713 UChar opc2 = ifieldOPClo5(theInstr); 7714 UChar flag_rC = ifieldBIT0(theInstr); 7715 7716 IRTemp frD = newTemp(Ity_F64); 7717 IRTemp frA = newTemp(Ity_F64); 7718 IRTemp frB = newTemp(Ity_F64); 7719 IRTemp frC = newTemp(Ity_F64); 7720 IRExpr* rm = get_IR_roundingmode(); 7721 7722 /* By default, we will examine the results of the operation and set 7723 fpscr[FPRF] accordingly. */ 7724 Bool set_FPRF = True; 7725 7726 /* By default, if flag_RC is set, we will clear cr1 after the 7727 operation. In reality we should set cr1 to indicate the 7728 exception status of the operation, but since we're not 7729 simulating exceptions, the exception status will appear to be 7730 zero. Hence cr1 should be cleared if this is a . form insn. */ 7731 Bool clear_CR1 = True; 7732 7733 assign( frA, getFReg(frA_addr)); 7734 assign( frB, getFReg(frB_addr)); 7735 assign( frC, getFReg(frC_addr)); 7736 7737 switch (opc1) { 7738 case 0x3B: 7739 switch (opc2) { 7740 case 0x12: // fdivs (Floating Divide Single, PPC32 p407) 7741 if (frC_addr != 0) 7742 return False; 7743 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7744 frD_addr, frA_addr, frB_addr); 7745 assign( frD, triop( Iop_DivF64r32, 7746 rm, mkexpr(frA), mkexpr(frB) )); 7747 break; 7748 7749 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430) 7750 if (frC_addr != 0) 7751 return False; 7752 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7753 frD_addr, frA_addr, frB_addr); 7754 assign( frD, triop( Iop_SubF64r32, 7755 rm, mkexpr(frA), mkexpr(frB) )); 7756 break; 7757 7758 case 0x15: // fadds (Floating Add Single, PPC32 p401) 7759 if (frC_addr != 0) 7760 return False; 7761 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7762 frD_addr, frA_addr, frB_addr); 7763 assign( frD, triop( Iop_AddF64r32, 7764 rm, mkexpr(frA), mkexpr(frB) )); 7765 break; 7766 7767 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428) 7768 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 7769 if (frA_addr != 0 || frC_addr != 0) 7770 return False; 7771 DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"", 7772 frD_addr, frB_addr); 7773 // however illogically, on ppc970 this insn behaves identically 7774 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32. 7775 assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) )); 7776 break; 7777 7778 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421) 7779 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7780 if (frA_addr != 0 || frC_addr != 0) 7781 return False; 7782 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"", 7783 frD_addr, frB_addr); 7784 { IRExpr* ieee_one 7785 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 7786 assign( frD, triop( Iop_DivF64r32, 7787 rm, 7788 ieee_one, mkexpr(frB) )); 7789 } 7790 break; 7791 7792 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414) 7793 if (frB_addr != 0) 7794 return False; 7795 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7796 frD_addr, frA_addr, frC_addr); 7797 assign( frD, triop( Iop_MulF64r32, 7798 rm, mkexpr(frA), mkexpr(frC) )); 7799 break; 7800 7801 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single) 7802 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7803 // Undocumented instruction? 7804 if (frA_addr != 0 || frC_addr != 0) 7805 return False; 7806 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"", 7807 frD_addr, frB_addr); 7808 assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) ); 7809 break; 7810 7811 default: 7812 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n"); 7813 return False; 7814 } 7815 break; 7816 7817 case 0x3F: 7818 switch (opc2) { 7819 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406) 7820 if (frC_addr != 0) 7821 return False; 7822 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7823 frD_addr, frA_addr, frB_addr); 7824 assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) ); 7825 break; 7826 7827 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429) 7828 if (frC_addr != 0) 7829 return False; 7830 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7831 frD_addr, frA_addr, frB_addr); 7832 assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) ); 7833 break; 7834 7835 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400) 7836 if (frC_addr != 0) 7837 return False; 7838 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7839 frD_addr, frA_addr, frB_addr); 7840 assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) ); 7841 break; 7842 7843 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427) 7844 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX) 7845 if (frA_addr != 0 || frC_addr != 0) 7846 return False; 7847 DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"", 7848 frD_addr, frB_addr); 7849 assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) ); 7850 break; 7851 7852 case 0x17: { // fsel (Floating Select, PPC32 p426) 7853 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7854 IRTemp cc = newTemp(Ity_I32); 7855 IRTemp cc_b0 = newTemp(Ity_I32); 7856 7857 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7858 frD_addr, frA_addr, frC_addr, frB_addr); 7859 7860 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40 7861 // => GT|EQ == (cc & 0x1 == 0) 7862 assign( cc, binop(Iop_CmpF64, mkexpr(frA), 7863 IRExpr_Const(IRConst_F64(0))) ); 7864 assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) ); 7865 7866 // frD = (frA >= 0.0) ? frC : frB 7867 // = (cc_b0 == 0) ? frC : frB 7868 assign( frD, 7869 IRExpr_ITE( 7870 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)), 7871 mkexpr(frC), 7872 mkexpr(frB) )); 7873 7874 /* One of the rare ones which don't mess with FPRF */ 7875 set_FPRF = False; 7876 break; 7877 } 7878 7879 case 0x18: // fre (Floating Reciprocal Estimate) 7880 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7881 // Note: unclear whether this insn really exists or not 7882 // ppc970 doesn't have it, but POWER5 does 7883 if (frA_addr != 0 || frC_addr != 0) 7884 return False; 7885 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"", 7886 frD_addr, frB_addr); 7887 { IRExpr* ieee_one 7888 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 7889 assign( frD, triop( Iop_DivF64, 7890 rm, 7891 ieee_one, mkexpr(frB) )); 7892 } 7893 break; 7894 7895 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413) 7896 if (frB_addr != 0) 7897 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n"); 7898 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7899 frD_addr, frA_addr, frC_addr); 7900 assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) ); 7901 break; 7902 7903 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424) 7904 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX) 7905 if (frA_addr != 0 || frC_addr != 0) 7906 return False; 7907 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"", 7908 frD_addr, frB_addr); 7909 assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) ); 7910 break; 7911 7912 default: 7913 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n"); 7914 return False; 7915 } 7916 break; 7917 7918 default: 7919 vex_printf("dis_fp_arith(ppc)(opc1)\n"); 7920 return False; 7921 } 7922 7923 putFReg( frD_addr, mkexpr(frD) ); 7924 7925 if (set_FPRF) { 7926 // XXX XXX XXX FIXME 7927 // set FPRF from frD 7928 } 7929 7930 if (flag_rC && clear_CR1) { 7931 putCR321( 1, mkU8(0) ); 7932 putCR0( 1, mkU8(0) ); 7933 } 7934 7935 return True; 7936 } 7937 7938 7939 7940 /* 7941 Floating Point Mult-Add Instructions 7942 */ 7943 static Bool dis_fp_multadd ( UInt theInstr ) 7944 { 7945 /* A-Form */ 7946 UChar opc1 = ifieldOPC(theInstr); 7947 UChar frD_addr = ifieldRegDS(theInstr); 7948 UChar frA_addr = ifieldRegA(theInstr); 7949 UChar frB_addr = ifieldRegB(theInstr); 7950 UChar frC_addr = ifieldRegC(theInstr); 7951 UChar opc2 = ifieldOPClo5(theInstr); 7952 UChar flag_rC = ifieldBIT0(theInstr); 7953 7954 IRTemp frD = newTemp(Ity_F64); 7955 IRTemp frA = newTemp(Ity_F64); 7956 IRTemp frB = newTemp(Ity_F64); 7957 IRTemp frC = newTemp(Ity_F64); 7958 IRTemp rmt = newTemp(Ity_I32); 7959 IRTemp tmp = newTemp(Ity_F64); 7960 IRTemp sign_tmp = newTemp(Ity_I64); 7961 IRTemp nan_mask = newTemp(Ity_I32); 7962 IRExpr* rm; 7963 7964 /* By default, we will examine the results of the operation and set 7965 fpscr[FPRF] accordingly. */ 7966 Bool set_FPRF = True; 7967 7968 /* By default, if flag_RC is set, we will clear cr1 after the 7969 operation. In reality we should set cr1 to indicate the 7970 exception status of the operation, but since we're not 7971 simulating exceptions, the exception status will appear to be 7972 zero. Hence cr1 should be cleared if this is a . form insn. */ 7973 Bool clear_CR1 = True; 7974 7975 /* Bind the rounding mode expression to a temp; there's no 7976 point in creating gratuitous CSEs, as we know we'll need 7977 to use it twice. */ 7978 assign( rmt, get_IR_roundingmode() ); 7979 rm = mkexpr(rmt); 7980 7981 assign( frA, getFReg(frA_addr)); 7982 assign( frB, getFReg(frB_addr)); 7983 assign( frC, getFReg(frC_addr)); 7984 7985 /* The rounding in this is all a bit dodgy. The idea is to only do 7986 one rounding. That clearly isn't achieveable without dedicated 7987 four-input IR primops, although in the single precision case we 7988 can sort-of simulate it by doing the inner multiply in double 7989 precision. 7990 7991 In the negated cases, the negation happens after rounding. */ 7992 7993 switch (opc1) { 7994 case 0x3B: 7995 switch (opc2) { 7996 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412) 7997 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 7998 frD_addr, frA_addr, frC_addr, frB_addr); 7999 assign( frD, qop( Iop_MSubF64r32, rm, 8000 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8001 break; 8002 8003 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409) 8004 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8005 frD_addr, frA_addr, frC_addr, frB_addr); 8006 assign( frD, qop( Iop_MAddF64r32, rm, 8007 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8008 break; 8009 8010 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420) 8011 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418) 8012 8013 if (opc2 == 0x1E) { 8014 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8015 frD_addr, frA_addr, frC_addr, frB_addr); 8016 assign( tmp, qop( Iop_MSubF64r32, rm, 8017 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8018 } else { 8019 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8020 frD_addr, frA_addr, frC_addr, frB_addr); 8021 assign( tmp, qop( Iop_MAddF64r32, rm, 8022 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8023 } 8024 8025 assign( nan_mask, Check_NaN( mkexpr( tmp ), 8026 mkU32( NANmaskSingle ) ) ); 8027 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 8028 mkexpr( nan_mask ) ) ); 8029 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 8030 break; 8031 8032 default: 8033 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n"); 8034 return False; 8035 } 8036 break; 8037 8038 case 0x3F: 8039 switch (opc2) { 8040 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411) 8041 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8042 frD_addr, frA_addr, frC_addr, frB_addr); 8043 assign( frD, qop( Iop_MSubF64, rm, 8044 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8045 break; 8046 8047 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408) 8048 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8049 frD_addr, frA_addr, frC_addr, frB_addr); 8050 assign( frD, qop( Iop_MAddF64, rm, 8051 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8052 break; 8053 8054 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419) 8055 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417) 8056 8057 if (opc2 == 0x1E) { 8058 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8059 frD_addr, frA_addr, frC_addr, frB_addr); 8060 assign( tmp, qop( Iop_MSubF64, rm, 8061 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) ); 8062 } else { 8063 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"", 8064 frD_addr, frA_addr, frC_addr, frB_addr); 8065 assign( tmp, qop( Iop_MAddF64, rm, 8066 mkexpr(frA), mkexpr(frC), mkexpr(frB) )); 8067 } 8068 8069 assign( nan_mask, Check_NaN( mkexpr( tmp ), 8070 mkU32( NANmaskDouble ) ) ); 8071 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ), 8072 mkexpr( nan_mask ) ) ); 8073 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) ); 8074 break; 8075 8076 default: 8077 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n"); 8078 return False; 8079 } 8080 break; 8081 8082 default: 8083 vex_printf("dis_fp_multadd(ppc)(opc1)\n"); 8084 return False; 8085 } 8086 8087 putFReg( frD_addr, mkexpr(frD) ); 8088 8089 if (set_FPRF) { 8090 // XXX XXX XXX FIXME 8091 // set FPRF from frD 8092 } 8093 8094 if (flag_rC && clear_CR1) { 8095 putCR321( 1, mkU8(0) ); 8096 putCR0( 1, mkU8(0) ); 8097 } 8098 8099 return True; 8100 } 8101 8102 /* 8103 * fe_flag is set to 1 if any of the following conditions occurs: 8104 * - The floating-point operand in register FRB is a Zero, a 8105 * NaN, an Infinity, or a negative value. 8106 * - e_b is less than or equal to: -970 for double precision; -103 for single precision 8107 * Otherwise fe_flag is set to 0. 8108 * 8109 * fg_flag is set to 1 if either of the following conditions occurs. 8110 * - The floating-point operand in register FRB is a Zero, an 8111 * Infinity, or a denormalized value. 8112 * Otherwise fg_flag is set to 0. 8113 * 8114 */ 8115 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 8116 { 8117 // The following temps are for holding intermediate results 8118 IRTemp e_b = newTemp(Ity_I32); 8119 IRExpr * fe_flag, * fg_flag; 8120 IRTemp frB_exp_shR = newTemp(Ity_I32); 8121 UInt bias = sp? 127 : 1023; 8122 IRExpr * frbNaN, * frbDenorm, * frBNeg; 8123 IRExpr * eb_LTE; 8124 IRTemp frbZero_tmp = newTemp(Ity_I1); 8125 IRTemp frbInf_tmp = newTemp(Ity_I1); 8126 *fe_flag_tmp = newTemp(Ity_I32); 8127 *fg_flag_tmp = newTemp(Ity_I32); 8128 assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) ); 8129 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 8130 8131 ////////////////// fe_flag tests BEGIN ////////////////////// 8132 /* We first do all tests that may result in setting fe_flag to '1'. 8133 * (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv() 8134 * for details.) 8135 */ 8136 frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int); 8137 assign( frbInf_tmp, is_Inf(frB_Int, sp) ); 8138 assign( frbZero_tmp, is_Zero(frB_Int, sp ) ); 8139 { 8140 // Test_value = -970 for double precision 8141 UInt test_value = sp ? 0xffffff99 : 0xfffffc36; 8142 eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) ); 8143 } 8144 frBNeg = binop( Iop_CmpEQ32, 8145 binop( Iop_Shr32, 8146 sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ), 8147 mkU8( 31 ) ), 8148 mkU32( 1 ) ); 8149 ////////////////// fe_flag tests END ////////////////////// 8150 8151 ////////////////// fg_flag tests BEGIN ////////////////////// 8152 /* 8153 * The following tests were already performed above in the fe_flag 8154 * tests. So these conditions will result in both fe_ and fg_ flags 8155 * being set. 8156 * - Test if FRB is Zero 8157 * - Test if FRB is an Infinity 8158 */ 8159 8160 /* 8161 * Test if FRB holds a denormalized value. A denormalized value is one where 8162 * the exp is 0 and the fraction is non-zero. 8163 */ 8164 if (sp) { 8165 IRTemp frac_part = newTemp(Ity_I32); 8166 assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) ); 8167 frbDenorm 8168 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 8169 binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) ); 8170 } else { 8171 IRExpr * hi32, * low32, * fraction_is_nonzero; 8172 IRTemp frac_part = newTemp(Ity_I64); 8173 8174 assign( frac_part, FP_FRAC_PART(frB_Int) ); 8175 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 8176 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 8177 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 8178 mkU32( 0 ) ); 8179 frbDenorm 8180 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ), 8181 fraction_is_nonzero ); 8182 } 8183 ////////////////// fg_flag tests END ////////////////////// 8184 8185 ///////////////////////// 8186 fe_flag = mkOR1( mkexpr( frbZero_tmp ), 8187 mkOR1( frbNaN, 8188 mkOR1( mkexpr( frbInf_tmp ), 8189 mkOR1( frBNeg, eb_LTE ) ) ) ); 8190 8191 fe_flag = unop(Iop_1Uto32, fe_flag); 8192 8193 fg_flag = mkOR1( mkexpr( frbZero_tmp ), 8194 mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) ); 8195 fg_flag = unop(Iop_1Uto32, fg_flag); 8196 assign (*fg_flag_tmp, fg_flag); 8197 assign (*fe_flag_tmp, fe_flag); 8198 } 8199 /* 8200 * fe_flag is set to 1 if any of the following conditions occurs: 8201 * - The double-precision floating-point operand in register FRA is a NaN or an 8202 * Infinity. 8203 * - The double-precision floating-point operand in register FRB is a Zero, a 8204 * NaN, or an Infinity. 8205 * - e_b is less than or equal to -1022. 8206 * - e_b is greater than or equal to 1021. 8207 * - The double-precision floating-point operand in register FRA is not a zero 8208 * and the difference, e_a - e_b, is greater than or equal to 1023. 8209 * - The double-precision floating-point operand in register FRA is not a zero 8210 * and the difference, e_a - e_b, is less than or equal to -1021. 8211 * - The double-precision floating-point operand in register FRA is not a zero 8212 * and e_a is less than or equal to -970 8213 * Otherwise fe_flag is set to 0. 8214 * 8215 * fg_flag is set to 1 if either of the following conditions occurs. 8216 * - The double-precision floating-point operand in register FRA is an Infinity. 8217 * - The double-precision floating-point operand in register FRB is a Zero, an 8218 * Infinity, or a denormalized value. 8219 * Otherwise fg_flag is set to 0. 8220 * 8221 */ 8222 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp) 8223 { 8224 // The following temps are for holding intermediate results 8225 IRTemp e_a = newTemp(Ity_I32); 8226 IRTemp e_b = newTemp(Ity_I32); 8227 IRTemp frA_exp_shR = newTemp(Ity_I32); 8228 IRTemp frB_exp_shR = newTemp(Ity_I32); 8229 8230 UInt bias = sp? 127 : 1023; 8231 *fe_flag_tmp = newTemp(Ity_I32); 8232 *fg_flag_tmp = newTemp(Ity_I32); 8233 8234 /* The following variables hold boolean results from tests 8235 * that are OR'ed together for setting the fe_ and fg_ flags. 8236 * For some cases, the booleans are used more than once, so 8237 * I make those IRTemp's instead of IRExpr's. 8238 */ 8239 IRExpr * fraNaN, * frbNaN, * frbDenorm; 8240 IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE; 8241 IRTemp fraInf_tmp = newTemp(Ity_I1); 8242 IRTemp frbZero_tmp = newTemp(Ity_I1); 8243 IRTemp frbInf_tmp = newTemp(Ity_I1); 8244 IRTemp fraNotZero_tmp = newTemp(Ity_I1); 8245 8246 /* The following are the flags that are set by OR'ing the results of 8247 * all the tests done for tdiv. These flags are the input to the specified CR. 8248 */ 8249 IRExpr * fe_flag, * fg_flag; 8250 8251 // Create temps that will be used throughout the following tests. 8252 assign( frA_exp_shR, fp_exp_part( frA_int, sp ) ); 8253 assign( frB_exp_shR, fp_exp_part( frB_int, sp ) ); 8254 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */ 8255 assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) )); 8256 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) )); 8257 8258 8259 ////////////////// fe_flag tests BEGIN ////////////////////// 8260 /* We first do all tests that may result in setting fe_flag to '1'. */ 8261 8262 /* 8263 * Test if the double-precision floating-point operand in register FRA is 8264 * a NaN: 8265 */ 8266 fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int); 8267 /* 8268 * Test if the double-precision floating-point operand in register FRA is 8269 * an Infinity. 8270 */ 8271 assign(fraInf_tmp, is_Inf(frA_int, sp)); 8272 8273 /* 8274 * Test if the double-precision floating-point operand in register FRB is 8275 * a NaN: 8276 */ 8277 frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int); 8278 /* 8279 * Test if the double-precision floating-point operand in register FRB is 8280 * an Infinity. 8281 */ 8282 assign( frbInf_tmp, is_Inf(frB_int, sp) ); 8283 /* 8284 * Test if the double-precision floating-point operand in register FRB is 8285 * a Zero. 8286 */ 8287 assign( frbZero_tmp, is_Zero(frB_int, sp) ); 8288 8289 /* 8290 * Test if e_b <= -1022 for double precision; 8291 * or e_b <= -126 for single precision 8292 */ 8293 { 8294 UInt test_value = sp ? 0xffffff82 : 0xfffffc02; 8295 eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value)); 8296 } 8297 8298 /* 8299 * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision; 8300 * or e_b >= -125 (125 < e_b) for single precision 8301 */ 8302 { 8303 Int test_value = sp ? 125 : 1021; 8304 eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b)); 8305 } 8306 8307 /* 8308 * Test if FRA != Zero and (e_a - e_b) >= bias 8309 */ 8310 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) ); 8311 ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ), 8312 binop( Iop_CmpLT32S, mkU32( bias ), 8313 binop( Iop_Sub32, mkexpr( e_a ), 8314 mkexpr( e_b ) ) ) ); 8315 8316 /* 8317 * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)] 8318 */ 8319 { 8320 UInt test_value = sp ? 0xffffff83 : 0xfffffc03; 8321 8322 ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ), 8323 binop( Iop_CmpLE32S, 8324 binop( Iop_Sub32, 8325 mkexpr( e_a ), 8326 mkexpr( e_b ) ), 8327 mkU32( test_value ) ) ); 8328 } 8329 8330 /* 8331 * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)] 8332 */ 8333 { 8334 UInt test_value = 0xfffffc36; //Int test_value = -970; 8335 8336 ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S, 8337 mkexpr( e_a ), 8338 mkU32( test_value ) ) ); 8339 } 8340 ////////////////// fe_flag tests END ////////////////////// 8341 8342 ////////////////// fg_flag tests BEGIN ////////////////////// 8343 /* 8344 * The following tests were already performed above in the fe_flag 8345 * tests. So these conditions will result in both fe_ and fg_ flags 8346 * being set. 8347 * - Test if FRA is an Infinity 8348 * - Test if FRB ix Zero 8349 * - Test if FRB is an Infinity 8350 */ 8351 8352 /* 8353 * Test if FRB holds a denormalized value. A denormalized value is one where 8354 * the exp is 0 and the fraction is non-zero. 8355 */ 8356 { 8357 IRExpr * fraction_is_nonzero; 8358 8359 if (sp) { 8360 fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int), 8361 mkU32( 0 ) ); 8362 } else { 8363 IRExpr * hi32, * low32; 8364 IRTemp frac_part = newTemp(Ity_I64); 8365 assign( frac_part, FP_FRAC_PART(frB_int) ); 8366 8367 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) ); 8368 low32 = unop( Iop_64to32, mkexpr( frac_part ) ); 8369 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ), 8370 mkU32( 0 ) ); 8371 } 8372 frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), 8373 mkU32( 0x0 ) ), fraction_is_nonzero ); 8374 8375 } 8376 ////////////////// fg_flag tests END ////////////////////// 8377 8378 fe_flag 8379 = mkOR1( 8380 fraNaN, 8381 mkOR1( 8382 mkexpr( fraInf_tmp ), 8383 mkOR1( 8384 mkexpr( frbZero_tmp ), 8385 mkOR1( 8386 frbNaN, 8387 mkOR1( 8388 mkexpr( frbInf_tmp ), 8389 mkOR1( eb_LTE, 8390 mkOR1( eb_GTE, 8391 mkOR1( ea_eb_GTE, 8392 mkOR1( ea_eb_LTE, 8393 ea_LTE ) ) ) ) ) ) ) ) ); 8394 8395 fe_flag = unop(Iop_1Uto32, fe_flag); 8396 8397 fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ), 8398 mkOR1( mkexpr( frbInf_tmp ), 8399 frbDenorm ) ) ); 8400 fg_flag = unop(Iop_1Uto32, fg_flag); 8401 assign(*fe_flag_tmp, fe_flag); 8402 assign(*fg_flag_tmp, fg_flag); 8403 } 8404 8405 /* See description for _do_fp_tdiv() above. */ 8406 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int) 8407 { 8408 IRTemp fe_flag, fg_flag; 8409 ///////////////////////// 8410 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 8411 * where fl_flag == 1 on ppc64. 8412 */ 8413 IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE)); 8414 fe_flag = fg_flag = IRTemp_INVALID; 8415 _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag); 8416 return binop( Iop_Or32, 8417 binop( Iop_Or32, 8418 binop( Iop_Shl32, fl_flag, mkU8( 3 ) ), 8419 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 8420 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ); 8421 } 8422 8423 static Bool dis_fp_tests ( UInt theInstr ) 8424 { 8425 UChar opc1 = ifieldOPC(theInstr); 8426 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 8427 UChar frB_addr = ifieldRegB(theInstr); 8428 UChar b0 = ifieldBIT0(theInstr); 8429 UInt opc2 = ifieldOPClo10(theInstr); 8430 IRTemp frB_I64 = newTemp(Ity_I64); 8431 8432 if (opc1 != 0x3F || b0 != 0 ){ 8433 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 8434 return False; 8435 } 8436 assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) ); 8437 8438 switch (opc2) { 8439 case 0x080: // ftdiv 8440 { 8441 UChar frA_addr = ifieldRegA(theInstr); 8442 IRTemp frA_I64 = newTemp(Ity_I64); 8443 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 8444 if (b21to22 != 0 ) { 8445 vex_printf("dis_fp_tests(ppc)(ftdiv)\n"); 8446 return False; 8447 } 8448 8449 assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) ); 8450 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 8451 8452 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8453 break; 8454 } 8455 case 0x0A0: // ftsqrt 8456 { 8457 IRTemp flags = newTemp(Ity_I32); 8458 IRTemp fe_flag, fg_flag; 8459 fe_flag = fg_flag = IRTemp_INVALID; 8460 UChar b18to22 = toUChar( IFIELD( theInstr, 18, 5 ) ); 8461 if ( b18to22 != 0) { 8462 vex_printf("dis_fp_tests(ppc)(ftsqrt)\n"); 8463 return False; 8464 } 8465 DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr); 8466 do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag); 8467 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 8468 * where fl_flag == 1 on ppc64. 8469 */ 8470 assign( flags, 8471 binop( Iop_Or32, 8472 binop( Iop_Or32, mkU32( 8 ), // fl_flag 8473 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 8474 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 8475 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 8476 break; 8477 } 8478 8479 default: 8480 vex_printf("dis_fp_tests(ppc)(opc2)\n"); 8481 return False; 8482 8483 } 8484 return True; 8485 } 8486 8487 /* 8488 Floating Point Compare Instructions 8489 */ 8490 static Bool dis_fp_cmp ( UInt theInstr ) 8491 { 8492 /* X-Form */ 8493 UChar opc1 = ifieldOPC(theInstr); 8494 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 8495 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 8496 UChar frA_addr = ifieldRegA(theInstr); 8497 UChar frB_addr = ifieldRegB(theInstr); 8498 UInt opc2 = ifieldOPClo10(theInstr); 8499 UChar b0 = ifieldBIT0(theInstr); 8500 8501 IRTemp ccIR = newTemp(Ity_I32); 8502 IRTemp ccPPC32 = newTemp(Ity_I32); 8503 8504 IRTemp frA = newTemp(Ity_F64); 8505 IRTemp frB = newTemp(Ity_F64); 8506 8507 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) { 8508 vex_printf("dis_fp_cmp(ppc)(instr)\n"); 8509 return False; 8510 } 8511 8512 assign( frA, getFReg(frA_addr)); 8513 assign( frB, getFReg(frB_addr)); 8514 8515 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) ); 8516 8517 /* Map compare result from IR to PPC32 */ 8518 /* 8519 FP cmp result | PPC | IR 8520 -------------------------- 8521 UN | 0x1 | 0x45 8522 EQ | 0x2 | 0x40 8523 GT | 0x4 | 0x00 8524 LT | 0x8 | 0x01 8525 */ 8526 8527 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2) 8528 // | ((ccIR ^ (ccIR>>6)) & 1) 8529 assign( 8530 ccPPC32, 8531 binop( 8532 Iop_Shl32, 8533 mkU32(1), 8534 unop( 8535 Iop_32to8, 8536 binop( 8537 Iop_Or32, 8538 binop( 8539 Iop_And32, 8540 unop( 8541 Iop_Not32, 8542 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5)) 8543 ), 8544 mkU32(2) 8545 ), 8546 binop( 8547 Iop_And32, 8548 binop( 8549 Iop_Xor32, 8550 mkexpr(ccIR), 8551 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6)) 8552 ), 8553 mkU32(1) 8554 ) 8555 ) 8556 ) 8557 ) 8558 ); 8559 8560 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 8561 8562 /* CAB: TODO?: Support writing cc to FPSCR->FPCC ? 8563 putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 ); 8564 */ 8565 // XXX XXX XXX FIXME 8566 // Also write the result into FPRF (it's not entirely clear how) 8567 8568 /* Note: Differences between fcmpu and fcmpo are only in exception 8569 flag settings, which aren't supported anyway. */ 8570 switch (opc2) { 8571 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403) 8572 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8573 break; 8574 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402) 8575 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr); 8576 break; 8577 default: 8578 vex_printf("dis_fp_cmp(ppc)(opc2)\n"); 8579 return False; 8580 } 8581 return True; 8582 } 8583 8584 8585 8586 /* 8587 Floating Point Rounding/Conversion Instructions 8588 */ 8589 static Bool dis_fp_round ( UInt theInstr ) 8590 { 8591 /* X-Form */ 8592 UChar opc1 = ifieldOPC(theInstr); 8593 UChar b16to20 = ifieldRegA(theInstr); 8594 UChar frD_addr = ifieldRegDS(theInstr); 8595 UChar frB_addr = ifieldRegB(theInstr); 8596 UInt opc2 = ifieldOPClo10(theInstr); 8597 UChar flag_rC = ifieldBIT0(theInstr); 8598 8599 IRTemp frD = newTemp(Ity_F64); 8600 IRTemp frB = newTemp(Ity_F64); 8601 IRTemp r_tmp32 = newTemp(Ity_I32); 8602 IRTemp r_tmp64 = newTemp(Ity_I64); 8603 IRExpr* rm = get_IR_roundingmode(); 8604 8605 /* By default, we will examine the results of the operation and set 8606 fpscr[FPRF] accordingly. */ 8607 Bool set_FPRF = True; 8608 8609 /* By default, if flag_RC is set, we will clear cr1 after the 8610 operation. In reality we should set cr1 to indicate the 8611 exception status of the operation, but since we're not 8612 simulating exceptions, the exception status will appear to be 8613 zero. Hence cr1 should be cleared if this is a . form insn. */ 8614 Bool clear_CR1 = True; 8615 if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) { 8616 vex_printf("dis_fp_round(ppc)(instr)\n"); 8617 return False; 8618 } 8619 8620 assign( frB, getFReg(frB_addr)); 8621 if (opc1 == 0x3B) { 8622 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because 8623 * they're very similar to the other instructions handled here, but have 8624 * a different primary opcode. 8625 */ 8626 switch (opc2) { 8627 case 0x34E: // fcfids (Float convert from signed DWord to single precision) 8628 DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8629 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8630 assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm, 8631 mkexpr( r_tmp64 ) ) ) ); 8632 goto putFR; 8633 8634 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision) 8635 DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8636 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8637 assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) ); 8638 goto putFR; 8639 } 8640 } 8641 8642 8643 switch (opc2) { 8644 case 0x00C: // frsp (Float Round to Single, PPC32 p423) 8645 DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8646 assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) )); 8647 break; 8648 8649 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404) 8650 DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8651 assign( r_tmp32, 8652 binop(Iop_F64toI32S, rm, mkexpr(frB)) ); 8653 assign( frD, unop( Iop_ReinterpI64asF64, 8654 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8655 /* FPRF is undefined after fctiw. Leave unchanged. */ 8656 set_FPRF = False; 8657 break; 8658 8659 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405) 8660 DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8661 assign( r_tmp32, 8662 binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) )); 8663 assign( frD, unop( Iop_ReinterpI64asF64, 8664 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8665 /* FPRF is undefined after fctiwz. Leave unchanged. */ 8666 set_FPRF = False; 8667 break; 8668 8669 case 0x08F: case 0x08E: // fctiwu[z] 8670 DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "", 8671 flag_rC ? ".":"", frD_addr, frB_addr); 8672 assign( r_tmp32, 8673 binop( Iop_F64toI32U, 8674 opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm, 8675 mkexpr( frB ) ) ); 8676 assign( frD, unop( Iop_ReinterpI64asF64, 8677 unop( Iop_32Uto64, mkexpr(r_tmp32)))); 8678 /* FPRF is undefined after fctiwz. Leave unchanged. */ 8679 set_FPRF = False; 8680 break; 8681 8682 8683 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437) 8684 DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8685 assign( r_tmp64, 8686 binop(Iop_F64toI64S, rm, mkexpr(frB)) ); 8687 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8688 /* FPRF is undefined after fctid. Leave unchanged. */ 8689 set_FPRF = False; 8690 break; 8691 8692 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437) 8693 DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8694 assign( r_tmp64, 8695 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 8696 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8697 /* FPRF is undefined after fctidz. Leave unchanged. */ 8698 set_FPRF = False; 8699 break; 8700 8701 case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero]) 8702 { 8703 DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z", 8704 flag_rC ? ".":"", frD_addr, frB_addr); 8705 assign( r_tmp64, 8706 binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) ); 8707 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) ); 8708 /* FPRF is undefined after fctidz. Leave unchanged. */ 8709 set_FPRF = False; 8710 break; 8711 } 8712 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434) 8713 DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8714 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8715 assign( frD, 8716 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) ); 8717 break; 8718 8719 case 0x3CE: // fcfidu (Float convert from unsigned DWord) 8720 DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8721 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) ); 8722 assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) ); 8723 break; 8724 8725 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim 8726 switch(opc2) { 8727 case 0x188: // frin (Floating Round to Integer Nearest) 8728 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8729 assign( r_tmp64, 8730 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) ); 8731 break; 8732 case 0x1A8: // friz (Floating Round to Integer Toward Zero) 8733 DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8734 assign( r_tmp64, 8735 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) ); 8736 break; 8737 case 0x1C8: // frip (Floating Round to Integer Plus) 8738 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8739 assign( r_tmp64, 8740 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) ); 8741 break; 8742 case 0x1E8: // frim (Floating Round to Integer Minus) 8743 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8744 assign( r_tmp64, 8745 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) ); 8746 break; 8747 } 8748 8749 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 8750 /* F64 has only log10(2**52) significant digits anyway */ 8751 /* need to preserve sign of zero */ 8752 /* frD = (fabs(frB) > 9e18) ? frB : 8753 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */ 8754 assign(frD, IRExpr_ITE( 8755 binop(Iop_CmpNE8, 8756 unop(Iop_32to8, 8757 binop(Iop_CmpF64, 8758 IRExpr_Const(IRConst_F64(9e18)), 8759 unop(Iop_AbsF64, mkexpr(frB)))), 8760 mkU8(0)), 8761 mkexpr(frB), 8762 IRExpr_ITE( 8763 binop(Iop_CmpNE32, 8764 binop(Iop_Shr32, 8765 unop(Iop_64HIto32, 8766 unop(Iop_ReinterpF64asI64, 8767 mkexpr(frB))), 8768 mkU8(31)), 8769 mkU32(0)), 8770 unop(Iop_NegF64, 8771 unop( Iop_AbsF64, 8772 binop(Iop_I64StoF64, mkU32(0), 8773 mkexpr(r_tmp64)) )), 8774 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ) 8775 ) 8776 )); 8777 break; 8778 8779 default: 8780 vex_printf("dis_fp_round(ppc)(opc2)\n"); 8781 return False; 8782 } 8783 putFR: 8784 putFReg( frD_addr, mkexpr(frD) ); 8785 8786 if (set_FPRF) { 8787 // XXX XXX XXX FIXME 8788 // set FPRF from frD 8789 } 8790 8791 if (flag_rC && clear_CR1) { 8792 putCR321( 1, mkU8(0) ); 8793 putCR0( 1, mkU8(0) ); 8794 } 8795 8796 return True; 8797 } 8798 8799 /* 8800 Floating Point Pair Instructions 8801 */ 8802 static Bool dis_fp_pair ( UInt theInstr ) 8803 { 8804 /* X-Form/DS-Form */ 8805 UChar opc1 = ifieldOPC(theInstr); 8806 UChar frT_hi_addr = ifieldRegDS(theInstr); 8807 UChar frT_lo_addr = frT_hi_addr + 1; 8808 UChar rA_addr = ifieldRegA(theInstr); 8809 UChar rB_addr = ifieldRegB(theInstr); 8810 UInt uimm16 = ifieldUIMM16(theInstr); 8811 Int simm16 = extend_s_16to32(uimm16); 8812 UInt opc2 = ifieldOPClo10(theInstr); 8813 IRType ty = mode64 ? Ity_I64 : Ity_I32; 8814 IRTemp EA_hi = newTemp(ty); 8815 IRTemp EA_lo = newTemp(ty); 8816 IRTemp frT_hi = newTemp(Ity_F64); 8817 IRTemp frT_lo = newTemp(Ity_F64); 8818 UChar b0 = ifieldBIT0(theInstr); 8819 Bool is_load = 0; 8820 8821 if ((frT_hi_addr %2) != 0) { 8822 vex_printf("dis_fp_pair(ppc) : odd frT register\n"); 8823 return False; 8824 } 8825 8826 switch (opc1) { 8827 case 0x1F: // register offset 8828 switch(opc2) { 8829 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125) 8830 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 8831 is_load = 1; 8832 break; 8833 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125) 8834 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr); 8835 break; 8836 default: 8837 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n"); 8838 return False; 8839 } 8840 8841 if (b0 != 0) { 8842 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n"); 8843 return False; 8844 } 8845 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) ); 8846 break; 8847 case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125) 8848 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 8849 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 8850 is_load = 1; 8851 break; 8852 case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125) 8853 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr); 8854 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) ); 8855 break; 8856 default: // immediate offset 8857 vex_printf("dis_fp_pair(ppc)(instr)\n"); 8858 return False; 8859 } 8860 8861 if (mode64) 8862 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) ); 8863 else 8864 assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) ); 8865 8866 assign( frT_hi, getFReg(frT_hi_addr) ); 8867 assign( frT_lo, getFReg(frT_lo_addr) ); 8868 8869 if (is_load) { 8870 putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) ); 8871 putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) ); 8872 } else { 8873 storeBE( mkexpr(EA_hi), mkexpr(frT_hi) ); 8874 storeBE( mkexpr(EA_lo), mkexpr(frT_lo) ); 8875 } 8876 8877 return True; 8878 } 8879 8880 8881 /* 8882 Floating Point Merge Instructions 8883 */ 8884 static Bool dis_fp_merge ( UInt theInstr ) 8885 { 8886 /* X-Form */ 8887 UInt opc2 = ifieldOPClo10(theInstr); 8888 UChar frD_addr = ifieldRegDS(theInstr); 8889 UChar frA_addr = ifieldRegA(theInstr); 8890 UChar frB_addr = ifieldRegB(theInstr); 8891 8892 IRTemp frD = newTemp(Ity_F64); 8893 IRTemp frA = newTemp(Ity_F64); 8894 IRTemp frB = newTemp(Ity_F64); 8895 8896 assign( frA, getFReg(frA_addr)); 8897 assign( frB, getFReg(frB_addr)); 8898 8899 switch (opc2) { 8900 case 0x3c6: // fmrgew floating merge even word 8901 DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 8902 8903 assign( frD, unop( Iop_ReinterpI64asF64, 8904 binop( Iop_32HLto64, 8905 unop( Iop_64HIto32, 8906 unop( Iop_ReinterpF64asI64, 8907 mkexpr(frA) ) ), 8908 unop( Iop_64HIto32, 8909 unop( Iop_ReinterpF64asI64, 8910 mkexpr(frB) ) ) ) ) ); 8911 break; 8912 8913 case 0x346: // fmrgow floating merge odd word 8914 DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr); 8915 8916 assign( frD, unop( Iop_ReinterpI64asF64, 8917 binop( Iop_32HLto64, 8918 unop( Iop_64to32, 8919 unop( Iop_ReinterpF64asI64, 8920 mkexpr(frA) ) ), 8921 unop( Iop_64to32, 8922 unop( Iop_ReinterpF64asI64, 8923 mkexpr(frB) ) ) ) ) ); 8924 break; 8925 8926 default: 8927 vex_printf("dis_fp_merge(ppc)(opc2)\n"); 8928 return False; 8929 } 8930 8931 putFReg( frD_addr, mkexpr(frD) ); 8932 return True; 8933 } 8934 8935 /* 8936 Floating Point Move Instructions 8937 */ 8938 static Bool dis_fp_move ( UInt theInstr ) 8939 { 8940 /* X-Form */ 8941 UChar opc1 = ifieldOPC(theInstr); 8942 UChar frD_addr = ifieldRegDS(theInstr); 8943 UChar frA_addr = ifieldRegA(theInstr); 8944 UChar frB_addr = ifieldRegB(theInstr); 8945 UInt opc2 = ifieldOPClo10(theInstr); 8946 UChar flag_rC = ifieldBIT0(theInstr); 8947 8948 IRTemp frD = newTemp(Ity_F64); 8949 IRTemp frB = newTemp(Ity_F64); 8950 IRTemp itmpB = newTemp(Ity_F64); 8951 IRTemp frA; 8952 IRTemp signA; 8953 IRTemp hiD; 8954 8955 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) { 8956 vex_printf("dis_fp_move(ppc)(instr)\n"); 8957 return False; 8958 } 8959 8960 assign( frB, getFReg(frB_addr)); 8961 8962 switch (opc2) { 8963 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126) 8964 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr, 8965 frB_addr); 8966 signA = newTemp(Ity_I32); 8967 hiD = newTemp(Ity_I32); 8968 itmpB = newTemp(Ity_I64); 8969 frA = newTemp(Ity_F64); 8970 assign( frA, getFReg(frA_addr) ); 8971 8972 /* get A's sign bit */ 8973 assign(signA, binop(Iop_And32, 8974 unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64, 8975 mkexpr(frA))), 8976 mkU32(0x80000000)) ); 8977 8978 assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) ); 8979 8980 /* mask off B's sign bit and or in A's sign bit */ 8981 assign(hiD, binop(Iop_Or32, 8982 binop(Iop_And32, 8983 unop(Iop_64HIto32, 8984 mkexpr(itmpB)), /* frB's high 32 bits */ 8985 mkU32(0x7fffffff)), 8986 mkexpr(signA)) ); 8987 8988 /* combine hiD/loB into frD */ 8989 assign( frD, unop(Iop_ReinterpI64asF64, 8990 binop(Iop_32HLto64, 8991 mkexpr(hiD), 8992 unop(Iop_64to32, 8993 mkexpr(itmpB)))) ); /* frB's low 32 bits */ 8994 break; 8995 8996 case 0x028: // fneg (Floating Negate, PPC32 p416) 8997 DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 8998 assign( frD, unop( Iop_NegF64, mkexpr(frB) )); 8999 break; 9000 9001 case 0x048: // fmr (Floating Move Register, PPC32 p410) 9002 DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9003 assign( frD, mkexpr(frB) ); 9004 break; 9005 9006 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415) 9007 DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9008 assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) ))); 9009 break; 9010 9011 case 0x108: // fabs (Floating Absolute Value, PPC32 p399) 9012 DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr); 9013 assign( frD, unop( Iop_AbsF64, mkexpr(frB) )); 9014 break; 9015 9016 default: 9017 vex_printf("dis_fp_move(ppc)(opc2)\n"); 9018 return False; 9019 } 9020 9021 putFReg( frD_addr, mkexpr(frD) ); 9022 9023 /* None of these change FPRF. cr1 is set in the usual way though, 9024 if flag_rC is set. */ 9025 9026 if (flag_rC) { 9027 putCR321( 1, mkU8(0) ); 9028 putCR0( 1, mkU8(0) ); 9029 } 9030 9031 return True; 9032 } 9033 9034 9035 9036 /* 9037 Floating Point Status/Control Register Instructions 9038 */ 9039 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level ) 9040 { 9041 /* Many forms - see each switch case */ 9042 UChar opc1 = ifieldOPC(theInstr); 9043 UInt opc2 = ifieldOPClo10(theInstr); 9044 UChar flag_rC = ifieldBIT0(theInstr); 9045 9046 if (opc1 != 0x3F) { 9047 vex_printf("dis_fp_scr(ppc)(instr)\n"); 9048 return False; 9049 } 9050 9051 switch (opc2) { 9052 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479) 9053 // Bit crbD of the FPSCR is set. 9054 UChar crbD = ifieldRegDS(theInstr); 9055 UInt b11to20 = IFIELD(theInstr, 11, 10); 9056 9057 if (b11to20 != 0) { 9058 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n"); 9059 return False; 9060 } 9061 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD); 9062 putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ), 9063 1ULL << ( 31 - crbD ) ); 9064 break; 9065 } 9066 9067 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465) 9068 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 9069 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) ); 9070 UChar crfS = toUChar( IFIELD( theInstr, 18, 3 ) ); 9071 UChar b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) ); 9072 IRTemp tmp = newTemp(Ity_I32); 9073 IRExpr* fpscr_all; 9074 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) { 9075 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n"); 9076 return False; 9077 } 9078 DIP("mcrfs crf%d,crf%d\n", crfD, crfS); 9079 vassert(crfD < 8); 9080 vassert(crfS < 8); 9081 fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 9082 assign( tmp, binop(Iop_And32, 9083 binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))), 9084 mkU32(0xF)) ); 9085 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD ); 9086 break; 9087 } 9088 9089 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478) 9090 // Bit crbD of the FPSCR is cleared. 9091 UChar crbD = ifieldRegDS(theInstr); 9092 UInt b11to20 = IFIELD(theInstr, 11, 10); 9093 9094 if (b11to20 != 0) { 9095 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n"); 9096 return False; 9097 } 9098 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD); 9099 putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) ); 9100 break; 9101 } 9102 9103 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481) 9104 UInt crfD = IFIELD( theInstr, 23, 3 ); 9105 UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) ); 9106 UChar IMM = toUChar( IFIELD( theInstr, 12, 4 ) ); 9107 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); 9108 UChar Wbit; 9109 9110 if (b16to22 != 0 || b11 != 0) { 9111 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n"); 9112 return False; 9113 } 9114 DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM); 9115 if (GX_level) { 9116 /* This implies that Decimal Floating Point is supported, and the 9117 * FPSCR must be managed as a 64-bit register. 9118 */ 9119 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 9120 } else { 9121 Wbit = 0; 9122 } 9123 crfD = crfD + (8 * (1 - Wbit) ); 9124 putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD ); 9125 break; 9126 } 9127 9128 case 0x247: { // mffs (Move from FPSCR, PPC32 p468) 9129 UChar frD_addr = ifieldRegDS(theInstr); 9130 UInt b11to20 = IFIELD(theInstr, 11, 10); 9131 IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ); 9132 IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR, 9133 MASK_FPSCR_DRN ); 9134 9135 if (b11to20 != 0) { 9136 vex_printf("dis_fp_scr(ppc)(instr,mffs)\n"); 9137 return False; 9138 } 9139 DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr); 9140 putFReg( frD_addr, 9141 unop( Iop_ReinterpI64asF64, 9142 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) ); 9143 break; 9144 } 9145 9146 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480) 9147 UChar b25 = toUChar( IFIELD(theInstr, 25, 1) ); 9148 UChar FM = toUChar( IFIELD(theInstr, 17, 8) ); 9149 UChar frB_addr = ifieldRegB(theInstr); 9150 IRTemp frB = newTemp(Ity_F64); 9151 IRTemp rB_64 = newTemp( Ity_I64 ); 9152 Int i; 9153 ULong mask; 9154 UChar Wbit; 9155 #define BFP_MASK_SEED 0x3000000000000000ULL 9156 #define DFP_MASK_SEED 0x7000000000000000ULL 9157 9158 if (GX_level) { 9159 /* This implies that Decimal Floating Point is supported, and the 9160 * FPSCR must be managed as a 64-bit register. 9161 */ 9162 Wbit = toUChar( IFIELD(theInstr, 16, 1) ); 9163 } else { 9164 Wbit = 0; 9165 } 9166 9167 if (b25 == 1) { 9168 /* new 64 bit move variant for power 6. If L field (bit 25) is 9169 * a one do a full 64 bit move. Note, the FPSCR is not really 9170 * properly modeled. This instruciton only changes the value of 9171 * the rounding mode. The HW exception bits do not get set in 9172 * the simulator. 1/12/09 9173 */ 9174 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr); 9175 mask = 0xFF; 9176 9177 } else { 9178 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr); 9179 // Build 32bit mask from FM: 9180 mask = 0; 9181 for (i=0; i<8; i++) { 9182 if ((FM & (1<<(7-i))) == 1) { 9183 /* FPSCR field k is set to the contents of the corresponding 9184 * field of register FRB, where k = i+8x(1-W). In the Power 9185 * ISA, register field numbering is from left to right, so field 9186 * 15 is the least significant field in a 64-bit register. To 9187 * generate the mask, we set all the appropriate rounding mode 9188 * bits in the highest order nibble (field 0) and shift right 9189 * 'k x nibble length'. 9190 */ 9191 if (Wbit) 9192 mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 9193 else 9194 mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) ); 9195 } 9196 } 9197 } 9198 assign( frB, getFReg(frB_addr)); 9199 assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 9200 putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask ); 9201 break; 9202 } 9203 9204 default: 9205 vex_printf("dis_fp_scr(ppc)(opc2)\n"); 9206 return False; 9207 } 9208 return True; 9209 } 9210 9211 /*------------------------------------------------------------*/ 9212 /*--- Decimal Floating Point (DFP) Helper functions ---*/ 9213 /*------------------------------------------------------------*/ 9214 #define DFP_LONG 1 9215 #define DFP_EXTND 2 9216 #define DFP_LONG_BIAS 398 9217 #define DFP_LONG_ENCODED_FIELD_MASK 0x1F00 9218 #define DFP_EXTND_BIAS 6176 9219 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000 9220 #define DFP_LONG_EXP_MSK 0XFF 9221 #define DFP_EXTND_EXP_MSK 0XFFF 9222 9223 #define DFP_G_FIELD_LONG_MASK 0x7FFC0000 // upper 32-bits only 9224 #define DFP_LONG_GFIELD_RT_SHIFT (63 - 13 - 32) // adj for upper 32-bits 9225 #define DFP_G_FIELD_EXTND_MASK 0x7FFFC000 // upper 32-bits only 9226 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits 9227 #define DFP_T_FIELD_LONG_MASK 0x3FFFF // mask for upper 32-bits 9228 #define DFP_T_FIELD_EXTND_MASK 0x03FFFF // mask for upper 32-bits 9229 #define DFP_LONG_EXP_MAX 369 // biased max 9230 #define DFP_LONG_EXP_MIN 0 // biased min 9231 #define DFP_EXTND_EXP_MAX 6111 // biased max 9232 #define DFP_EXTND_EXP_MIN 0 // biased min 9233 #define DFP_LONG_MAX_SIG_DIGITS 16 9234 #define DFP_EXTND_MAX_SIG_DIGITS 34 9235 #define MAX_DIGITS_IN_STRING 8 9236 9237 9238 #define AND(x, y) binop( Iop_And32, x, y ) 9239 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) ) 9240 #define OR(x, y) binop( Iop_Or32, x, y ) 9241 #define OR3(x, y, z) OR( x, OR( y, z ) ) 9242 #define OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) ) 9243 #define NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1, mkexpr( x ) ) ) ) 9244 9245 #define SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) ) 9246 #define SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) ) 9247 9248 #define BITS5(_b4,_b3,_b2,_b1,_b0) \ 9249 (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \ 9250 ((_b1) << 1) | ((_b0) << 0)) 9251 9252 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 ) 9253 { 9254 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 9255 IRTemp lmd_8_mask = newTemp( Ity_I32 ); 9256 IRTemp lmd_9_mask = newTemp( Ity_I32 ); 9257 IRTemp lmexp_00_mask = newTemp( Ity_I32 ); 9258 IRTemp lmexp_01_mask = newTemp( Ity_I32 ); 9259 IRTemp lmexp_10_mask = newTemp( Ity_I32 ); 9260 IRTemp lmd_07_val = newTemp( Ity_I32 ); 9261 IRTemp lmd_8_val = newTemp( Ity_I32 ); 9262 IRTemp lmd_9_val = newTemp( Ity_I32 ); 9263 9264 /* The encodig is as follows: 9265 * lmd - left most digit 9266 * lme - left most 2-bits of the exponent 9267 * 9268 * lmd 9269 * 0 - 7 (lmexp << 3) | lmd 9270 * 8 0b11000 (24 decimal) if lme=0b00; 9271 * 0b11010 (26 decimal) if lme=0b01; 9272 * 0b11100 (28 decimal) if lme=0b10; 9273 * 9 0b11001 (25 decimal) if lme=0b00; 9274 * 0b11011 (27 decimal) if lme=0b01; 9275 * 0b11101 (29 decimal) if lme=0b10; 9276 */ 9277 9278 /* Generate the masks for each condition */ 9279 assign( lmd_07_mask, 9280 unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) ); 9281 assign( lmd_8_mask, 9282 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) ); 9283 assign( lmd_9_mask, 9284 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) ); 9285 assign( lmexp_00_mask, 9286 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) ); 9287 assign( lmexp_01_mask, 9288 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) ); 9289 assign( lmexp_10_mask, 9290 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) ); 9291 9292 /* Generate the values for each LMD condition, assuming the condition 9293 * is TRUE. 9294 */ 9295 assign( lmd_07_val, 9296 binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) ); 9297 assign( lmd_8_val, 9298 binop( Iop_Or32, 9299 binop( Iop_Or32, 9300 binop( Iop_And32, 9301 mkexpr( lmexp_00_mask ), 9302 mkU32( 24 ) ), 9303 binop( Iop_And32, 9304 mkexpr( lmexp_01_mask ), 9305 mkU32( 26 ) ) ), 9306 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) ); 9307 assign( lmd_9_val, 9308 binop( Iop_Or32, 9309 binop( Iop_Or32, 9310 binop( Iop_And32, 9311 mkexpr( lmexp_00_mask ), 9312 mkU32( 25 ) ), 9313 binop( Iop_And32, 9314 mkexpr( lmexp_01_mask ), 9315 mkU32( 27 ) ) ), 9316 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) ); 9317 9318 /* generate the result from the possible LMD values */ 9319 return binop( Iop_Or32, 9320 binop( Iop_Or32, 9321 binop( Iop_And32, 9322 mkexpr( lmd_07_mask ), 9323 mkexpr( lmd_07_val ) ), 9324 binop( Iop_And32, 9325 mkexpr( lmd_8_mask ), 9326 mkexpr( lmd_8_val ) ) ), 9327 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) ); 9328 } 9329 9330 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 ) 9331 { 9332 /* Extract the exponent and the left most digit of the mantissa 9333 * from the G field bits [0:4]. 9334 */ 9335 IRTemp lmd_07_mask = newTemp( Ity_I32 ); 9336 IRTemp lmd_8_00_mask = newTemp( Ity_I32 ); 9337 IRTemp lmd_8_01_mask = newTemp( Ity_I32 ); 9338 IRTemp lmd_8_10_mask = newTemp( Ity_I32 ); 9339 IRTemp lmd_9_00_mask = newTemp( Ity_I32 ); 9340 IRTemp lmd_9_01_mask = newTemp( Ity_I32 ); 9341 IRTemp lmd_9_10_mask = newTemp( Ity_I32 ); 9342 9343 IRTemp lmd_07_val = newTemp( Ity_I32 ); 9344 IRTemp lmd_8_val = newTemp( Ity_I32 ); 9345 IRTemp lmd_9_val = newTemp( Ity_I32 ); 9346 9347 /* The left most digit (LMD) encoding is as follows: 9348 * lmd 9349 * 0 - 7 (lmexp << 3) | lmd 9350 * 8 0b11000 (24 decimal) if lme=0b00; 9351 * 0b11010 (26 decimal) if lme=0b01; 9352 * 0b11100 (28 decimal) if lme=0b10 9353 * 9 0b11001 (25 decimal) if lme=0b00; 9354 * 0b11011 (27 decimal) if lme=0b01; 9355 * 0b11101 (29 decimal) if lme=0b10; 9356 */ 9357 9358 /* Generate the masks for each condition of LMD and exponent bits */ 9359 assign( lmd_07_mask, 9360 unop( Iop_1Sto32, binop( Iop_CmpLE32U, 9361 gfield_0_4, 9362 mkU32( BITS5(1,0,1,1,1) ) ) ) ); 9363 assign( lmd_8_00_mask, 9364 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9365 gfield_0_4, 9366 mkU32( BITS5(1,1,0,0,0) ) ) ) ); 9367 assign( lmd_8_01_mask, 9368 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9369 gfield_0_4, 9370 mkU32( BITS5(1,1,0,1,0) ) ) ) ); 9371 assign( lmd_8_10_mask, 9372 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9373 gfield_0_4, 9374 mkU32( BITS5(1,1,1,0,0) ) ) ) ); 9375 assign( lmd_9_00_mask, 9376 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9377 gfield_0_4, 9378 mkU32( BITS5(1,1,0,0,1) ) ) ) ); 9379 assign( lmd_9_01_mask, 9380 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9381 gfield_0_4, 9382 mkU32( BITS5(1,1,0,1,1) ) ) ) ); 9383 assign( lmd_9_10_mask, 9384 unop( Iop_1Sto32, binop( Iop_CmpEQ32, 9385 gfield_0_4, 9386 mkU32( BITS5(1,1,1,0,1) ) ) ) ); 9387 9388 /* Generate the values for each LMD condition, assuming the condition 9389 * is TRUE. 9390 */ 9391 assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) ); 9392 assign( lmd_8_val, mkU32( 0x8 ) ); 9393 assign( lmd_9_val, mkU32( 0x9 ) ); 9394 9395 assign( *lmd, 9396 OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ), 9397 AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ), 9398 AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )), 9399 OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ), 9400 AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ), 9401 AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ), 9402 AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) ) 9403 ) ) ); 9404 } 9405 9406 #define DIGIT1_SHR 4 // shift digit 1 to bottom 4 bits 9407 #define DIGIT2_SHR 8 // shift digit 2 to bottom 4 bits 9408 #define DIGIT3_SHR 12 9409 #define DIGIT4_SHR 16 9410 #define DIGIT5_SHR 20 9411 #define DIGIT6_SHR 24 9412 #define DIGIT7_SHR 28 9413 9414 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l ) 9415 { 9416 /* 60-bit BCD string stored in two 32-bit values. Check that each, 9417 * digit is a valid BCD number, i.e. less then 9. 9418 */ 9419 IRTemp valid = newTemp( Ity_I32 ); 9420 9421 assign( valid, 9422 AND4( AND4 ( unop( Iop_1Sto32, 9423 binop( Iop_CmpLE32U, 9424 binop( Iop_And32, 9425 bcd_l, 9426 mkU32 ( 0xF ) ), 9427 mkU32( 0x9 ) ) ), 9428 unop( Iop_1Sto32, 9429 binop( Iop_CmpLE32U, 9430 binop( Iop_And32, 9431 binop( Iop_Shr32, 9432 bcd_l, 9433 mkU8 ( DIGIT1_SHR ) ), 9434 mkU32 ( 0xF ) ), 9435 mkU32( 0x9 ) ) ), 9436 unop( Iop_1Sto32, 9437 binop( Iop_CmpLE32U, 9438 binop( Iop_And32, 9439 binop( Iop_Shr32, 9440 bcd_l, 9441 mkU8 ( DIGIT2_SHR ) ), 9442 mkU32 ( 0xF ) ), 9443 mkU32( 0x9 ) ) ), 9444 unop( Iop_1Sto32, 9445 binop( Iop_CmpLE32U, 9446 binop( Iop_And32, 9447 binop( Iop_Shr32, 9448 bcd_l, 9449 mkU8 ( DIGIT3_SHR ) ), 9450 mkU32 ( 0xF ) ), 9451 mkU32( 0x9 ) ) ) ), 9452 AND4 ( unop( Iop_1Sto32, 9453 binop( Iop_CmpLE32U, 9454 binop( Iop_And32, 9455 binop( Iop_Shr32, 9456 bcd_l, 9457 mkU8 ( DIGIT4_SHR ) ), 9458 mkU32 ( 0xF ) ), 9459 mkU32( 0x9 ) ) ), 9460 unop( Iop_1Sto32, 9461 binop( Iop_CmpLE32U, 9462 binop( Iop_And32, 9463 binop( Iop_Shr32, 9464 bcd_l, 9465 mkU8 ( DIGIT5_SHR ) ), 9466 mkU32 ( 0xF ) ), 9467 mkU32( 0x9 ) ) ), 9468 unop( Iop_1Sto32, 9469 binop( Iop_CmpLE32U, 9470 binop( Iop_And32, 9471 binop( Iop_Shr32, 9472 bcd_l, 9473 mkU8 ( DIGIT6_SHR ) ), 9474 mkU32 ( 0xF ) ), 9475 mkU32( 0x9 ) ) ), 9476 unop( Iop_1Sto32, 9477 binop( Iop_CmpLE32U, 9478 binop( Iop_And32, 9479 binop( Iop_Shr32, 9480 bcd_l, 9481 mkU8 ( DIGIT7_SHR ) ), 9482 mkU32 ( 0xF ) ), 9483 mkU32( 0x9 ) ) ) ), 9484 AND4( unop( Iop_1Sto32, 9485 binop( Iop_CmpLE32U, 9486 binop( Iop_And32, 9487 bcd_u, 9488 mkU32 ( 0xF ) ), 9489 mkU32( 0x9 ) ) ), 9490 unop( Iop_1Sto32, 9491 binop( Iop_CmpLE32U, 9492 binop( Iop_And32, 9493 binop( Iop_Shr32, 9494 bcd_u, 9495 mkU8 ( DIGIT1_SHR ) ), 9496 mkU32 ( 0xF ) ), 9497 mkU32( 0x9 ) ) ), 9498 unop( Iop_1Sto32, 9499 binop( Iop_CmpLE32U, 9500 binop( Iop_And32, 9501 binop( Iop_Shr32, 9502 bcd_u, 9503 mkU8 ( DIGIT2_SHR ) ), 9504 mkU32 ( 0xF ) ), 9505 mkU32( 0x9 ) ) ), 9506 unop( Iop_1Sto32, 9507 binop( Iop_CmpLE32U, 9508 binop( Iop_And32, 9509 binop( Iop_Shr32, 9510 bcd_u, 9511 mkU8 ( DIGIT3_SHR ) ), 9512 mkU32 ( 0xF ) ), 9513 mkU32( 0x9 ) ) ) ), 9514 AND4( unop( Iop_1Sto32, 9515 binop( Iop_CmpLE32U, 9516 binop( Iop_And32, 9517 binop( Iop_Shr32, 9518 bcd_u, 9519 mkU8 ( DIGIT4_SHR ) ), 9520 mkU32 ( 0xF ) ), 9521 mkU32( 0x9 ) ) ), 9522 unop( Iop_1Sto32, 9523 binop( Iop_CmpLE32U, 9524 binop( Iop_And32, 9525 binop( Iop_Shr32, 9526 bcd_u, 9527 mkU8 ( DIGIT5_SHR ) ), 9528 mkU32 ( 0xF ) ), 9529 mkU32( 0x9 ) ) ), 9530 unop( Iop_1Sto32, 9531 binop( Iop_CmpLE32U, 9532 binop( Iop_And32, 9533 binop( Iop_Shr32, 9534 bcd_u, 9535 mkU8 ( DIGIT6_SHR ) ), 9536 mkU32 ( 0xF ) ), 9537 mkU32( 0x9 ) ) ), 9538 unop( Iop_1Sto32, 9539 binop( Iop_CmpLE32U, 9540 binop( Iop_And32, 9541 binop( Iop_Shr32, 9542 bcd_u, 9543 mkU8 ( DIGIT7_SHR ) ), 9544 mkU32 ( 0xF ) ), 9545 mkU32( 0x9 ) ) ) ) ) ); 9546 9547 return unop( Iop_Not32, mkexpr( valid ) ); 9548 } 9549 #undef DIGIT1_SHR 9550 #undef DIGIT2_SHR 9551 #undef DIGIT3_SHR 9552 #undef DIGIT4_SHR 9553 #undef DIGIT5_SHR 9554 #undef DIGIT6_SHR 9555 #undef DIGIT7_SHR 9556 9557 static IRExpr * Generate_neg_sign_mask( IRExpr * sign ) 9558 { 9559 return binop( Iop_Or32, 9560 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ), 9561 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) ) 9562 ); 9563 } 9564 9565 static IRExpr * Generate_pos_sign_mask( IRExpr * sign ) 9566 { 9567 return binop( Iop_Or32, 9568 binop( Iop_Or32, 9569 unop( Iop_1Sto32, 9570 binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ), 9571 unop( Iop_1Sto32, 9572 binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ), 9573 binop( Iop_Or32, 9574 unop( Iop_1Sto32, 9575 binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ), 9576 unop( Iop_1Sto32, 9577 binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) ); 9578 } 9579 9580 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask, 9581 IRExpr * neg_sign_mask ) 9582 { 9583 return binop( Iop_Or32, 9584 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ), 9585 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) ); 9586 } 9587 9588 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask, 9589 IRExpr * pos_sign_mask, 9590 IRExpr * neg_sign_mask ) 9591 /* first argument is all 1's if the BCD string had an invalid digit in it. */ 9592 { 9593 return binop( Iop_Or32, 9594 invalid_bcd_mask, 9595 unop( Iop_1Sto32, 9596 binop( Iop_CmpEQ32, 9597 binop( Iop_Or32, pos_sign_mask, neg_sign_mask ), 9598 mkU32( 0x0 ) ) ) ); 9599 } 9600 9601 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo, 9602 IRTemp * top_12_l, IRTemp * mid_60_u, 9603 IRTemp * mid_60_l, IRTemp * low_60_u, 9604 IRTemp * low_60_l) 9605 { 9606 IRTemp tmplow60 = newTemp( Ity_I64 ); 9607 IRTemp tmpmid60 = newTemp( Ity_I64 ); 9608 IRTemp tmptop12 = newTemp( Ity_I64 ); 9609 IRTemp low_50 = newTemp( Ity_I64 ); 9610 IRTemp mid_50 = newTemp( Ity_I64 ); 9611 IRTemp top_10 = newTemp( Ity_I64 ); 9612 IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg 9613 9614 /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */ 9615 9616 /* low_50[49:0] = ((frBI64_lo[49:32] << 14) | frBI64_lo[31:0]) */ 9617 assign( low_50, 9618 binop( Iop_32HLto64, 9619 binop( Iop_And32, 9620 unop( Iop_64HIto32, frBI64_lo ), 9621 mkU32( 0x3FFFF ) ), 9622 unop( Iop_64to32, frBI64_lo ) ) ); 9623 9624 /* Convert the 50 bit densely packed BCD string to a 60 bit 9625 * BCD string. 9626 */ 9627 assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) ); 9628 assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) ); 9629 assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) ); 9630 9631 /* mid_50[49:0] = ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) | 9632 * ((frBI64_hi[17:0] << 14) | frBI64_lo[63:50]) 9633 */ 9634 assign( mid_50, 9635 binop( Iop_32HLto64, 9636 binop( Iop_Or32, 9637 binop( Iop_Shl32, 9638 binop( Iop_And32, 9639 unop( Iop_64HIto32, frBI64_hi ), 9640 mkU32( 0xF ) ), 9641 mkU8( 14 ) ), 9642 binop( Iop_Shr32, 9643 unop( Iop_64to32, frBI64_hi ), 9644 mkU8( 18 ) ) ), 9645 binop( Iop_Or32, 9646 binop( Iop_Shl32, 9647 unop( Iop_64to32, frBI64_hi ), 9648 mkU8( 14 ) ), 9649 binop( Iop_Shr32, 9650 unop( Iop_64HIto32, frBI64_lo ), 9651 mkU8( 18 ) ) ) ) ); 9652 9653 /* Convert the 50 bit densely packed BCD string to a 60 bit 9654 * BCD string. 9655 */ 9656 assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) ); 9657 assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) ); 9658 assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) ); 9659 9660 /* top_10[49:0] = frBI64_hi[45:36]) | */ 9661 assign( top_10, 9662 binop( Iop_32HLto64, 9663 mkU32( 0 ), 9664 binop( Iop_And32, 9665 binop( Iop_Shr32, 9666 unop( Iop_64HIto32, frBI64_hi ), 9667 mkU8( 4 ) ), 9668 mkU32( 0x3FF ) ) ) ); 9669 9670 /* Convert the 10 bit densely packed BCD string to a 12 bit 9671 * BCD string. 9672 */ 9673 assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) ); 9674 assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) ); 9675 assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) ); 9676 } 9677 9678 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag, 9679 IRTemp * final_cnt, IRTemp * final_flag, 9680 IRExpr * string ) 9681 { 9682 IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1]; 9683 int digits = MAX_DIGITS_IN_STRING; 9684 int i; 9685 9686 cnt[start-1] = newTemp( Ity_I8 ); 9687 flag[start-1] = newTemp( Ity_I8 ); 9688 assign( cnt[start-1], init_cnt); 9689 assign( flag[start-1], init_flag); 9690 9691 for ( i = start; i <= digits; i++) { 9692 cnt[i] = newTemp( Ity_I8 ); 9693 flag[i] = newTemp( Ity_I8 ); 9694 assign( cnt[i], 9695 binop( Iop_Add8, 9696 mkexpr( cnt[i-1] ), 9697 binop(Iop_And8, 9698 unop( Iop_1Uto8, 9699 binop(Iop_CmpEQ32, 9700 binop(Iop_And32, 9701 string, 9702 mkU32( 0xF << 9703 ( ( digits - i ) * 4) ) ), 9704 mkU32( 0 ) ) ), 9705 binop( Iop_Xor8, /* complement flag */ 9706 mkexpr( flag[i - 1] ), 9707 mkU8( 0xFF ) ) ) ) ); 9708 9709 /* set flag to 1 if digit was not a zero */ 9710 assign( flag[i], 9711 binop(Iop_Or8, 9712 unop( Iop_1Sto8, 9713 binop(Iop_CmpNE32, 9714 binop(Iop_And32, 9715 string, 9716 mkU32( 0xF << 9717 ( (digits - i) * 4) ) ), 9718 mkU32( 0 ) ) ), 9719 mkexpr( flag[i - 1] ) ) ); 9720 } 9721 9722 *final_cnt = cnt[digits]; 9723 *final_flag = flag[digits]; 9724 } 9725 9726 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28, 9727 IRExpr * low_32 ) 9728 { 9729 IRTemp num_lmd = newTemp( Ity_I8 ); 9730 IRTemp num_upper = newTemp( Ity_I8 ); 9731 IRTemp num_low = newTemp( Ity_I8 ); 9732 IRTemp lmd_flag = newTemp( Ity_I8 ); 9733 IRTemp upper_flag = newTemp( Ity_I8 ); 9734 IRTemp low_flag = newTemp( Ity_I8 ); 9735 9736 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 9737 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 9738 9739 Count_zeros( 2, 9740 mkexpr( num_lmd ), 9741 mkexpr( lmd_flag ), 9742 &num_upper, 9743 &upper_flag, 9744 upper_28 ); 9745 9746 Count_zeros( 1, 9747 mkexpr( num_upper ), 9748 mkexpr( upper_flag ), 9749 &num_low, 9750 &low_flag, 9751 low_32 ); 9752 9753 return mkexpr( num_low ); 9754 } 9755 9756 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l, 9757 IRExpr * mid_60_u, IRExpr * mid_60_l, 9758 IRExpr * low_60_u, IRExpr * low_60_l) 9759 { 9760 IRTemp num_lmd = newTemp( Ity_I8 ); 9761 IRTemp num_top = newTemp( Ity_I8 ); 9762 IRTemp num_mid_u = newTemp( Ity_I8 ); 9763 IRTemp num_mid_l = newTemp( Ity_I8 ); 9764 IRTemp num_low_u = newTemp( Ity_I8 ); 9765 IRTemp num_low_l = newTemp( Ity_I8 ); 9766 9767 IRTemp lmd_flag = newTemp( Ity_I8 ); 9768 IRTemp top_flag = newTemp( Ity_I8 ); 9769 IRTemp mid_u_flag = newTemp( Ity_I8 ); 9770 IRTemp mid_l_flag = newTemp( Ity_I8 ); 9771 IRTemp low_u_flag = newTemp( Ity_I8 ); 9772 IRTemp low_l_flag = newTemp( Ity_I8 ); 9773 9774 /* Check the LMD, digit 16, to see if it is zero. */ 9775 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) ); 9776 9777 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) ); 9778 9779 Count_zeros( 6, 9780 mkexpr( num_lmd ), 9781 mkexpr( lmd_flag ), 9782 &num_top, 9783 &top_flag, 9784 top_12_l ); 9785 9786 Count_zeros( 1, 9787 mkexpr( num_top ), 9788 mkexpr( top_flag ), 9789 &num_mid_u, 9790 &mid_u_flag, 9791 binop( Iop_Or32, 9792 binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ), 9793 binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) ); 9794 9795 Count_zeros( 2, 9796 mkexpr( num_mid_u ), 9797 mkexpr( mid_u_flag ), 9798 &num_mid_l, 9799 &mid_l_flag, 9800 mid_60_l ); 9801 9802 Count_zeros( 1, 9803 mkexpr( num_mid_l ), 9804 mkexpr( mid_l_flag ), 9805 &num_low_u, 9806 &low_u_flag, 9807 binop( Iop_Or32, 9808 binop( Iop_Shl32, low_60_u, mkU8( 2 ) ), 9809 binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) ); 9810 9811 Count_zeros( 2, 9812 mkexpr( num_low_u ), 9813 mkexpr( low_u_flag ), 9814 &num_low_l, 9815 &low_l_flag, 9816 low_60_l ); 9817 9818 return mkexpr( num_low_l ); 9819 } 9820 9821 static IRExpr * Check_unordered(IRExpr * val) 9822 { 9823 IRTemp gfield0to5 = newTemp( Ity_I32 ); 9824 9825 /* Extract G[0:4] */ 9826 assign( gfield0to5, 9827 binop( Iop_And32, 9828 binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ), 9829 mkU32( 0x1F ) ) ); 9830 9831 /* Check for unordered, return all 1'x if true */ 9832 return binop( Iop_Or32, /* QNaN check */ 9833 unop( Iop_1Sto32, 9834 binop( Iop_CmpEQ32, 9835 mkexpr( gfield0to5 ), 9836 mkU32( 0x1E ) ) ), 9837 unop( Iop_1Sto32, /* SNaN check */ 9838 binop( Iop_CmpEQ32, 9839 mkexpr( gfield0to5 ), 9840 mkU32( 0x1F ) ) ) ); 9841 } 9842 9843 #undef AND 9844 #undef AND4 9845 #undef OR 9846 #undef OR3 9847 #undef OR4 9848 #undef NOT 9849 #undef SHR 9850 #undef SHL 9851 #undef BITS5 9852 9853 /*------------------------------------------------------------*/ 9854 /*--- Decimal Floating Point (DFP) instruction translation ---*/ 9855 /*------------------------------------------------------------*/ 9856 9857 /* DFP Arithmetic instructions */ 9858 static Bool dis_dfp_arith(UInt theInstr) 9859 { 9860 UInt opc2 = ifieldOPClo10( theInstr ); 9861 UChar frS_addr = ifieldRegDS( theInstr ); 9862 UChar frA_addr = ifieldRegA( theInstr ); 9863 UChar frB_addr = ifieldRegB( theInstr ); 9864 UChar flag_rC = ifieldBIT0( theInstr ); 9865 9866 IRTemp frA = newTemp( Ity_D64 ); 9867 IRTemp frB = newTemp( Ity_D64 ); 9868 IRTemp frS = newTemp( Ity_D64 ); 9869 IRExpr* round = get_IR_roundingmode_DFP(); 9870 9871 /* By default, if flag_RC is set, we will clear cr1 after the 9872 * operation. In reality we should set cr1 to indicate the 9873 * exception status of the operation, but since we're not 9874 * simulating exceptions, the exception status will appear to be 9875 * zero. Hence cr1 should be cleared if this is a . form insn. 9876 */ 9877 Bool clear_CR1 = True; 9878 9879 assign( frA, getDReg( frA_addr ) ); 9880 assign( frB, getDReg( frB_addr ) ); 9881 9882 switch (opc2) { 9883 case 0x2: // dadd 9884 DIP( "dadd%s fr%u,fr%u,fr%u\n", 9885 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9886 assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 9887 break; 9888 case 0x202: // dsub 9889 DIP( "dsub%s fr%u,fr%u,fr%u\n", 9890 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9891 assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 9892 break; 9893 case 0x22: // dmul 9894 DIP( "dmul%s fr%u,fr%u,fr%u\n", 9895 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9896 assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 9897 break; 9898 case 0x222: // ddiv 9899 DIP( "ddiv%s fr%u,fr%u,fr%u\n", 9900 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9901 assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) ); 9902 break; 9903 } 9904 9905 putDReg( frS_addr, mkexpr( frS ) ); 9906 9907 if (flag_rC && clear_CR1) { 9908 putCR321( 1, mkU8( 0 ) ); 9909 putCR0( 1, mkU8( 0 ) ); 9910 } 9911 9912 return True; 9913 } 9914 9915 /* Quad DFP Arithmetic instructions */ 9916 static Bool dis_dfp_arithq(UInt theInstr) 9917 { 9918 UInt opc2 = ifieldOPClo10( theInstr ); 9919 UChar frS_addr = ifieldRegDS( theInstr ); 9920 UChar frA_addr = ifieldRegA( theInstr ); 9921 UChar frB_addr = ifieldRegB( theInstr ); 9922 UChar flag_rC = ifieldBIT0( theInstr ); 9923 9924 IRTemp frA = newTemp( Ity_D128 ); 9925 IRTemp frB = newTemp( Ity_D128 ); 9926 IRTemp frS = newTemp( Ity_D128 ); 9927 IRExpr* round = get_IR_roundingmode_DFP(); 9928 9929 /* By default, if flag_RC is set, we will clear cr1 after the 9930 * operation. In reality we should set cr1 to indicate the 9931 * exception status of the operation, but since we're not 9932 * simulating exceptions, the exception status will appear to be 9933 * zero. Hence cr1 should be cleared if this is a . form insn. 9934 */ 9935 Bool clear_CR1 = True; 9936 9937 assign( frA, getDReg_pair( frA_addr ) ); 9938 assign( frB, getDReg_pair( frB_addr ) ); 9939 9940 switch (opc2) { 9941 case 0x2: // daddq 9942 DIP( "daddq%s fr%u,fr%u,fr%u\n", 9943 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9944 assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 9945 break; 9946 case 0x202: // dsubq 9947 DIP( "dsubq%s fr%u,fr%u,fr%u\n", 9948 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9949 assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 9950 break; 9951 case 0x22: // dmulq 9952 DIP( "dmulq%s fr%u,fr%u,fr%u\n", 9953 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9954 assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 9955 break; 9956 case 0x222: // ddivq 9957 DIP( "ddivq%s fr%u,fr%u,fr%u\n", 9958 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 9959 assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) ); 9960 break; 9961 } 9962 9963 putDReg_pair( frS_addr, mkexpr( frS ) ); 9964 9965 if (flag_rC && clear_CR1) { 9966 putCR321( 1, mkU8( 0 ) ); 9967 putCR0( 1, mkU8( 0 ) ); 9968 } 9969 9970 return True; 9971 } 9972 9973 /* DFP 64-bit logical shift instructions */ 9974 static Bool dis_dfp_shift(UInt theInstr) { 9975 UInt opc2 = ifieldOPClo9( theInstr ); 9976 UChar frS_addr = ifieldRegDS( theInstr ); 9977 UChar frA_addr = ifieldRegA( theInstr ); 9978 UChar shift_val = IFIELD(theInstr, 10, 6); 9979 UChar flag_rC = ifieldBIT0( theInstr ); 9980 9981 IRTemp frA = newTemp( Ity_D64 ); 9982 IRTemp frS = newTemp( Ity_D64 ); 9983 Bool clear_CR1 = True; 9984 9985 assign( frA, getDReg( frA_addr ) ); 9986 9987 switch (opc2) { 9988 case 0x42: // dscli 9989 DIP( "dscli%s fr%u,fr%u,%u\n", 9990 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 9991 assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) ); 9992 break; 9993 case 0x62: // dscri 9994 DIP( "dscri%s fr%u,fr%u,%u\n", 9995 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 9996 assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) ); 9997 break; 9998 } 9999 10000 putDReg( frS_addr, mkexpr( frS ) ); 10001 10002 if (flag_rC && clear_CR1) { 10003 putCR321( 1, mkU8( 0 ) ); 10004 putCR0( 1, mkU8( 0 ) ); 10005 } 10006 10007 return True; 10008 } 10009 10010 /* Quad DFP logical shift instructions */ 10011 static Bool dis_dfp_shiftq(UInt theInstr) { 10012 UInt opc2 = ifieldOPClo9( theInstr ); 10013 UChar frS_addr = ifieldRegDS( theInstr ); 10014 UChar frA_addr = ifieldRegA( theInstr ); 10015 UChar shift_val = IFIELD(theInstr, 10, 6); 10016 UChar flag_rC = ifieldBIT0( theInstr ); 10017 10018 IRTemp frA = newTemp( Ity_D128 ); 10019 IRTemp frS = newTemp( Ity_D128 ); 10020 Bool clear_CR1 = True; 10021 10022 assign( frA, getDReg_pair( frA_addr ) ); 10023 10024 switch (opc2) { 10025 case 0x42: // dscliq 10026 DIP( "dscliq%s fr%u,fr%u,%u\n", 10027 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10028 assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) ); 10029 break; 10030 case 0x62: // dscriq 10031 DIP( "dscriq%s fr%u,fr%u,%u\n", 10032 flag_rC ? ".":"", frS_addr, frA_addr, shift_val ); 10033 assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) ); 10034 break; 10035 } 10036 10037 putDReg_pair( frS_addr, mkexpr( frS ) ); 10038 10039 if (flag_rC && clear_CR1) { 10040 putCR321( 1, mkU8( 0 ) ); 10041 putCR0( 1, mkU8( 0 ) ); 10042 } 10043 10044 return True; 10045 } 10046 10047 /* DFP 64-bit format conversion instructions */ 10048 static Bool dis_dfp_fmt_conv(UInt theInstr) { 10049 UInt opc2 = ifieldOPClo10( theInstr ); 10050 UChar frS_addr = ifieldRegDS( theInstr ); 10051 UChar frB_addr = ifieldRegB( theInstr ); 10052 IRExpr* round = get_IR_roundingmode_DFP(); 10053 UChar flag_rC = ifieldBIT0( theInstr ); 10054 IRTemp frB; 10055 IRTemp frS; 10056 Bool clear_CR1 = True; 10057 10058 switch (opc2) { 10059 case 0x102: //dctdp 10060 DIP( "dctdp%s fr%u,fr%u\n", 10061 flag_rC ? ".":"", frS_addr, frB_addr ); 10062 10063 frB = newTemp( Ity_D32 ); 10064 frS = newTemp( Ity_D64 ); 10065 assign( frB, getDReg32( frB_addr ) ); 10066 assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) ); 10067 putDReg( frS_addr, mkexpr( frS ) ); 10068 break; 10069 case 0x302: // drsp 10070 DIP( "drsp%s fr%u,fr%u\n", 10071 flag_rC ? ".":"", frS_addr, frB_addr ); 10072 frB = newTemp( Ity_D64 ); 10073 frS = newTemp( Ity_D32 ); 10074 assign( frB, getDReg( frB_addr ) ); 10075 assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) ); 10076 putDReg32( frS_addr, mkexpr( frS ) ); 10077 break; 10078 case 0x122: // dctfix 10079 { 10080 IRTemp tmp = newTemp( Ity_I64 ); 10081 10082 DIP( "dctfix%s fr%u,fr%u\n", 10083 flag_rC ? ".":"", frS_addr, frB_addr ); 10084 frB = newTemp( Ity_D64 ); 10085 frS = newTemp( Ity_D64 ); 10086 assign( frB, getDReg( frB_addr ) ); 10087 assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) ); 10088 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10089 putDReg( frS_addr, mkexpr( frS ) ); 10090 } 10091 break; 10092 case 0x322: // dcffix 10093 DIP( "dcffix%s fr%u,fr%u\n", 10094 flag_rC ? ".":"", frS_addr, frB_addr ); 10095 frB = newTemp( Ity_D64 ); 10096 frS = newTemp( Ity_D64 ); 10097 assign( frB, getDReg( frB_addr ) ); 10098 assign( frS, binop( Iop_I64StoD64, 10099 round, 10100 unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) ); 10101 putDReg( frS_addr, mkexpr( frS ) ); 10102 break; 10103 } 10104 10105 if (flag_rC && clear_CR1) { 10106 putCR321( 1, mkU8( 0 ) ); 10107 putCR0( 1, mkU8( 0 ) ); 10108 } 10109 10110 return True; 10111 } 10112 10113 /* Quad DFP format conversion instructions */ 10114 static Bool dis_dfp_fmt_convq(UInt theInstr) { 10115 UInt opc2 = ifieldOPClo10( theInstr ); 10116 UChar frS_addr = ifieldRegDS( theInstr ); 10117 UChar frB_addr = ifieldRegB( theInstr ); 10118 IRExpr* round = get_IR_roundingmode_DFP(); 10119 IRTemp frB64 = newTemp( Ity_D64 ); 10120 IRTemp frB128 = newTemp( Ity_D128 ); 10121 IRTemp frS64 = newTemp( Ity_D64 ); 10122 IRTemp frS128 = newTemp( Ity_D128 ); 10123 UChar flag_rC = ifieldBIT0( theInstr ); 10124 Bool clear_CR1 = True; 10125 10126 switch (opc2) { 10127 case 0x102: // dctqpq 10128 DIP( "dctqpq%s fr%u,fr%u\n", 10129 flag_rC ? ".":"", frS_addr, frB_addr ); 10130 assign( frB64, getDReg( frB_addr ) ); 10131 assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) ); 10132 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 10133 break; 10134 case 0x122: // dctfixq 10135 { 10136 IRTemp tmp = newTemp( Ity_I64 ); 10137 10138 DIP( "dctfixq%s fr%u,fr%u\n", 10139 flag_rC ? ".":"", frS_addr, frB_addr ); 10140 assign( frB128, getDReg_pair( frB_addr ) ); 10141 assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) ); 10142 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10143 putDReg( frS_addr, mkexpr( frS64 ) ); 10144 } 10145 break; 10146 case 0x302: //drdpq 10147 DIP( "drdpq%s fr%u,fr%u\n", 10148 flag_rC ? ".":"", frS_addr, frB_addr ); 10149 assign( frB128, getDReg_pair( frB_addr ) ); 10150 assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) ); 10151 putDReg( frS_addr, mkexpr( frS64 ) ); 10152 break; 10153 case 0x322: // dcffixq 10154 { 10155 /* Have to introduce an IOP for this instruction so it will work 10156 * on POWER 6 because emulating the instruction requires a POWER 7 10157 * DFP instruction in the emulation code. 10158 */ 10159 DIP( "dcffixq%s fr%u,fr%u\n", 10160 flag_rC ? ".":"", frS_addr, frB_addr ); 10161 assign( frB64, getDReg( frB_addr ) ); 10162 assign( frS128, unop( Iop_I64StoD128, 10163 unop( Iop_ReinterpD64asI64, 10164 mkexpr( frB64 ) ) ) ); 10165 putDReg_pair( frS_addr, mkexpr( frS128 ) ); 10166 break; 10167 } 10168 } 10169 10170 if (flag_rC && clear_CR1) { 10171 putCR321( 1, mkU8( 0 ) ); 10172 putCR0( 1, mkU8( 0 ) ); 10173 } 10174 10175 return True; 10176 } 10177 10178 static Bool dis_dfp_round( UInt theInstr ) { 10179 UChar frS_addr = ifieldRegDS(theInstr); 10180 UChar R = IFIELD(theInstr, 16, 1); 10181 UChar RMC = IFIELD(theInstr, 9, 2); 10182 UChar frB_addr = ifieldRegB( theInstr ); 10183 UChar flag_rC = ifieldBIT0( theInstr ); 10184 IRTemp frB = newTemp( Ity_D64 ); 10185 IRTemp frS = newTemp( Ity_D64 ); 10186 UInt opc2 = ifieldOPClo8( theInstr ); 10187 Bool clear_CR1 = True; 10188 10189 switch (opc2) { 10190 /* drintn, is the same as drintx. The only difference is this 10191 * instruction does not generate an exception for an inexact operation. 10192 * Currently not supporting inexact exceptions. 10193 */ 10194 case 0x63: // drintx 10195 case 0xE3: // drintn 10196 DIP( "drintx/drintn%s fr%u,fr%u\n", 10197 flag_rC ? ".":"", frS_addr, frB_addr ); 10198 10199 /* NOTE, this instruction takes a DFP value and rounds to the 10200 * neares floating point integer value, i.e. fractional part 10201 * is zero. The result is a floating point number. 10202 */ 10203 /* pass the value of R and RMC in the same field */ 10204 assign( frB, getDReg( frB_addr ) ); 10205 assign( frS, binop( Iop_RoundD64toInt, 10206 mkU32( ( R << 3 ) | RMC ), 10207 mkexpr( frB ) ) ); 10208 putDReg( frS_addr, mkexpr( frS ) ); 10209 break; 10210 default: 10211 vex_printf("dis_dfp_round(ppc)(opc2)\n"); 10212 return False; 10213 } 10214 10215 if (flag_rC && clear_CR1) { 10216 putCR321( 1, mkU8( 0 ) ); 10217 putCR0( 1, mkU8( 0 ) ); 10218 } 10219 10220 return True; 10221 } 10222 10223 static Bool dis_dfp_roundq(UInt theInstr) { 10224 UChar frS_addr = ifieldRegDS( theInstr ); 10225 UChar frB_addr = ifieldRegB( theInstr ); 10226 UChar R = IFIELD(theInstr, 16, 1); 10227 UChar RMC = IFIELD(theInstr, 9, 2); 10228 UChar flag_rC = ifieldBIT0( theInstr ); 10229 IRTemp frB = newTemp( Ity_D128 ); 10230 IRTemp frS = newTemp( Ity_D128 ); 10231 Bool clear_CR1 = True; 10232 UInt opc2 = ifieldOPClo8( theInstr ); 10233 10234 switch (opc2) { 10235 /* drintnq, is the same as drintxq. The only difference is this 10236 * instruction does not generate an exception for an inexact operation. 10237 * Currently not supporting inexact exceptions. 10238 */ 10239 case 0x63: // drintxq 10240 case 0xE3: // drintnq 10241 DIP( "drintxq/drintnq%s fr%u,fr%u\n", 10242 flag_rC ? ".":"", frS_addr, frB_addr ); 10243 10244 /* pass the value of R and RMC in the same field */ 10245 assign( frB, getDReg_pair( frB_addr ) ); 10246 assign( frS, binop( Iop_RoundD128toInt, 10247 mkU32( ( R << 3 ) | RMC ), 10248 mkexpr( frB ) ) ); 10249 putDReg_pair( frS_addr, mkexpr( frS ) ); 10250 break; 10251 default: 10252 vex_printf("dis_dfp_roundq(ppc)(opc2)\n"); 10253 return False; 10254 } 10255 10256 if (flag_rC && clear_CR1) { 10257 putCR321( 1, mkU8( 0 ) ); 10258 putCR0( 1, mkU8( 0 ) ); 10259 } 10260 10261 return True; 10262 } 10263 10264 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) { 10265 UInt opc2 = ifieldOPClo8( theInstr ); 10266 UChar frS_addr = ifieldRegDS( theInstr ); 10267 UChar frA_addr = ifieldRegA( theInstr ); 10268 UChar frB_addr = ifieldRegB( theInstr ); 10269 UChar flag_rC = ifieldBIT0( theInstr ); 10270 UInt TE_value = IFIELD(theInstr, 16, 4); 10271 UInt TE_sign = IFIELD(theInstr, 20, 1); 10272 UInt RMC = IFIELD(theInstr, 9, 2); 10273 IRTemp frA = newTemp( Ity_D64 ); 10274 IRTemp frB = newTemp( Ity_D64 ); 10275 IRTemp frS = newTemp( Ity_D64 ); 10276 Bool clear_CR1 = True; 10277 10278 assign( frB, getDReg( frB_addr ) ); 10279 10280 switch (opc2) { 10281 case 0x43: // dquai 10282 DIP( "dquai%s fr%u,fr%u,fr%u\n", 10283 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10284 IRTemp TE_I64 = newTemp( Ity_I64 ); 10285 10286 /* Generate a reference DFP value frA with the desired exponent 10287 * given by TE using significand from frB. Need to add the bias 10288 * 398 to TE. TE is stored as a 2's complement number. 10289 */ 10290 if (TE_sign == 1) { 10291 /* Take 2's complement of the 5-bit value and subtract from bias. 10292 * Bias is adjusted for the +1 required when taking 2's complement. 10293 */ 10294 assign( TE_I64, 10295 unop( Iop_32Uto64, 10296 binop( Iop_Sub32, mkU32( 397 ), 10297 binop( Iop_And32, mkU32( 0xF ), 10298 unop( Iop_Not32, mkU32( TE_value ) ) 10299 ) ) ) ); 10300 10301 } else { 10302 assign( TE_I64, 10303 unop( Iop_32Uto64, 10304 binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) ) 10305 ) ); 10306 } 10307 10308 assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ), 10309 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ); 10310 10311 assign( frS, triop( Iop_QuantizeD64, 10312 mkU32( RMC ), 10313 mkexpr( frA ), 10314 mkexpr( frB ) ) ); 10315 break; 10316 10317 case 0x3: // dqua 10318 DIP( "dqua%s fr%u,fr%u,fr%u\n", 10319 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10320 assign( frA, getDReg( frA_addr ) ); 10321 assign( frS, triop( Iop_QuantizeD64, 10322 mkU32( RMC ), 10323 mkexpr( frA ), 10324 mkexpr( frB ) ) ); 10325 break; 10326 case 0x23: // drrnd 10327 { 10328 IRTemp tmp = newTemp( Ity_I8 ); 10329 10330 DIP( "drrnd%s fr%u,fr%u,fr%u\n", 10331 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10332 assign( frA, getDReg( frA_addr ) ); 10333 /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */ 10334 assign( tmp, unop( Iop_32to8, 10335 unop( Iop_64to32, 10336 unop( Iop_ReinterpD64asI64, 10337 mkexpr( frA ) ) ) ) ); 10338 assign( frS, triop( Iop_SignificanceRoundD64, 10339 mkU32( RMC ), 10340 mkexpr( tmp ), 10341 mkexpr( frB ) ) ); 10342 } 10343 break; 10344 default: 10345 vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n"); 10346 return False; 10347 } 10348 putDReg( frS_addr, mkexpr( frS ) ); 10349 10350 if (flag_rC && clear_CR1) { 10351 putCR321( 1, mkU8( 0 ) ); 10352 putCR0( 1, mkU8( 0 ) ); 10353 } 10354 10355 return True; 10356 } 10357 10358 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) { 10359 UInt opc2 = ifieldOPClo8( theInstr ); 10360 UChar frS_addr = ifieldRegDS( theInstr ); 10361 UChar frA_addr = ifieldRegA( theInstr ); 10362 UChar frB_addr = ifieldRegB( theInstr ); 10363 UChar flag_rC = ifieldBIT0( theInstr ); 10364 UInt TE_value = IFIELD(theInstr, 16, 4); 10365 UInt TE_sign = IFIELD(theInstr, 20, 1); 10366 UInt RMC = IFIELD(theInstr, 9, 2); 10367 IRTemp frA = newTemp( Ity_D128 ); 10368 IRTemp frB = newTemp( Ity_D128 ); 10369 IRTemp frS = newTemp( Ity_D128 ); 10370 Bool clear_CR1 = True; 10371 10372 assign( frB, getDReg_pair( frB_addr ) ); 10373 10374 switch (opc2) { 10375 case 0x43: // dquaiq 10376 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 10377 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10378 IRTemp TE_I64 = newTemp( Ity_I64 ); 10379 10380 /* Generate a reference DFP value frA with the desired exponent 10381 * given by TE using significand of 1. Need to add the bias 10382 * 6176 to TE. 10383 */ 10384 if (TE_sign == 1) { 10385 /* Take 2's complement of the 5-bit value and subtract from bias. 10386 * Bias adjusted for the +1 required when taking 2's complement. 10387 */ 10388 assign( TE_I64, 10389 unop( Iop_32Uto64, 10390 binop( Iop_Sub32, mkU32( 6175 ), 10391 binop( Iop_And32, mkU32( 0xF ), 10392 unop( Iop_Not32, mkU32( TE_value ) ) 10393 ) ) ) ); 10394 10395 } else { 10396 assign( TE_I64, 10397 unop( Iop_32Uto64, 10398 binop( Iop_Add32, 10399 mkU32( 6176 ), 10400 mkU32( TE_value ) ) ) ); 10401 } 10402 10403 assign( frA, 10404 binop( Iop_InsertExpD128, mkexpr( TE_I64 ), 10405 unop( Iop_D64toD128, 10406 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) ); 10407 assign( frS, triop( Iop_QuantizeD128, 10408 mkU32( RMC ), 10409 mkexpr( frA ), 10410 mkexpr( frB ) ) ); 10411 break; 10412 case 0x3: // dquaq 10413 DIP( "dquaiq%s fr%u,fr%u,fr%u\n", 10414 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10415 assign( frA, getDReg_pair( frA_addr ) ); 10416 assign( frS, triop( Iop_QuantizeD128, 10417 mkU32( RMC ), 10418 mkexpr( frA ), 10419 mkexpr( frB ) ) ); 10420 break; 10421 case 0x23: // drrndq 10422 { 10423 IRTemp tmp = newTemp( Ity_I8 ); 10424 10425 DIP( "drrndq%s fr%u,fr%u,fr%u\n", 10426 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10427 assign( frA, getDReg_pair( frA_addr ) ); 10428 assign( tmp, unop( Iop_32to8, 10429 unop( Iop_64to32, 10430 unop( Iop_ReinterpD64asI64, 10431 unop( Iop_D128HItoD64, 10432 mkexpr( frA ) ) ) ) ) ); 10433 assign( frS, triop( Iop_SignificanceRoundD128, 10434 mkU32( RMC ), 10435 mkexpr( tmp ), 10436 mkexpr( frB ) ) ); 10437 } 10438 break; 10439 default: 10440 vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n"); 10441 return False; 10442 } 10443 putDReg_pair( frS_addr, mkexpr( frS ) ); 10444 10445 if (flag_rC && clear_CR1) { 10446 putCR321( 1, mkU8( 0 ) ); 10447 putCR0( 1, mkU8( 0 ) ); 10448 } 10449 10450 return True; 10451 } 10452 10453 static Bool dis_dfp_extract_insert(UInt theInstr) { 10454 UInt opc2 = ifieldOPClo10( theInstr ); 10455 UChar frS_addr = ifieldRegDS( theInstr ); 10456 UChar frA_addr = ifieldRegA( theInstr ); 10457 UChar frB_addr = ifieldRegB( theInstr ); 10458 UChar flag_rC = ifieldBIT0( theInstr ); 10459 Bool clear_CR1 = True; 10460 10461 IRTemp frA = newTemp( Ity_D64 ); 10462 IRTemp frB = newTemp( Ity_D64 ); 10463 IRTemp frS = newTemp( Ity_D64 ); 10464 IRTemp tmp = newTemp( Ity_I64 ); 10465 10466 assign( frA, getDReg( frA_addr ) ); 10467 assign( frB, getDReg( frB_addr ) ); 10468 10469 switch (opc2) { 10470 case 0x162: // dxex 10471 DIP( "dxex%s fr%u,fr%u,fr%u\n", 10472 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10473 assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) ); 10474 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10475 break; 10476 case 0x362: // diex 10477 DIP( "diex%s fr%u,fr%u,fr%u\n", 10478 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10479 assign( frS, binop( Iop_InsertExpD64, 10480 unop( Iop_ReinterpD64asI64, 10481 mkexpr( frA ) ), 10482 mkexpr( frB ) ) ); 10483 break; 10484 default: 10485 vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n"); 10486 return False; 10487 } 10488 10489 putDReg( frS_addr, mkexpr( frS ) ); 10490 10491 if (flag_rC && clear_CR1) { 10492 putCR321( 1, mkU8( 0 ) ); 10493 putCR0( 1, mkU8( 0 ) ); 10494 } 10495 10496 return True; 10497 } 10498 10499 static Bool dis_dfp_extract_insertq(UInt theInstr) { 10500 UInt opc2 = ifieldOPClo10( theInstr ); 10501 UChar frS_addr = ifieldRegDS( theInstr ); 10502 UChar frA_addr = ifieldRegA( theInstr ); 10503 UChar frB_addr = ifieldRegB( theInstr ); 10504 UChar flag_rC = ifieldBIT0( theInstr ); 10505 10506 IRTemp frA = newTemp( Ity_D64 ); 10507 IRTemp frB = newTemp( Ity_D128 ); 10508 IRTemp frS64 = newTemp( Ity_D64 ); 10509 IRTemp frS = newTemp( Ity_D128 ); 10510 IRTemp tmp = newTemp( Ity_I64 ); 10511 Bool clear_CR1 = True; 10512 10513 assign( frB, getDReg_pair( frB_addr ) ); 10514 10515 switch (opc2) { 10516 case 0x162: // dxexq 10517 DIP( "dxexq%s fr%u,fr%u\n", 10518 flag_rC ? ".":"", frS_addr, frB_addr ); 10519 /* Instruction actually returns a 64-bit result. So as to be 10520 * consistent and not have to add a new struct, the emulation returns 10521 * the 64-bit result in the upper and lower register. 10522 */ 10523 assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) ); 10524 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) ); 10525 putDReg( frS_addr, mkexpr( frS64 ) ); 10526 break; 10527 case 0x362: // diexq 10528 DIP( "diexq%s fr%u,fr%u,fr%u\n", 10529 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr ); 10530 assign( frA, getDReg( frA_addr ) ); 10531 assign( frS, binop( Iop_InsertExpD128, 10532 unop( Iop_ReinterpD64asI64, mkexpr( frA ) ), 10533 mkexpr( frB ) ) ); 10534 putDReg_pair( frS_addr, mkexpr( frS ) ); 10535 break; 10536 default: 10537 vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n"); 10538 return False; 10539 } 10540 10541 if (flag_rC && clear_CR1) { 10542 putCR321( 1, mkU8( 0 ) ); 10543 putCR0( 1, mkU8( 0 ) ); 10544 } 10545 10546 return True; 10547 } 10548 10549 /* DFP 64-bit comparison instructions */ 10550 static Bool dis_dfp_compare(UInt theInstr) { 10551 /* X-Form */ 10552 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 10553 UChar frA_addr = ifieldRegA( theInstr ); 10554 UChar frB_addr = ifieldRegB( theInstr ); 10555 UInt opc1 = ifieldOPC( theInstr ); 10556 IRTemp frA; 10557 IRTemp frB; 10558 10559 IRTemp ccIR = newTemp( Ity_I32 ); 10560 IRTemp ccPPC32 = newTemp( Ity_I32 ); 10561 10562 10563 /* Note: Differences between dcmpu and dcmpo are only in exception 10564 flag settings, which aren't supported anyway. */ 10565 switch (opc1) { 10566 case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */ 10567 DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 10568 frA = newTemp( Ity_D64 ); 10569 frB = newTemp( Ity_D64 ); 10570 10571 assign( frA, getDReg( frA_addr ) ); 10572 assign( frB, getDReg( frB_addr ) ); 10573 10574 assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) ); 10575 break; 10576 case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */ 10577 DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr ); 10578 frA = newTemp( Ity_D128 ); 10579 frB = newTemp( Ity_D128 ); 10580 10581 assign( frA, getDReg_pair( frA_addr ) ); 10582 assign( frB, getDReg_pair( frB_addr ) ); 10583 assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) ); 10584 break; 10585 default: 10586 vex_printf("dis_dfp_compare(ppc)(opc2)\n"); 10587 return False; 10588 } 10589 10590 /* Map compare result from IR to PPC32 */ 10591 /* 10592 FP cmp result | PPC | IR 10593 -------------------------- 10594 UN | 0x1 | 0x45 10595 EQ | 0x2 | 0x40 10596 GT | 0x4 | 0x00 10597 LT | 0x8 | 0x01 10598 */ 10599 10600 assign( ccPPC32, 10601 binop( Iop_Shl32, 10602 mkU32( 1 ), 10603 unop( Iop_32to8, 10604 binop( Iop_Or32, 10605 binop( Iop_And32, 10606 unop( Iop_Not32, 10607 binop( Iop_Shr32, 10608 mkexpr( ccIR ), 10609 mkU8( 5 ) ) ), 10610 mkU32( 2 ) ), 10611 binop( Iop_And32, 10612 binop( Iop_Xor32, 10613 mkexpr( ccIR ), 10614 binop( Iop_Shr32, 10615 mkexpr( ccIR ), 10616 mkU8( 6 ) ) ), 10617 mkU32( 1 ) ) ) ) ) ); 10618 10619 putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD ); 10620 return True; 10621 } 10622 10623 /* Test class/group/exponent/significance instructions. */ 10624 static Bool dis_dfp_exponent_test ( UInt theInstr ) 10625 { 10626 UChar frA_addr = ifieldRegA( theInstr ); 10627 UChar frB_addr = ifieldRegB( theInstr ); 10628 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 10629 IRTemp frA = newTemp( Ity_D64 ); 10630 IRTemp frB = newTemp( Ity_D64 ); 10631 IRTemp frA128 = newTemp( Ity_D128 ); 10632 IRTemp frB128 = newTemp( Ity_D128 ); 10633 UInt opc1 = ifieldOPC( theInstr ); 10634 IRTemp gfield_A = newTemp( Ity_I32 ); 10635 IRTemp gfield_B = newTemp( Ity_I32 ); 10636 IRTemp gfield_mask = newTemp( Ity_I32 ); 10637 IRTemp exponent_A = newTemp( Ity_I32 ); 10638 IRTemp exponent_B = newTemp( Ity_I32 ); 10639 IRTemp A_NaN_true = newTemp( Ity_I32 ); 10640 IRTemp B_NaN_true = newTemp( Ity_I32 ); 10641 IRTemp A_inf_true = newTemp( Ity_I32 ); 10642 IRTemp B_inf_true = newTemp( Ity_I32 ); 10643 IRTemp A_equals_B = newTemp( Ity_I32 ); 10644 IRTemp finite_number = newTemp( Ity_I32 ); 10645 IRTemp cc0 = newTemp( Ity_I32 ); 10646 IRTemp cc1 = newTemp( Ity_I32 ); 10647 IRTemp cc2 = newTemp( Ity_I32 ); 10648 IRTemp cc3 = newTemp( Ity_I32 ); 10649 10650 /* The dtstex and dtstexg instructions only differ in the size of the 10651 * exponent field. The following switch statement takes care of the size 10652 * specific setup. Once the value of the exponents, the G-field shift 10653 * and mask is setup the remaining code is identical. 10654 */ 10655 switch (opc1) { 10656 case 0x3b: // dtstex Extended instruction setup 10657 DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 10658 assign( frA, getDReg( frA_addr ) ); 10659 assign( frB, getDReg( frB_addr ) ); 10660 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 10661 assign(exponent_A, unop( Iop_64to32, 10662 unop( Iop_ExtractExpD64, 10663 mkexpr( frA ) ) ) ); 10664 assign(exponent_B, unop( Iop_64to32, 10665 unop( Iop_ExtractExpD64, 10666 mkexpr( frB ) ) ) ); 10667 break; 10668 10669 case 0x3F: // dtstexq Quad instruction setup 10670 DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr); 10671 assign( frA128, getDReg_pair( frA_addr ) ); 10672 assign( frB128, getDReg_pair( frB_addr ) ); 10673 assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) ); 10674 assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) ); 10675 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 10676 assign( exponent_A, unop( Iop_64to32, 10677 unop( Iop_ExtractExpD128, 10678 mkexpr( frA128 ) ) ) ); 10679 assign( exponent_B, unop( Iop_64to32, 10680 unop( Iop_ExtractExpD128, 10681 mkexpr( frB128 ) ) ) ); 10682 break; 10683 default: 10684 vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n"); 10685 return False; 10686 } 10687 10688 /* Extract the Gfield */ 10689 assign( gfield_A, binop( Iop_And32, 10690 mkexpr( gfield_mask ), 10691 unop( Iop_64HIto32, 10692 unop( Iop_ReinterpD64asI64, 10693 mkexpr(frA) ) ) ) ); 10694 10695 assign( gfield_B, binop( Iop_And32, 10696 mkexpr( gfield_mask ), 10697 unop( Iop_64HIto32, 10698 unop( Iop_ReinterpD64asI64, 10699 mkexpr(frB) ) ) ) ); 10700 10701 /* check for NAN */ 10702 assign( A_NaN_true, binop(Iop_Or32, 10703 unop( Iop_1Sto32, 10704 binop( Iop_CmpEQ32, 10705 mkexpr( gfield_A ), 10706 mkU32( 0x7C000000 ) ) ), 10707 unop( Iop_1Sto32, 10708 binop( Iop_CmpEQ32, 10709 mkexpr( gfield_A ), 10710 mkU32( 0x7E000000 ) ) 10711 ) ) ); 10712 assign( B_NaN_true, binop(Iop_Or32, 10713 unop( Iop_1Sto32, 10714 binop( Iop_CmpEQ32, 10715 mkexpr( gfield_B ), 10716 mkU32( 0x7C000000 ) ) ), 10717 unop( Iop_1Sto32, 10718 binop( Iop_CmpEQ32, 10719 mkexpr( gfield_B ), 10720 mkU32( 0x7E000000 ) ) 10721 ) ) ); 10722 10723 /* check for infinity */ 10724 assign( A_inf_true, 10725 unop( Iop_1Sto32, 10726 binop( Iop_CmpEQ32, 10727 mkexpr( gfield_A ), 10728 mkU32( 0x78000000 ) ) ) ); 10729 10730 assign( B_inf_true, 10731 unop( Iop_1Sto32, 10732 binop( Iop_CmpEQ32, 10733 mkexpr( gfield_B ), 10734 mkU32( 0x78000000 ) ) ) ); 10735 10736 assign( finite_number, 10737 unop( Iop_Not32, 10738 binop( Iop_Or32, 10739 binop( Iop_Or32, 10740 mkexpr( A_NaN_true ), 10741 mkexpr( B_NaN_true ) ), 10742 binop( Iop_Or32, 10743 mkexpr( A_inf_true ), 10744 mkexpr( B_inf_true ) ) ) ) ); 10745 10746 /* Calculate the condition code bits 10747 * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero 10748 * regardless of the value of the comparisons and cc3 is 1. Otherwise, 10749 * cc0, cc1 and cc0 reflect the results of the comparisons. 10750 */ 10751 assign( A_equals_B, 10752 binop( Iop_Or32, 10753 unop( Iop_1Uto32, 10754 binop( Iop_CmpEQ32, 10755 mkexpr( exponent_A ), 10756 mkexpr( exponent_B ) ) ), 10757 binop( Iop_Or32, 10758 binop( Iop_And32, 10759 mkexpr( A_inf_true ), 10760 mkexpr( B_inf_true ) ), 10761 binop( Iop_And32, 10762 mkexpr( A_NaN_true ), 10763 mkexpr( B_NaN_true ) ) ) ) ); 10764 10765 assign( cc0, binop( Iop_And32, 10766 mkexpr( finite_number ), 10767 binop( Iop_Shl32, 10768 unop( Iop_1Uto32, 10769 binop( Iop_CmpLT32U, 10770 mkexpr( exponent_A ), 10771 mkexpr( exponent_B ) ) ), 10772 mkU8( 3 ) ) ) ); 10773 10774 assign( cc1, binop( Iop_And32, 10775 mkexpr( finite_number ), 10776 binop( Iop_Shl32, 10777 unop( Iop_1Uto32, 10778 binop( Iop_CmpLT32U, 10779 mkexpr( exponent_B ), 10780 mkexpr( exponent_A ) ) ), 10781 mkU8( 2 ) ) ) ); 10782 10783 assign( cc2, binop( Iop_Shl32, 10784 binop( Iop_And32, 10785 mkexpr( A_equals_B ), 10786 mkU32( 1 ) ), 10787 mkU8( 1 ) ) ); 10788 10789 assign( cc3, binop( Iop_And32, 10790 unop( Iop_Not32, mkexpr( A_equals_B ) ), 10791 binop( Iop_And32, 10792 mkU32( 0x1 ), 10793 binop( Iop_Or32, 10794 binop( Iop_Or32, 10795 mkexpr ( A_inf_true ), 10796 mkexpr ( B_inf_true ) ), 10797 binop( Iop_Or32, 10798 mkexpr ( A_NaN_true ), 10799 mkexpr ( B_NaN_true ) ) ) 10800 ) ) ); 10801 10802 /* store the condition code */ 10803 putGST_field( PPC_GST_CR, 10804 binop( Iop_Or32, 10805 mkexpr( cc0 ), 10806 binop( Iop_Or32, 10807 mkexpr( cc1 ), 10808 binop( Iop_Or32, 10809 mkexpr( cc2 ), 10810 mkexpr( cc3 ) ) ) ), 10811 crfD ); 10812 return True; 10813 } 10814 10815 /* Test class/group/exponent/significance instructions. */ 10816 static Bool dis_dfp_class_test ( UInt theInstr ) 10817 { 10818 UChar frA_addr = ifieldRegA( theInstr ); 10819 IRTemp frA = newTemp( Ity_D64 ); 10820 IRTemp abs_frA = newTemp( Ity_D64 ); 10821 IRTemp frAI64_hi = newTemp( Ity_I64 ); 10822 IRTemp frAI64_lo = newTemp( Ity_I64 ); 10823 UInt opc1 = ifieldOPC( theInstr ); 10824 UInt opc2 = ifieldOPClo9( theInstr ); 10825 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 10826 UInt DCM = IFIELD( theInstr, 10, 6 ); 10827 IRTemp DCM_calc = newTemp( Ity_I32 ); 10828 UInt max_exp = 0; 10829 UInt min_exp = 0; 10830 IRTemp min_subnormalD64 = newTemp( Ity_D64 ); 10831 IRTemp min_subnormalD128 = newTemp( Ity_D128 ); 10832 IRTemp significand64 = newTemp( Ity_D64 ); 10833 IRTemp significand128 = newTemp( Ity_D128 ); 10834 IRTemp exp_min_normal = newTemp( Ity_I64 ); 10835 IRTemp exponent = newTemp( Ity_I32 ); 10836 10837 IRTemp infinity_true = newTemp( Ity_I32 ); 10838 IRTemp SNaN_true = newTemp( Ity_I32 ); 10839 IRTemp QNaN_true = newTemp( Ity_I32 ); 10840 IRTemp subnormal_true = newTemp( Ity_I32 ); 10841 IRTemp normal_true = newTemp( Ity_I32 ); 10842 IRTemp extreme_true = newTemp( Ity_I32 ); 10843 IRTemp lmd = newTemp( Ity_I32 ); 10844 IRTemp lmd_zero_true = newTemp( Ity_I32 ); 10845 IRTemp zero_true = newTemp( Ity_I32 ); 10846 IRTemp sign = newTemp( Ity_I32 ); 10847 IRTemp field = newTemp( Ity_I32 ); 10848 IRTemp ccIR_zero = newTemp( Ity_I32 ); 10849 IRTemp ccIR_subnormal = newTemp( Ity_I32 ); 10850 10851 /* UInt size = DFP_LONG; JRS:unused */ 10852 IRTemp gfield = newTemp( Ity_I32 ); 10853 IRTemp gfield_0_4_shift = newTemp( Ity_I8 ); 10854 IRTemp gfield_mask = newTemp( Ity_I32 ); 10855 IRTemp dcm0 = newTemp( Ity_I32 ); 10856 IRTemp dcm1 = newTemp( Ity_I32 ); 10857 IRTemp dcm2 = newTemp( Ity_I32 ); 10858 IRTemp dcm3 = newTemp( Ity_I32 ); 10859 IRTemp dcm4 = newTemp( Ity_I32 ); 10860 IRTemp dcm5 = newTemp( Ity_I32 ); 10861 10862 /* The only difference between the dtstdc and dtstdcq instructions is 10863 * size of the T and G fields. The calculation of the 4 bit field 10864 * is the same. Setup the parameters and values that are DFP size 10865 * specific. The rest of the code is independent of the DFP size. 10866 * 10867 * The Io_CmpD64 is used below. The instruction sets the ccIR values. 10868 * The interpretation of the ccIR values is as follows: 10869 * 10870 * DFP cmp result | IR 10871 * -------------------------- 10872 * UN | 0x45 10873 * EQ | 0x40 10874 * GT | 0x00 10875 * LT | 0x01 10876 */ 10877 10878 assign( frA, getDReg( frA_addr ) ); 10879 assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) ); 10880 10881 assign( abs_frA, unop( Iop_ReinterpI64asD64, 10882 binop( Iop_And64, 10883 unop( Iop_ReinterpD64asI64, 10884 mkexpr( frA ) ), 10885 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) ); 10886 assign( gfield_0_4_shift, mkU8( 31 - 5 ) ); // G-field[0:4] 10887 switch (opc1) { 10888 case 0x3b: // dtstdc, dtstdg 10889 DIP("dtstd%s %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g", 10890 crfD, frA_addr, DCM); 10891 /* setup the parameters for the long format of the two instructions */ 10892 assign( frAI64_lo, mkU64( 0 ) ); 10893 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) ); 10894 max_exp = DFP_LONG_EXP_MAX; 10895 min_exp = DFP_LONG_EXP_MIN; 10896 10897 assign( exponent, unop( Iop_64to32, 10898 unop( Iop_ExtractExpD64, 10899 mkexpr( frA ) ) ) ); 10900 assign( significand64, 10901 unop( Iop_ReinterpI64asD64, 10902 mkU64( 0x2234000000000001ULL ) ) ); // dfp 1.0 10903 assign( exp_min_normal,mkU64( 398 - 383 ) ); 10904 assign( min_subnormalD64, 10905 binop( Iop_InsertExpD64, 10906 mkexpr( exp_min_normal ), 10907 mkexpr( significand64 ) ) ); 10908 10909 assign( ccIR_subnormal, 10910 binop( Iop_CmpD64, 10911 mkexpr( abs_frA ), 10912 mkexpr( min_subnormalD64 ) ) ); 10913 10914 /* compare absolute value of frA with zero */ 10915 assign( ccIR_zero, 10916 binop( Iop_CmpD64, 10917 mkexpr( abs_frA ), 10918 unop( Iop_ReinterpI64asD64, 10919 mkU64( 0x2238000000000000ULL ) ) ) ); 10920 10921 /* size = DFP_LONG; JRS: unused */ 10922 break; 10923 10924 case 0x3F: // dtstdcq, dtstdgq 10925 DIP("dtstd%sq %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g", 10926 crfD, frA_addr, DCM); 10927 /* setup the parameters for the extended format of the 10928 * two instructions 10929 */ 10930 assign( frAI64_lo, unop( Iop_ReinterpD64asI64, 10931 getDReg( frA_addr+1 ) ) ); 10932 10933 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) ); 10934 max_exp = DFP_EXTND_EXP_MAX; 10935 min_exp = DFP_EXTND_EXP_MIN; 10936 assign( exponent, unop( Iop_64to32, 10937 unop( Iop_ExtractExpD128, 10938 getDReg_pair( frA_addr) ) ) ); 10939 10940 /* create quand exponent for minimum normal number */ 10941 assign( exp_min_normal, mkU64( 6176 - 6143 ) ); 10942 assign( significand128, 10943 unop( Iop_D64toD128, 10944 unop( Iop_ReinterpI64asD64, 10945 mkU64( 0x2234000000000001ULL ) ) ) ); // dfp 1.0 10946 10947 assign( min_subnormalD128, 10948 binop( Iop_InsertExpD128, 10949 mkexpr( exp_min_normal ), 10950 mkexpr( significand128 ) ) ); 10951 10952 assign( ccIR_subnormal, 10953 binop( Iop_CmpD128, 10954 binop( Iop_D64HLtoD128, 10955 unop( Iop_ReinterpI64asD64, 10956 binop( Iop_And64, 10957 unop( Iop_ReinterpD64asI64, 10958 mkexpr( frA ) ), 10959 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ), 10960 getDReg( frA_addr+1 ) ), 10961 mkexpr( min_subnormalD128 ) ) ); 10962 assign( ccIR_zero, 10963 binop( Iop_CmpD128, 10964 binop( Iop_D64HLtoD128, 10965 mkexpr( abs_frA ), 10966 getDReg( frA_addr+1 ) ), 10967 unop( Iop_D64toD128, 10968 unop( Iop_ReinterpI64asD64, 10969 mkU64( 0x0ULL ) ) ) ) ); 10970 10971 /* size = DFP_EXTND; JRS:unused */ 10972 break; 10973 default: 10974 vex_printf("dis_dfp_class_test(ppc)(opc2)\n"); 10975 return False; 10976 } 10977 10978 /* The G-field is in the upper 32-bits. The I64 logical operations 10979 * do not seem to be supported in 32-bit mode so keep things as 32-bit 10980 * operations. 10981 */ 10982 assign( gfield, binop( Iop_And32, 10983 mkexpr( gfield_mask ), 10984 unop( Iop_64HIto32, 10985 mkexpr(frAI64_hi) ) ) ); 10986 10987 /* There is a lot of code that is the same to do the class and group 10988 * instructions. Later there is an if statement to handle the specific 10989 * instruction. 10990 * 10991 * Will be using I32 values, compares, shifts and logical operations for 10992 * this code as the 64-bit compare, shifts, logical operations are not 10993 * supported in 32-bit mode. 10994 */ 10995 10996 /* Check the bits for Infinity, QNaN or Signaling NaN */ 10997 assign( infinity_true, 10998 unop( Iop_1Sto32, 10999 binop( Iop_CmpEQ32, 11000 binop( Iop_And32, 11001 mkU32( 0x7C000000 ), 11002 mkexpr( gfield ) ), 11003 mkU32( 0x78000000 ) ) ) ); 11004 11005 assign( SNaN_true, 11006 unop( Iop_1Sto32, 11007 binop( Iop_CmpEQ32, 11008 binop( Iop_And32, 11009 mkU32( 0x7E000000 ), 11010 mkexpr( gfield ) ), 11011 mkU32( 0x7E000000 ) ) ) ); 11012 11013 assign( QNaN_true, 11014 binop( Iop_And32, 11015 unop( Iop_1Sto32, 11016 binop( Iop_CmpEQ32, 11017 binop( Iop_And32, 11018 mkU32( 0x7E000000 ), 11019 mkexpr( gfield ) ), 11020 mkU32( 0x7C000000 ) ) ), 11021 unop( Iop_Not32, 11022 mkexpr( SNaN_true ) ) ) ); 11023 11024 assign( zero_true, 11025 binop( Iop_And32, 11026 unop(Iop_1Sto32, 11027 binop( Iop_CmpEQ32, 11028 mkexpr( ccIR_zero ), 11029 mkU32( 0x40 ) ) ), // ccIR code for Equal 11030 unop( Iop_Not32, 11031 binop( Iop_Or32, 11032 mkexpr( infinity_true ), 11033 binop( Iop_Or32, 11034 mkexpr( QNaN_true ), 11035 mkexpr( SNaN_true ) ) ) ) ) ); 11036 11037 /* Do compare of frA the minimum normal value. Comparison is size 11038 * depenent and was done above to get the ccIR value. 11039 */ 11040 assign( subnormal_true, 11041 binop( Iop_And32, 11042 binop( Iop_Or32, 11043 unop( Iop_1Sto32, 11044 binop( Iop_CmpEQ32, 11045 mkexpr( ccIR_subnormal ), 11046 mkU32( 0x40 ) ) ), // ccIR code for Equal 11047 unop( Iop_1Sto32, 11048 binop( Iop_CmpEQ32, 11049 mkexpr( ccIR_subnormal ), 11050 mkU32( 0x1 ) ) ) ), // ccIR code for LT 11051 unop( Iop_Not32, 11052 binop( Iop_Or32, 11053 binop( Iop_Or32, 11054 mkexpr( infinity_true ), 11055 mkexpr( zero_true) ), 11056 binop( Iop_Or32, 11057 mkexpr( QNaN_true ), 11058 mkexpr( SNaN_true ) ) ) ) ) ); 11059 11060 /* Normal number is not subnormal, infinity, NaN or Zero */ 11061 assign( normal_true, 11062 unop( Iop_Not32, 11063 binop( Iop_Or32, 11064 binop( Iop_Or32, 11065 mkexpr( infinity_true ), 11066 mkexpr( zero_true ) ), 11067 binop( Iop_Or32, 11068 mkexpr( subnormal_true ), 11069 binop( Iop_Or32, 11070 mkexpr( QNaN_true ), 11071 mkexpr( SNaN_true ) ) ) ) ) ); 11072 11073 /* Calculate the DCM bit field based on the tests for the specific 11074 * instruction 11075 */ 11076 if (opc2 == 0xC2) { // dtstdc, dtstdcq 11077 /* DCM[0:5] Bit Data Class definition 11078 * 0 Zero 11079 * 1 Subnormal 11080 * 2 Normal 11081 * 3 Infinity 11082 * 4 Quiet NaN 11083 * 5 Signaling NaN 11084 */ 11085 11086 assign( dcm0, binop( Iop_Shl32, 11087 mkexpr( zero_true ), 11088 mkU8( 5 ) ) ); 11089 assign( dcm1, binop( Iop_Shl32, 11090 binop( Iop_And32, 11091 mkexpr( subnormal_true ), 11092 mkU32( 1 ) ), 11093 mkU8( 4 ) ) ); 11094 assign( dcm2, binop( Iop_Shl32, 11095 binop( Iop_And32, 11096 mkexpr( normal_true ), 11097 mkU32( 1 ) ), 11098 mkU8( 3 ) ) ); 11099 assign( dcm3, binop( Iop_Shl32, 11100 binop( Iop_And32, 11101 mkexpr( infinity_true), 11102 mkU32( 1 ) ), 11103 mkU8( 2 ) ) ); 11104 assign( dcm4, binop( Iop_Shl32, 11105 binop( Iop_And32, 11106 mkexpr( QNaN_true ), 11107 mkU32( 1 ) ), 11108 mkU8( 1 ) ) ); 11109 assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) ); 11110 11111 } else if (opc2 == 0xE2) { // dtstdg, dtstdgq 11112 /* check if the exponent is extreme */ 11113 assign( extreme_true, binop( Iop_Or32, 11114 unop( Iop_1Sto32, 11115 binop( Iop_CmpEQ32, 11116 mkexpr( exponent ), 11117 mkU32( max_exp ) ) ), 11118 unop( Iop_1Sto32, 11119 binop( Iop_CmpEQ32, 11120 mkexpr( exponent ), 11121 mkU32( min_exp ) ) ) ) ); 11122 11123 /* Check if LMD is zero */ 11124 Get_lmd( &lmd, binop( Iop_Shr32, 11125 mkexpr( gfield ), mkU8( 31 - 5 ) ) ); 11126 11127 assign( lmd_zero_true, unop( Iop_1Sto32, 11128 binop( Iop_CmpEQ32, 11129 mkexpr( lmd ), 11130 mkU32( 0 ) ) ) ); 11131 11132 /* DCM[0:5] Bit Data Class definition 11133 * 0 Zero with non-extreme exponent 11134 * 1 Zero with extreme exponent 11135 * 2 Subnormal or (Normal with extreme exponent) 11136 * 3 Normal with non-extreme exponent and 11137 * leftmost zero digit in significand 11138 * 4 Normal with non-extreme exponent and 11139 * leftmost nonzero digit in significand 11140 * 5 Special symbol (Infinity, QNaN, or SNaN) 11141 */ 11142 assign( dcm0, binop( Iop_Shl32, 11143 binop( Iop_And32, 11144 binop( Iop_And32, 11145 unop( Iop_Not32, 11146 mkexpr( extreme_true ) ), 11147 mkexpr( zero_true ) ), 11148 mkU32( 0x1 ) ), 11149 mkU8( 5 ) ) ); 11150 11151 assign( dcm1, binop( Iop_Shl32, 11152 binop( Iop_And32, 11153 binop( Iop_And32, 11154 mkexpr( extreme_true ), 11155 mkexpr( zero_true ) ), 11156 mkU32( 0x1 ) ), 11157 mkU8( 4 ) ) ); 11158 11159 assign( dcm2, binop( Iop_Shl32, 11160 binop( Iop_And32, 11161 binop( Iop_Or32, 11162 binop( Iop_And32, 11163 mkexpr( extreme_true ), 11164 mkexpr( normal_true ) ), 11165 mkexpr( subnormal_true ) ), 11166 mkU32( 0x1 ) ), 11167 mkU8( 3 ) ) ); 11168 11169 assign( dcm3, binop( Iop_Shl32, 11170 binop( Iop_And32, 11171 binop( Iop_And32, 11172 binop( Iop_And32, 11173 unop( Iop_Not32, 11174 mkexpr( extreme_true ) ), 11175 mkexpr( normal_true ) ), 11176 unop( Iop_1Sto32, 11177 binop( Iop_CmpEQ32, 11178 mkexpr( lmd ), 11179 mkU32( 0 ) ) ) ), 11180 mkU32( 0x1 ) ), 11181 mkU8( 2 ) ) ); 11182 11183 assign( dcm4, binop( Iop_Shl32, 11184 binop( Iop_And32, 11185 binop( Iop_And32, 11186 binop( Iop_And32, 11187 unop( Iop_Not32, 11188 mkexpr( extreme_true ) ), 11189 mkexpr( normal_true ) ), 11190 unop( Iop_1Sto32, 11191 binop( Iop_CmpNE32, 11192 mkexpr( lmd ), 11193 mkU32( 0 ) ) ) ), 11194 mkU32( 0x1 ) ), 11195 mkU8( 1 ) ) ); 11196 11197 assign( dcm5, binop( Iop_And32, 11198 binop( Iop_Or32, 11199 mkexpr( SNaN_true), 11200 binop( Iop_Or32, 11201 mkexpr( QNaN_true), 11202 mkexpr( infinity_true) ) ), 11203 mkU32( 0x1 ) ) ); 11204 } 11205 11206 /* create DCM field */ 11207 assign( DCM_calc, 11208 binop( Iop_Or32, 11209 mkexpr( dcm0 ), 11210 binop( Iop_Or32, 11211 mkexpr( dcm1 ), 11212 binop( Iop_Or32, 11213 mkexpr( dcm2 ), 11214 binop( Iop_Or32, 11215 mkexpr( dcm3 ), 11216 binop( Iop_Or32, 11217 mkexpr( dcm4 ), 11218 mkexpr( dcm5 ) ) ) ) ) ) ); 11219 11220 /* Get the sign of the DFP number, ignore sign for QNaN */ 11221 assign( sign, 11222 unop( Iop_1Uto32, 11223 binop( Iop_CmpEQ32, 11224 binop( Iop_Shr32, 11225 unop( Iop_64HIto32, mkexpr( frAI64_hi ) ), 11226 mkU8( 63 - 32 ) ), 11227 mkU32( 1 ) ) ) ); 11228 11229 /* This instruction generates a four bit field to be stored in the 11230 * condition code register. The condition code register consists of 7 11231 * fields. The field to be written to is specified by the BF (AKA crfD) 11232 * field. 11233 * 11234 * The field layout is as follows: 11235 * 11236 * Field Meaning 11237 * 0000 Operand positive with no match 11238 * 0100 Operand positive with at least one match 11239 * 0001 Operand negative with no match 11240 * 0101 Operand negative with at least one match 11241 */ 11242 assign( field, binop( Iop_Or32, 11243 binop( Iop_Shl32, 11244 mkexpr( sign ), 11245 mkU8( 3 ) ), 11246 binop( Iop_Shl32, 11247 unop( Iop_1Uto32, 11248 binop( Iop_CmpNE32, 11249 binop( Iop_And32, 11250 mkU32( DCM ), 11251 mkexpr( DCM_calc ) ), 11252 mkU32( 0 ) ) ), 11253 mkU8( 1 ) ) ) ); 11254 11255 putGST_field( PPC_GST_CR, mkexpr( field ), crfD ); 11256 return True; 11257 } 11258 11259 static Bool dis_dfp_bcd(UInt theInstr) { 11260 UInt opc2 = ifieldOPClo10( theInstr ); 11261 ULong sp = IFIELD(theInstr, 19, 2); 11262 ULong s = IFIELD(theInstr, 20, 1); 11263 UChar frT_addr = ifieldRegDS( theInstr ); 11264 UChar frB_addr = ifieldRegB( theInstr ); 11265 IRTemp frB = newTemp( Ity_D64 ); 11266 IRTemp frBI64 = newTemp( Ity_I64 ); 11267 IRTemp result = newTemp( Ity_I64 ); 11268 IRTemp resultD64 = newTemp( Ity_D64 ); 11269 IRTemp bcd64 = newTemp( Ity_I64 ); 11270 IRTemp bcd_u = newTemp( Ity_I32 ); 11271 IRTemp bcd_l = newTemp( Ity_I32 ); 11272 IRTemp dbcd_u = newTemp( Ity_I32 ); 11273 IRTemp dbcd_l = newTemp( Ity_I32 ); 11274 IRTemp lmd = newTemp( Ity_I32 ); 11275 11276 assign( frB, getDReg( frB_addr ) ); 11277 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 11278 11279 switch ( opc2 ) { 11280 case 0x142: // ddedpd DFP Decode DPD to BCD 11281 DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 11282 11283 assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 11284 assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) ); 11285 assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) ); 11286 11287 if ( ( sp == 0 ) || ( sp == 1 ) ) { 11288 /* Unsigned BCD string */ 11289 Get_lmd( &lmd, 11290 binop( Iop_Shr32, 11291 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11292 mkU8( 31 - 5 ) ) ); // G-field[0:4] 11293 11294 assign( result, 11295 binop( Iop_32HLto64, 11296 binop( Iop_Or32, 11297 binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ), 11298 mkexpr( bcd_u ) ), 11299 mkexpr( bcd_l ) ) ); 11300 11301 } else { 11302 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 11303 * the positive and negative values are encoded in the least 11304 * significant bits. 11305 */ 11306 IRTemp sign = newTemp( Ity_I32 ); 11307 11308 if (sp == 2) { 11309 /* Positive sign = 0xC, negative sign = 0xD */ 11310 11311 assign( sign, 11312 binop( Iop_Or32, 11313 binop( Iop_Shr32, 11314 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11315 mkU8( 31 ) ), 11316 mkU32( 0xC ) ) ); 11317 11318 } else if ( sp == 3 ) { 11319 /* Positive sign = 0xF, negative sign = 0xD */ 11320 IRTemp tmp32 = newTemp( Ity_I32 ); 11321 11322 /* Complement sign bit then OR into bit position 1 */ 11323 assign( tmp32, 11324 binop( Iop_Xor32, 11325 binop( Iop_Shr32, 11326 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11327 mkU8( 30 ) ), 11328 mkU32( 0x2 ) ) ); 11329 11330 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 11331 11332 } else { 11333 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 11334 } 11335 11336 /* Put sign in bottom 4 bits, move most significant 4-bits from 11337 * bcd_l to bcd_u. 11338 */ 11339 assign( result, 11340 binop( Iop_32HLto64, 11341 binop( Iop_Or32, 11342 binop( Iop_Shr32, 11343 mkexpr( bcd_l ), 11344 mkU8( 28 ) ), 11345 binop( Iop_Shl32, 11346 mkexpr( bcd_u ), 11347 mkU8( 4 ) ) ), 11348 binop( Iop_Or32, 11349 mkexpr( sign ), 11350 binop( Iop_Shl32, 11351 mkexpr( bcd_l ), 11352 mkU8( 4 ) ) ) ) ); 11353 } 11354 11355 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) ); 11356 break; 11357 11358 case 0x342: // denbcd DFP Encode BCD to DPD 11359 { 11360 IRTemp valid_mask = newTemp( Ity_I32 ); 11361 IRTemp invalid_mask = newTemp( Ity_I32 ); 11362 IRTemp without_lmd = newTemp( Ity_I64 ); 11363 IRTemp tmp64 = newTemp( Ity_I64 ); 11364 IRTemp dbcd64 = newTemp( Ity_I64 ); 11365 IRTemp left_exp = newTemp( Ity_I32 ); 11366 IRTemp g0_4 = newTemp( Ity_I32 ); 11367 11368 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 11369 11370 if ( s == 0 ) { 11371 /* Unsigned BCD string */ 11372 assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) ); 11373 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) ); 11374 assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) ); 11375 11376 assign( lmd, 11377 binop( Iop_Shr32, 11378 binop( Iop_And32, 11379 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11380 mkU32( 0xF0000000 ) ), 11381 mkU8( 28 ) ) ); 11382 11383 assign( invalid_mask, 11384 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11385 unop( Iop_64to32, mkexpr( frBI64 ) ) ) ); 11386 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 11387 11388 assign( without_lmd, 11389 unop( Iop_ReinterpD64asI64, 11390 binop( Iop_InsertExpD64, 11391 mkU64( DFP_LONG_BIAS ), 11392 unop( Iop_ReinterpI64asD64, 11393 binop( Iop_32HLto64, 11394 mkexpr( dbcd_u ), 11395 mkexpr( dbcd_l ) ) ) ) ) ); 11396 assign( left_exp, 11397 binop( Iop_Shr32, 11398 binop( Iop_And32, 11399 unop( Iop_64HIto32, mkexpr( without_lmd ) ), 11400 mkU32( 0x60000000 ) ), 11401 mkU8( 29 ) ) ); 11402 11403 assign( g0_4, 11404 binop( Iop_Shl32, 11405 Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ), 11406 mkU8( 26 ) ) ); 11407 11408 assign( tmp64, 11409 binop( Iop_32HLto64, 11410 binop( Iop_Or32, 11411 binop( Iop_And32, 11412 unop( Iop_64HIto32, 11413 mkexpr( without_lmd ) ), 11414 mkU32( 0x83FFFFFF ) ), 11415 mkexpr( g0_4 ) ), 11416 unop( Iop_64to32, mkexpr( without_lmd ) ) ) ); 11417 11418 } else if ( s == 1 ) { 11419 IRTemp sign = newTemp( Ity_I32 ); 11420 IRTemp sign_bit = newTemp( Ity_I32 ); 11421 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 11422 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 11423 IRTemp tmp = newTemp( Ity_I64 ); 11424 11425 /* Signed BCD string, least significant 4 bits are sign bits 11426 * positive sign = 0xC, negative sign = 0xD 11427 */ 11428 assign( tmp, unop( Iop_BCDtoDPB, 11429 binop( Iop_32HLto64, 11430 binop( Iop_Shr32, 11431 unop( Iop_64HIto32, 11432 mkexpr( frBI64 ) ), 11433 mkU8( 4 ) ), 11434 binop( Iop_Or32, 11435 binop( Iop_Shr32, 11436 unop( Iop_64to32, 11437 mkexpr( frBI64 ) ), 11438 mkU8( 4 ) ), 11439 binop( Iop_Shl32, 11440 unop( Iop_64HIto32, 11441 mkexpr( frBI64 ) ), 11442 mkU8( 28 ) ) ) ) ) ); 11443 11444 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) ); 11445 assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) ); 11446 11447 /* Get the sign of the BCD string. */ 11448 assign( sign, 11449 binop( Iop_And32, 11450 unop( Iop_64to32, mkexpr( frBI64 ) ), 11451 mkU32( 0xF ) ) ); 11452 11453 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 11454 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 11455 assign( sign_bit, 11456 Generate_sign_bit( mkexpr( pos_sign_mask ), 11457 mkexpr( neg_sign_mask ) ) ); 11458 11459 /* Check for invalid sign and BCD digit. Don't check the bottom 11460 * four bits of bcd_l as that is the sign value. 11461 */ 11462 assign( invalid_mask, 11463 Generate_inv_mask( 11464 bcd_digit_inval( unop( Iop_64HIto32, 11465 mkexpr( frBI64 ) ), 11466 binop( Iop_Shr32, 11467 unop( Iop_64to32, 11468 mkexpr( frBI64 ) ), 11469 mkU8( 4 ) ) ), 11470 mkexpr( pos_sign_mask ), 11471 mkexpr( neg_sign_mask ) ) ); 11472 11473 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 11474 11475 /* Generate the result assuming the sign value was valid. */ 11476 assign( tmp64, 11477 unop( Iop_ReinterpD64asI64, 11478 binop( Iop_InsertExpD64, 11479 mkU64( DFP_LONG_BIAS ), 11480 unop( Iop_ReinterpI64asD64, 11481 binop( Iop_32HLto64, 11482 binop( Iop_Or32, 11483 mkexpr( dbcd_u ), 11484 mkexpr( sign_bit ) ), 11485 mkexpr( dbcd_l ) ) ) ) ) ); 11486 } 11487 11488 /* Generate the value to store depending on the validity of the 11489 * sign value and the validity of the BCD digits. 11490 */ 11491 assign( resultD64, 11492 unop( Iop_ReinterpI64asD64, 11493 binop( Iop_32HLto64, 11494 binop( Iop_Or32, 11495 binop( Iop_And32, 11496 mkexpr( valid_mask ), 11497 unop( Iop_64HIto32, 11498 mkexpr( tmp64 ) ) ), 11499 binop( Iop_And32, 11500 mkU32( 0x7C000000 ), 11501 mkexpr( invalid_mask ) ) ), 11502 binop( Iop_Or32, 11503 binop( Iop_And32, 11504 mkexpr( valid_mask ), 11505 unop( Iop_64to32, mkexpr( tmp64 ) ) ), 11506 binop( Iop_And32, 11507 mkU32( 0x0 ), 11508 mkexpr( invalid_mask ) ) ) ) ) ); 11509 putDReg( frT_addr, mkexpr( resultD64 ) ); 11510 } 11511 break; 11512 default: 11513 vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " ); 11514 return False; 11515 } 11516 return True; 11517 } 11518 11519 static Bool dis_dfp_bcdq( UInt theInstr ) 11520 { 11521 UInt opc2 = ifieldOPClo10( theInstr ); 11522 ULong sp = IFIELD(theInstr, 19, 2); 11523 ULong s = IFIELD(theInstr, 20, 1); 11524 IRTemp frB_hi = newTemp( Ity_D64 ); 11525 IRTemp frB_lo = newTemp( Ity_D64 ); 11526 IRTemp frBI64_hi = newTemp( Ity_I64 ); 11527 IRTemp frBI64_lo = newTemp( Ity_I64 ); 11528 UChar frT_addr = ifieldRegDS( theInstr ); 11529 UChar frB_addr = ifieldRegB( theInstr ); 11530 11531 IRTemp lmd = newTemp( Ity_I32 ); 11532 IRTemp result_hi = newTemp( Ity_I64 ); 11533 IRTemp result_lo = newTemp( Ity_I64 ); 11534 11535 assign( frB_hi, getDReg( frB_addr ) ); 11536 assign( frB_lo, getDReg( frB_addr + 1 ) ); 11537 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 11538 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 11539 11540 switch ( opc2 ) { 11541 case 0x142: // ddedpdq DFP Decode DPD to BCD 11542 { 11543 IRTemp low_60_u = newTemp( Ity_I32 ); 11544 IRTemp low_60_l = newTemp( Ity_I32 ); 11545 IRTemp mid_60_u = newTemp( Ity_I32 ); 11546 IRTemp mid_60_l = newTemp( Ity_I32 ); 11547 IRTemp top_12_l = newTemp( Ity_I32 ); 11548 11549 DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr ); 11550 11551 /* Note, instruction only stores the lower 32 BCD digits in 11552 * the result 11553 */ 11554 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 11555 mkexpr( frBI64_lo ), 11556 &top_12_l, 11557 &mid_60_u, 11558 &mid_60_l, 11559 &low_60_u, 11560 &low_60_l ); 11561 11562 if ( ( sp == 0 ) || ( sp == 1 ) ) { 11563 /* Unsigned BCD string */ 11564 assign( result_hi, 11565 binop( Iop_32HLto64, 11566 binop( Iop_Or32, 11567 binop( Iop_Shl32, 11568 mkexpr( top_12_l ), 11569 mkU8( 24 ) ), 11570 binop( Iop_Shr32, 11571 mkexpr( mid_60_u ), 11572 mkU8( 4 ) ) ), 11573 binop( Iop_Or32, 11574 binop( Iop_Shl32, 11575 mkexpr( mid_60_u ), 11576 mkU8( 28 ) ), 11577 binop( Iop_Shr32, 11578 mkexpr( mid_60_l ), 11579 mkU8( 4 ) ) ) ) ); 11580 11581 assign( result_lo, 11582 binop( Iop_32HLto64, 11583 binop( Iop_Or32, 11584 binop( Iop_Shl32, 11585 mkexpr( mid_60_l ), 11586 mkU8( 28 ) ), 11587 mkexpr( low_60_u ) ), 11588 mkexpr( low_60_l ) ) ); 11589 11590 } else { 11591 /* Signed BCD string, the cases for sp 2 and 3 only differ in how 11592 * the positive and negative values are encoded in the least 11593 * significant bits. 11594 */ 11595 IRTemp sign = newTemp( Ity_I32 ); 11596 11597 if ( sp == 2 ) { 11598 /* Positive sign = 0xC, negative sign = 0xD */ 11599 assign( sign, 11600 binop( Iop_Or32, 11601 binop( Iop_Shr32, 11602 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 11603 mkU8( 31 ) ), 11604 mkU32( 0xC ) ) ); 11605 11606 } else if ( sp == 3 ) { 11607 IRTemp tmp32 = newTemp( Ity_I32 ); 11608 11609 /* Positive sign = 0xF, negative sign = 0xD. 11610 * Need to complement sign bit then OR into bit position 1. 11611 */ 11612 assign( tmp32, 11613 binop( Iop_Xor32, 11614 binop( Iop_Shr32, 11615 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 11616 mkU8( 30 ) ), 11617 mkU32( 0x2 ) ) ); 11618 11619 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) ); 11620 11621 } else { 11622 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" ); 11623 } 11624 11625 assign( result_hi, 11626 binop( Iop_32HLto64, 11627 binop( Iop_Or32, 11628 binop( Iop_Shl32, 11629 mkexpr( top_12_l ), 11630 mkU8( 28 ) ), 11631 mkexpr( mid_60_u ) ), 11632 mkexpr( mid_60_l ) ) ); 11633 11634 assign( result_lo, 11635 binop( Iop_32HLto64, 11636 binop( Iop_Or32, 11637 binop( Iop_Shl32, 11638 mkexpr( low_60_u ), 11639 mkU8( 4 ) ), 11640 binop( Iop_Shr32, 11641 mkexpr( low_60_l ), 11642 mkU8( 28 ) ) ), 11643 binop( Iop_Or32, 11644 binop( Iop_Shl32, 11645 mkexpr( low_60_l ), 11646 mkU8( 4 ) ), 11647 mkexpr( sign ) ) ) ); 11648 } 11649 11650 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 11651 putDReg( frT_addr + 1, 11652 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 11653 } 11654 break; 11655 case 0x342: // denbcdq DFP Encode BCD to DPD 11656 { 11657 IRTemp valid_mask = newTemp( Ity_I32 ); 11658 IRTemp invalid_mask = newTemp( Ity_I32 ); 11659 IRTemp result128 = newTemp( Ity_D128 ); 11660 IRTemp dfp_significand = newTemp( Ity_D128 ); 11661 IRTemp tmp_hi = newTemp( Ity_I64 ); 11662 IRTemp tmp_lo = newTemp( Ity_I64 ); 11663 IRTemp dbcd_top_l = newTemp( Ity_I32 ); 11664 IRTemp dbcd_mid_u = newTemp( Ity_I32 ); 11665 IRTemp dbcd_mid_l = newTemp( Ity_I32 ); 11666 IRTemp dbcd_low_u = newTemp( Ity_I32 ); 11667 IRTemp dbcd_low_l = newTemp( Ity_I32 ); 11668 IRTemp bcd_top_8 = newTemp( Ity_I64 ); 11669 IRTemp bcd_mid_60 = newTemp( Ity_I64 ); 11670 IRTemp bcd_low_60 = newTemp( Ity_I64 ); 11671 IRTemp sign_bit = newTemp( Ity_I32 ); 11672 IRTemp tmptop10 = newTemp( Ity_I64 ); 11673 IRTemp tmpmid50 = newTemp( Ity_I64 ); 11674 IRTemp tmplow50 = newTemp( Ity_I64 ); 11675 IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 ); 11676 11677 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr ); 11678 11679 if ( s == 0 ) { 11680 /* Unsigned BCD string */ 11681 assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string 11682 11683 assign( bcd_top_8, 11684 binop( Iop_32HLto64, 11685 mkU32( 0 ), 11686 binop( Iop_And32, 11687 binop( Iop_Shr32, 11688 unop( Iop_64HIto32, 11689 mkexpr( frBI64_hi ) ), 11690 mkU8( 24 ) ), 11691 mkU32( 0xFF ) ) ) ); 11692 assign( bcd_mid_60, 11693 binop( Iop_32HLto64, 11694 binop( Iop_Or32, 11695 binop( Iop_Shr32, 11696 unop( Iop_64to32, 11697 mkexpr( frBI64_hi ) ), 11698 mkU8( 28 ) ), 11699 binop( Iop_Shl32, 11700 unop( Iop_64HIto32, 11701 mkexpr( frBI64_hi ) ), 11702 mkU8( 4 ) ) ), 11703 binop( Iop_Or32, 11704 binop( Iop_Shl32, 11705 unop( Iop_64to32, 11706 mkexpr( frBI64_hi ) ), 11707 mkU8( 4 ) ), 11708 binop( Iop_Shr32, 11709 unop( Iop_64HIto32, 11710 mkexpr( frBI64_lo ) ), 11711 mkU8( 28 ) ) ) ) ); 11712 11713 /* Note, the various helper functions ignores top 4-bits */ 11714 assign( bcd_low_60, mkexpr( frBI64_lo ) ); 11715 11716 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) ); 11717 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 11718 11719 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) ); 11720 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 11721 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 11722 11723 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 11724 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 11725 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 11726 11727 /* The entire BCD string fits in lower 110-bits. The LMD = 0, 11728 * value is not part of the final result. Only the right most 11729 * BCD digits are stored. 11730 */ 11731 assign( lmd, mkU32( 0 ) ); 11732 11733 assign( invalid_mask, 11734 binop( Iop_Or32, 11735 bcd_digit_inval( mkU32( 0 ), 11736 unop( Iop_64to32, 11737 mkexpr( bcd_top_8 ) ) ), 11738 binop( Iop_Or32, 11739 bcd_digit_inval( unop( Iop_64HIto32, 11740 mkexpr( bcd_mid_60 ) ), 11741 unop( Iop_64to32, 11742 mkexpr( bcd_mid_60 ) ) ), 11743 bcd_digit_inval( unop( Iop_64HIto32, 11744 mkexpr( bcd_low_60 ) ), 11745 unop( Iop_64to32, 11746 mkexpr( bcd_low_60 ) ) 11747 ) ) ) ); 11748 11749 } else if ( s == 1 ) { 11750 IRTemp sign = newTemp( Ity_I32 ); 11751 IRTemp zero = newTemp( Ity_I32 ); 11752 IRTemp pos_sign_mask = newTemp( Ity_I32 ); 11753 IRTemp neg_sign_mask = newTemp( Ity_I32 ); 11754 11755 /* The sign of the BCD string is stored in lower 4 bits */ 11756 assign( sign, 11757 binop( Iop_And32, 11758 unop( Iop_64to32, mkexpr( frBI64_lo ) ), 11759 mkU32( 0xF ) ) ); 11760 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) ); 11761 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) ); 11762 assign( sign_bit, 11763 Generate_sign_bit( mkexpr( pos_sign_mask ), 11764 mkexpr( neg_sign_mask ) ) ); 11765 11766 /* Generate the value assuminig the sign and BCD digits are vaild */ 11767 assign( bcd_top_8, 11768 binop( Iop_32HLto64, 11769 mkU32( 0x0 ), 11770 binop( Iop_Shr32, 11771 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 11772 mkU8( 28 ) ) ) ); 11773 11774 /* The various helper routines ignore the upper 4-bits */ 11775 assign( bcd_mid_60, mkexpr( frBI64_hi ) ); 11776 11777 /* Remove bottom four sign bits */ 11778 assign( bcd_low_60, 11779 binop( Iop_32HLto64, 11780 binop( Iop_Shr32, 11781 unop( Iop_64HIto32, 11782 mkexpr( frBI64_lo ) ), 11783 mkU8( 4 ) ), 11784 binop( Iop_Or32, 11785 binop( Iop_Shl32, 11786 unop( Iop_64HIto32, 11787 mkexpr( frBI64_lo ) ), 11788 mkU8( 28 ) ), 11789 binop( Iop_Shr32, 11790 unop( Iop_64to32, 11791 mkexpr( frBI64_lo ) ), 11792 mkU8( 4 ) ) ) ) ); 11793 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) ); 11794 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) ); 11795 11796 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) ); 11797 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) ); 11798 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) ); 11799 11800 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) ); 11801 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) ); 11802 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) ); 11803 11804 /* The entire BCD string fits in lower 110-bits. The LMD value 11805 * is not stored in the final result for the DFP Long instruction. 11806 */ 11807 assign( lmd, mkU32( 0 ) ); 11808 11809 /* Check for invalid sign and invalid BCD digit. Don't check the 11810 * bottom four bits of frBI64_lo as that is the sign value. 11811 */ 11812 assign( zero, mkU32( 0 ) ); 11813 assign( inval_bcd_digit_mask, 11814 binop( Iop_Or32, 11815 bcd_digit_inval( mkexpr( zero ), 11816 unop( Iop_64to32, 11817 mkexpr( bcd_top_8 ) ) ), 11818 binop( Iop_Or32, 11819 bcd_digit_inval( unop( Iop_64HIto32, 11820 mkexpr( bcd_mid_60 ) ), 11821 unop( Iop_64to32, 11822 mkexpr( bcd_mid_60 ) ) ), 11823 bcd_digit_inval( unop( Iop_64HIto32, 11824 mkexpr( frBI64_lo ) ), 11825 binop( Iop_Shr32, 11826 unop( Iop_64to32, 11827 mkexpr( frBI64_lo ) ), 11828 mkU8( 4 ) ) ) ) ) ); 11829 assign( invalid_mask, 11830 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ), 11831 mkexpr( pos_sign_mask ), 11832 mkexpr( neg_sign_mask ) ) ); 11833 11834 } 11835 11836 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) ); 11837 11838 /* Calculate the value of the result assuming sign and BCD digits 11839 * are all valid. 11840 */ 11841 assign( dfp_significand, 11842 binop( Iop_D64HLtoD128, 11843 unop( Iop_ReinterpI64asD64, 11844 binop( Iop_32HLto64, 11845 binop( Iop_Or32, 11846 mkexpr( sign_bit ), 11847 mkexpr( dbcd_top_l ) ), 11848 binop( Iop_Or32, 11849 binop( Iop_Shl32, 11850 mkexpr( dbcd_mid_u ), 11851 mkU8( 18 ) ), 11852 binop( Iop_Shr32, 11853 mkexpr( dbcd_mid_l ), 11854 mkU8( 14 ) ) ) ) ), 11855 unop( Iop_ReinterpI64asD64, 11856 binop( Iop_32HLto64, 11857 binop( Iop_Or32, 11858 mkexpr( dbcd_low_u ), 11859 binop( Iop_Shl32, 11860 mkexpr( dbcd_mid_l ), 11861 mkU8( 18 ) ) ), 11862 mkexpr( dbcd_low_l ) ) ) ) ); 11863 11864 /* Break the result back down to 32-bit chunks and replace chunks. 11865 * If there was an invalid BCD digit or invalid sign value, replace 11866 * the calculated result with the invalid bit string. 11867 */ 11868 assign( result128, 11869 binop( Iop_InsertExpD128, 11870 mkU64( DFP_EXTND_BIAS ), 11871 mkexpr( dfp_significand ) ) ); 11872 11873 assign( tmp_hi, 11874 unop( Iop_ReinterpD64asI64, 11875 unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) ); 11876 11877 assign( tmp_lo, 11878 unop( Iop_ReinterpD64asI64, 11879 unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) ); 11880 11881 assign( result_hi, 11882 binop( Iop_32HLto64, 11883 binop( Iop_Or32, 11884 binop( Iop_And32, 11885 mkexpr( valid_mask ), 11886 unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ), 11887 binop( Iop_And32, 11888 mkU32( 0x7C000000 ), 11889 mkexpr( invalid_mask ) ) ), 11890 binop( Iop_Or32, 11891 binop( Iop_And32, 11892 mkexpr( valid_mask ), 11893 unop( Iop_64to32, mkexpr( tmp_hi ) ) ), 11894 binop( Iop_And32, 11895 mkU32( 0x0 ), 11896 mkexpr( invalid_mask ) ) ) ) ); 11897 11898 assign( result_lo, 11899 binop( Iop_32HLto64, 11900 binop( Iop_Or32, 11901 binop( Iop_And32, 11902 mkexpr( valid_mask ), 11903 unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ), 11904 binop( Iop_And32, 11905 mkU32( 0x0 ), 11906 mkexpr( invalid_mask ) ) ), 11907 binop( Iop_Or32, 11908 binop( Iop_And32, 11909 mkexpr( valid_mask ), 11910 unop( Iop_64to32, mkexpr( tmp_lo ) ) ), 11911 binop( Iop_And32, 11912 mkU32( 0x0 ), 11913 mkexpr( invalid_mask ) ) ) ) ); 11914 11915 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) ); 11916 putDReg( frT_addr + 1, 11917 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) ); 11918 11919 } 11920 break; 11921 default: 11922 vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " ); 11923 break; 11924 } 11925 return True; 11926 } 11927 11928 static Bool dis_dfp_significant_digits( UInt theInstr ) 11929 { 11930 UChar frA_addr = ifieldRegA( theInstr ); 11931 UChar frB_addr = ifieldRegB( theInstr ); 11932 IRTemp frA = newTemp( Ity_D64 ); 11933 UInt opc1 = ifieldOPC( theInstr ); 11934 IRTemp B_sig = newTemp( Ity_I8 ); 11935 IRTemp K = newTemp( Ity_I8 ); 11936 IRTemp lmd_B = newTemp( Ity_I32 ); 11937 IRTemp field = newTemp( Ity_I32 ); 11938 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF 11939 IRTemp Unordered_true = newTemp( Ity_I32 ); 11940 IRTemp Eq_true_mask = newTemp( Ity_I32 ); 11941 IRTemp Lt_true_mask = newTemp( Ity_I32 ); 11942 IRTemp Gt_true_mask = newTemp( Ity_I32 ); 11943 IRTemp KisZero_true_mask = newTemp( Ity_I32 ); 11944 IRTemp KisZero_false_mask = newTemp( Ity_I32 ); 11945 11946 /* Get the reference singificance stored in frA */ 11947 assign( frA, getDReg( frA_addr ) ); 11948 11949 /* Convert from 64 bit to 8 bits in two steps. The Iop_64to8 is not 11950 * supported in 32-bit mode. 11951 */ 11952 assign( K, unop( Iop_32to8, 11953 binop( Iop_And32, 11954 unop( Iop_64to32, 11955 unop( Iop_ReinterpD64asI64, 11956 mkexpr( frA ) ) ), 11957 mkU32( 0x3F ) ) ) ); 11958 11959 switch ( opc1 ) { 11960 case 0x3b: // dtstsf DFP Test Significance 11961 { 11962 IRTemp frB = newTemp( Ity_D64 ); 11963 IRTemp frBI64 = newTemp( Ity_I64 ); 11964 IRTemp B_bcd_u = newTemp( Ity_I32 ); 11965 IRTemp B_bcd_l = newTemp( Ity_I32 ); 11966 IRTemp tmp64 = newTemp( Ity_I64 ); 11967 11968 DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 11969 11970 assign( frB, getDReg( frB_addr ) ); 11971 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ); 11972 11973 /* Get the BCD string for the value stored in a series of I32 values. 11974 * Count the number of leading zeros. Subtract the number of leading 11975 * zeros from 16 (maximum number of significant digits in DFP 11976 * Long). 11977 */ 11978 Get_lmd( &lmd_B, 11979 binop( Iop_Shr32, 11980 unop( Iop_64HIto32, mkexpr( frBI64 ) ), 11981 mkU8( 31 - 5 ) ) ); // G-field[0:4] 11982 11983 assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) ); 11984 assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) ); 11985 assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) ); 11986 11987 assign( B_sig, 11988 binop( Iop_Sub8, 11989 mkU8( DFP_LONG_MAX_SIG_DIGITS ), 11990 Count_leading_zeros_60( mkexpr( lmd_B ), 11991 mkexpr( B_bcd_u ), 11992 mkexpr( B_bcd_l ) ) ) ); 11993 assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) ); 11994 } 11995 break; 11996 case 0x3F: // dtstsfq DFP Test Significance 11997 { 11998 IRTemp frB_hi = newTemp( Ity_D64 ); 11999 IRTemp frB_lo = newTemp( Ity_D64 ); 12000 IRTemp frBI64_hi = newTemp( Ity_I64 ); 12001 IRTemp frBI64_lo = newTemp( Ity_I64 ); 12002 IRTemp B_low_60_u = newTemp( Ity_I32 ); 12003 IRTemp B_low_60_l = newTemp( Ity_I32 ); 12004 IRTemp B_mid_60_u = newTemp( Ity_I32 ); 12005 IRTemp B_mid_60_l = newTemp( Ity_I32 ); 12006 IRTemp B_top_12_l = newTemp( Ity_I32 ); 12007 12008 DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr ); 12009 12010 assign( frB_hi, getDReg( frB_addr ) ); 12011 assign( frB_lo, getDReg( frB_addr + 1 ) ); 12012 12013 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) ); 12014 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) ); 12015 12016 /* Get the BCD string for the value stored in a series of I32 values. 12017 * Count the number of leading zeros. Subtract the number of leading 12018 * zeros from 32 (maximum number of significant digits in DFP 12019 * extended). 12020 */ 12021 Get_lmd( &lmd_B, 12022 binop( Iop_Shr32, 12023 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ), 12024 mkU8( 31 - 5 ) ) ); // G-field[0:4] 12025 12026 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ), 12027 mkexpr( frBI64_lo ), 12028 &B_top_12_l, 12029 &B_mid_60_u, 12030 &B_mid_60_l, 12031 &B_low_60_u, 12032 &B_low_60_l ); 12033 12034 assign( B_sig, 12035 binop( Iop_Sub8, 12036 mkU8( DFP_EXTND_MAX_SIG_DIGITS ), 12037 Count_leading_zeros_128( mkexpr( lmd_B ), 12038 mkexpr( B_top_12_l ), 12039 mkexpr( B_mid_60_u ), 12040 mkexpr( B_mid_60_l ), 12041 mkexpr( B_low_60_u ), 12042 mkexpr( B_low_60_l ) ) ) ); 12043 12044 assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) ); 12045 } 12046 break; 12047 } 12048 12049 /* Compare (16 - cnt[0]) against K and set the condition code field 12050 * accordingly. 12051 * 12052 * The field layout is as follows: 12053 * 12054 * bit[3:0] Description 12055 * 3 K != 0 and K < Number of significant digits if FRB 12056 * 2 K != 0 and K > Number of significant digits if FRB OR K = 0 12057 * 1 K != 0 and K = Number of significant digits if FRB 12058 * 0 K ? Number of significant digits if FRB 12059 */ 12060 assign( Eq_true_mask, 12061 unop( Iop_1Sto32, 12062 binop( Iop_CmpEQ32, 12063 unop( Iop_8Uto32, mkexpr( K ) ), 12064 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 12065 assign( Lt_true_mask, 12066 unop( Iop_1Sto32, 12067 binop( Iop_CmpLT32U, 12068 unop( Iop_8Uto32, mkexpr( K ) ), 12069 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) ); 12070 assign( Gt_true_mask, 12071 unop( Iop_1Sto32, 12072 binop( Iop_CmpLT32U, 12073 unop( Iop_8Uto32, mkexpr( B_sig ) ), 12074 unop( Iop_8Uto32, mkexpr( K ) ) ) ) ); 12075 12076 assign( KisZero_true_mask, 12077 unop( Iop_1Sto32, 12078 binop( Iop_CmpEQ32, 12079 unop( Iop_8Uto32, mkexpr( K ) ), 12080 mkU32( 0 ) ) ) ); 12081 assign( KisZero_false_mask, 12082 unop( Iop_1Sto32, 12083 binop( Iop_CmpNE32, 12084 unop( Iop_8Uto32, mkexpr( K ) ), 12085 mkU32( 0 ) ) ) ); 12086 12087 assign( field, 12088 binop( Iop_Or32, 12089 binop( Iop_And32, 12090 mkexpr( KisZero_false_mask ), 12091 binop( Iop_Or32, 12092 binop( Iop_And32, 12093 mkexpr( Lt_true_mask ), 12094 mkU32( 0x8 ) ), 12095 binop( Iop_Or32, 12096 binop( Iop_And32, 12097 mkexpr( Gt_true_mask ), 12098 mkU32( 0x4 ) ), 12099 binop( Iop_And32, 12100 mkexpr( Eq_true_mask ), 12101 mkU32( 0x2 ) ) ) ) ), 12102 binop( Iop_And32, 12103 mkexpr( KisZero_true_mask ), 12104 mkU32( 0x4 ) ) ) ); 12105 12106 putGST_field( PPC_GST_CR, 12107 binop( Iop_Or32, 12108 binop( Iop_And32, 12109 mkexpr( Unordered_true ), 12110 mkU32( 0x1 ) ), 12111 binop( Iop_And32, 12112 unop( Iop_Not32, mkexpr( Unordered_true ) ), 12113 mkexpr( field ) ) ), 12114 crfD ); 12115 12116 return True; 12117 } 12118 12119 /*------------------------------------------------------------*/ 12120 /*--- AltiVec Instruction Translation ---*/ 12121 /*------------------------------------------------------------*/ 12122 12123 /* 12124 Altivec Cache Control Instructions (Data Streams) 12125 */ 12126 static Bool dis_av_datastream ( UInt theInstr ) 12127 { 12128 /* X-Form */ 12129 UChar opc1 = ifieldOPC(theInstr); 12130 UChar flag_T = toUChar( IFIELD( theInstr, 25, 1 ) ); 12131 UChar flag_A = flag_T; 12132 UChar b23to24 = toUChar( IFIELD( theInstr, 23, 2 ) ); 12133 UChar STRM = toUChar( IFIELD( theInstr, 21, 2 ) ); 12134 UChar rA_addr = ifieldRegA(theInstr); 12135 UChar rB_addr = ifieldRegB(theInstr); 12136 UInt opc2 = ifieldOPClo10(theInstr); 12137 UChar b0 = ifieldBIT0(theInstr); 12138 12139 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) { 12140 vex_printf("dis_av_datastream(ppc)(instr)\n"); 12141 return False; 12142 } 12143 12144 switch (opc2) { 12145 case 0x156: // dst (Data Stream Touch, AV p115) 12146 DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "", 12147 rA_addr, rB_addr, STRM); 12148 break; 12149 12150 case 0x176: // dstst (Data Stream Touch for Store, AV p117) 12151 DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "", 12152 rA_addr, rB_addr, STRM); 12153 break; 12154 12155 case 0x336: // dss (Data Stream Stop, AV p114) 12156 if (rA_addr != 0 || rB_addr != 0) { 12157 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n"); 12158 return False; 12159 } 12160 if (flag_A == 0) { 12161 DIP("dss %d\n", STRM); 12162 } else { 12163 DIP("dssall\n"); 12164 } 12165 break; 12166 12167 default: 12168 vex_printf("dis_av_datastream(ppc)(opc2)\n"); 12169 return False; 12170 } 12171 return True; 12172 } 12173 12174 /* 12175 AltiVec Processor Control Instructions 12176 */ 12177 static Bool dis_av_procctl ( UInt theInstr ) 12178 { 12179 /* VX-Form */ 12180 UChar opc1 = ifieldOPC(theInstr); 12181 UChar vD_addr = ifieldRegDS(theInstr); 12182 UChar vA_addr = ifieldRegA(theInstr); 12183 UChar vB_addr = ifieldRegB(theInstr); 12184 UInt opc2 = IFIELD( theInstr, 0, 11 ); 12185 12186 if (opc1 != 0x4) { 12187 vex_printf("dis_av_procctl(ppc)(instr)\n"); 12188 return False; 12189 } 12190 12191 switch (opc2) { 12192 case 0x604: // mfvscr (Move from VSCR, AV p129) 12193 if (vA_addr != 0 || vB_addr != 0) { 12194 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 12195 return False; 12196 } 12197 DIP("mfvscr v%d\n", vD_addr); 12198 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) ); 12199 break; 12200 12201 case 0x644: { // mtvscr (Move to VSCR, AV p130) 12202 IRTemp vB = newTemp(Ity_V128); 12203 if (vD_addr != 0 || vA_addr != 0) { 12204 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n"); 12205 return False; 12206 } 12207 DIP("mtvscr v%d\n", vB_addr); 12208 assign( vB, getVReg(vB_addr)); 12209 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) ); 12210 break; 12211 } 12212 default: 12213 vex_printf("dis_av_procctl(ppc)(opc2)\n"); 12214 return False; 12215 } 12216 return True; 12217 } 12218 12219 /* 12220 * VSX scalar and vector convert instructions 12221 */ 12222 static Bool 12223 dis_vx_conv ( UInt theInstr, UInt opc2 ) 12224 { 12225 /* XX2-Form */ 12226 UChar opc1 = ifieldOPC( theInstr ); 12227 UChar XT = ifieldRegXT( theInstr ); 12228 UChar XB = ifieldRegXB( theInstr ); 12229 IRTemp xB, xB2; 12230 IRTemp b3, b2, b1, b0; 12231 xB = xB2 = IRTemp_INVALID; 12232 12233 if (opc1 != 0x3C) { 12234 vex_printf( "dis_vx_conv(ppc)(instr)\n" ); 12235 return False; 12236 } 12237 12238 /* Create and assign temps only as needed for the given instruction. */ 12239 switch (opc2) { 12240 // scalar double-precision floating point argument 12241 case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090: 12242 xB = newTemp(Ity_F64); 12243 assign( xB, 12244 unop( Iop_ReinterpI64asF64, 12245 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12246 break; 12247 // vector double-precision floating point arguments 12248 case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0: 12249 12250 xB = newTemp(Ity_F64); 12251 xB2 = newTemp(Ity_F64); 12252 assign( xB, 12253 unop( Iop_ReinterpI64asF64, 12254 unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12255 assign( xB2, 12256 unop( Iop_ReinterpI64asF64, 12257 unop( Iop_V128to64, getVSReg( XB ) ) ) ); 12258 break; 12259 // vector single precision or [un]signed integer word arguments 12260 case 0x130: case 0x392: case 0x330: case 0x310: case 0x110: 12261 case 0x1f0: case 0x1d0: 12262 b3 = b2 = b1 = b0 = IRTemp_INVALID; 12263 breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0); 12264 break; 12265 // vector [un]signed integer doubleword argument 12266 case 0x3f0: case 0x370: case 0x3d0: case 0x350: 12267 xB = newTemp(Ity_I64); 12268 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 12269 xB2 = newTemp(Ity_I64); 12270 assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) ); 12271 break; 12272 // scalar [un]signed integer doubleword argument 12273 case 0x250: case 0x270: case 0x2D0: case 0x2F0: 12274 xB = newTemp(Ity_I64); 12275 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 12276 break; 12277 // scalar single precision argument 12278 case 0x292: // xscvspdp 12279 xB = newTemp(Ity_I32); 12280 12281 assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32, 12282 unop( Iop_V128HIto64, 12283 getVSReg( XB ) ) ) ) ); 12284 break; 12285 case 0x296: // xscvspdpn (non signaling version of xscvpdp) 12286 xB = newTemp(Ity_I32); 12287 assign( xB, 12288 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) ); 12289 break; 12290 12291 /* Certain instructions have their complete implementation in the main switch statement 12292 * that follows this one; thus we have a "do nothing" case for those instructions here. 12293 */ 12294 case 0x170: case 0x150: 12295 break; // do nothing 12296 12297 default: 12298 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 12299 return False; 12300 } 12301 12302 12303 switch (opc2) { 12304 case 0x2B0: 12305 // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert 12306 // to Signed Integer Doubleword format with Saturate) 12307 DIP("xscvdpsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12308 putVSReg( XT, 12309 binop( Iop_64HLtoV128, binop( Iop_F64toI64S, 12310 mkU32( Irrm_ZERO ), 12311 mkexpr( xB ) ), mkU64( 0 ) ) ); 12312 break; 12313 case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and 12314 // Convert to Signed Integer Word format with Saturate) 12315 DIP("xscvdpsxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12316 putVSReg( XT, 12317 binop( Iop_64HLtoV128, 12318 unop( Iop_32Sto64, 12319 binop( Iop_F64toI32S, 12320 mkU32( Irrm_ZERO ), 12321 mkexpr( xB ) ) ), 12322 mkU64( 0ULL ) ) ); 12323 break; 12324 case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert 12325 // to Unsigned Integer Doubleword format with Saturate) 12326 DIP("xscvdpuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12327 putVSReg( XT, 12328 binop( Iop_64HLtoV128, 12329 binop( Iop_F64toI64U, 12330 mkU32( Irrm_ZERO ), 12331 mkexpr( xB ) ), 12332 mkU64( 0ULL ) ) ); 12333 break; 12334 case 0x270: 12335 // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword 12336 // to Single-Precision format) 12337 DIP("xscvsxdsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12338 putVSReg( XT, 12339 binop( Iop_64HLtoV128, 12340 unop( Iop_ReinterpF64asI64, 12341 binop( Iop_RoundF64toF32, 12342 get_IR_roundingmode(), 12343 binop( Iop_I64StoF64, 12344 get_IR_roundingmode(), 12345 mkexpr( xB ) ) ) ), 12346 mkU64( 0 ) ) ); 12347 break; 12348 case 0x2F0: 12349 // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to 12350 // Double-Precision format) 12351 DIP("xscvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12352 putVSReg( XT, 12353 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 12354 binop( Iop_I64StoF64, get_IR_roundingmode(), 12355 mkexpr( xB ) ) ), 12356 mkU64( 0 ) ) ); 12357 break; 12358 case 0x250: 12359 // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer 12360 // Doubleword to Singel-Precision format) 12361 DIP("xscvuxdsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12362 putVSReg( XT, 12363 binop( Iop_64HLtoV128, 12364 unop( Iop_ReinterpF64asI64, 12365 binop( Iop_RoundF64toF32, 12366 get_IR_roundingmode(), 12367 binop( Iop_I64UtoF64, 12368 get_IR_roundingmode(), 12369 mkexpr( xB ) ) ) ), 12370 mkU64( 0 ) ) ); 12371 break; 12372 case 0x2D0: 12373 // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to 12374 // Double-Precision format) 12375 DIP("xscvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12376 putVSReg( XT, 12377 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 12378 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12379 mkexpr( xB ) ) ), 12380 mkU64( 0 ) ) ); 12381 break; 12382 case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert 12383 // to Signed Integer Word format with Saturate) 12384 { 12385 IRTemp hiResult_32 = newTemp(Ity_I32); 12386 IRTemp loResult_32 = newTemp(Ity_I32); 12387 IRExpr* rmZero = mkU32(Irrm_ZERO); 12388 12389 DIP("xvcvdpsxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12390 assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB))); 12391 assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2))); 12392 putVSReg( XT, 12393 binop( Iop_64HLtoV128, 12394 unop( Iop_32Sto64, mkexpr( hiResult_32 ) ), 12395 unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) ); 12396 break; 12397 } 12398 case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws 12399 // (VSX Vector truncate Single-Precision to integer and 12400 // Convert to [Un]signed Integer Word format with Saturate) 12401 { 12402 IRExpr * b0_result, * b1_result, * b2_result, * b3_result; 12403 IRTemp tempResult = newTemp(Ity_V128); 12404 IRTemp res0 = newTemp(Ity_I32); 12405 IRTemp res1 = newTemp(Ity_I32); 12406 IRTemp res2 = newTemp(Ity_I32); 12407 IRTemp res3 = newTemp(Ity_I32); 12408 IRTemp hi64 = newTemp(Ity_I64); 12409 IRTemp lo64 = newTemp(Ity_I64); 12410 Bool un_signed = (opc2 == 0x110); 12411 IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ; 12412 12413 DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB); 12414 /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN, 12415 * then result is set to 0x80000000. */ 12416 assign(tempResult, unop(op, getVSReg(XB))); 12417 assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) ); 12418 assign( lo64, unop(Iop_V128to64, mkexpr(tempResult)) ); 12419 assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) ); 12420 assign( res2, unop(Iop_64to32, mkexpr(hi64)) ); 12421 assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) ); 12422 assign( res0, unop(Iop_64to32, mkexpr(lo64)) ); 12423 12424 b3_result = IRExpr_ITE(is_NaN_32(b3), 12425 // then: result is 0x{8|0}80000000 12426 mkU32(un_signed ? 0x00000000 : 0x80000000), 12427 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12428 mkexpr(res3)); 12429 b2_result = IRExpr_ITE(is_NaN_32(b2), 12430 // then: result is 0x{8|0}80000000 12431 mkU32(un_signed ? 0x00000000 : 0x80000000), 12432 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12433 mkexpr(res2)); 12434 b1_result = IRExpr_ITE(is_NaN_32(b1), 12435 // then: result is 0x{8|0}80000000 12436 mkU32(un_signed ? 0x00000000 : 0x80000000), 12437 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12438 mkexpr(res1)); 12439 b0_result = IRExpr_ITE(is_NaN_32(b0), 12440 // then: result is 0x{8|0}80000000 12441 mkU32(un_signed ? 0x00000000 : 0x80000000), 12442 // else: result is from the Iop_QFtoI32{s|u}x4_RZ 12443 mkexpr(res0)); 12444 12445 putVSReg( XT, 12446 binop( Iop_64HLtoV128, 12447 binop( Iop_32HLto64, b3_result, b2_result ), 12448 binop( Iop_32HLto64, b1_result, b0_result ) ) ); 12449 break; 12450 } 12451 case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and 12452 // Convert to Single-Precision format 12453 DIP("xscvdpsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12454 putVSReg( XT, 12455 binop( Iop_64HLtoV128, 12456 binop( Iop_32HLto64, 12457 unop( Iop_ReinterpF32asI32, 12458 unop( Iop_TruncF64asF32, 12459 binop( Iop_RoundF64toF32, 12460 get_IR_roundingmode(), 12461 mkexpr( xB ) ) ) ), 12462 mkU32( 0 ) ), 12463 mkU64( 0ULL ) ) ); 12464 break; 12465 case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to 12466 vector Single-Precision non-signalling */ 12467 DIP("xscvdpspn v%u,v%u\n", (UInt)XT, (UInt)XB); 12468 putVSReg( XT, 12469 binop( Iop_64HLtoV128, 12470 binop( Iop_32HLto64, 12471 unop( Iop_ReinterpF32asI32, 12472 unop( Iop_TruncF64asF32, 12473 mkexpr( xB ) ) ), 12474 mkU32( 0 ) ), 12475 mkU64( 0ULL ) ) ); 12476 break; 12477 case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer 12478 // and Convert to Unsigned Integer Word format with Saturate) 12479 DIP("xscvdpuxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12480 putVSReg( XT, 12481 binop( Iop_64HLtoV128, 12482 binop( Iop_32HLto64, 12483 mkU32( 0 ), 12484 binop( Iop_F64toI32U, 12485 mkU32( Irrm_ZERO ), 12486 mkexpr( xB ) ) ), 12487 mkU64( 0ULL ) ) ); 12488 break; 12489 case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling) 12490 DIP("xscvspdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12491 putVSReg( XT, 12492 binop( Iop_64HLtoV128, 12493 unop( Iop_ReinterpF64asI64, 12494 unop( Iop_F32toF64, 12495 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 12496 mkU64( 0ULL ) ) ); 12497 break; 12498 case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling) 12499 DIP("xscvspdpn v%u,v%u\n", (UInt)XT, (UInt)XB); 12500 putVSReg( XT, 12501 binop( Iop_64HLtoV128, 12502 unop( Iop_ReinterpF64asI64, 12503 unop( Iop_F32toF64, 12504 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ), 12505 mkU64( 0ULL ) ) ); 12506 break; 12507 case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision 12508 // and Convert to Single-Precision format) 12509 DIP("xvcvdpsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12510 putVSReg( XT, 12511 binop( Iop_64HLtoV128, 12512 binop( Iop_32HLto64, 12513 unop( Iop_ReinterpF32asI32, 12514 unop( Iop_TruncF64asF32, 12515 binop( Iop_RoundF64toF32, 12516 get_IR_roundingmode(), 12517 mkexpr( xB ) ) ) ), 12518 mkU32( 0 ) ), 12519 binop( Iop_32HLto64, 12520 unop( Iop_ReinterpF32asI32, 12521 unop( Iop_TruncF64asF32, 12522 binop( Iop_RoundF64toF32, 12523 get_IR_roundingmode(), 12524 mkexpr( xB2 ) ) ) ), 12525 mkU32( 0 ) ) ) ); 12526 break; 12527 case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer 12528 // and Convert to Unsigned Integer Doubleword format 12529 // with Saturate) 12530 DIP("xvcvdpuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12531 putVSReg( XT, 12532 binop( Iop_64HLtoV128, 12533 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 12534 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 12535 break; 12536 case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and 12537 // Convert to Unsigned Integer Word format with Saturate) 12538 DIP("xvcvdpuxws v%u,v%u\n", (UInt)XT, (UInt)XB); 12539 putVSReg( XT, 12540 binop( Iop_64HLtoV128, 12541 binop( Iop_32HLto64, 12542 binop( Iop_F64toI32U, 12543 mkU32( Irrm_ZERO ), 12544 mkexpr( xB ) ), 12545 mkU32( 0 ) ), 12546 binop( Iop_32HLto64, 12547 binop( Iop_F64toI32U, 12548 mkU32( Irrm_ZERO ), 12549 mkexpr( xB2 ) ), 12550 mkU32( 0 ) ) ) ); 12551 break; 12552 case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format) 12553 DIP("xvcvspdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12554 putVSReg( XT, 12555 binop( Iop_64HLtoV128, 12556 unop( Iop_ReinterpF64asI64, 12557 unop( Iop_F32toF64, 12558 unop( Iop_ReinterpI32asF32, 12559 handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ), 12560 unop( Iop_ReinterpF64asI64, 12561 unop( Iop_F32toF64, 12562 unop( Iop_ReinterpI32asF32, 12563 handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) ); 12564 break; 12565 case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and 12566 // Convert to Signed Integer Doubleword format with Saturate) 12567 DIP("xvcvspsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12568 putVSReg( XT, 12569 binop( Iop_64HLtoV128, 12570 binop( Iop_F64toI64S, 12571 mkU32( Irrm_ZERO ), 12572 unop( Iop_F32toF64, 12573 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 12574 binop( Iop_F64toI64S, 12575 mkU32( Irrm_ZERO ), 12576 unop( Iop_F32toF64, 12577 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 12578 break; 12579 case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and 12580 // Convert to Unsigned Integer Doubleword format with Saturate) 12581 DIP("xvcvspuxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12582 putVSReg( XT, 12583 binop( Iop_64HLtoV128, 12584 binop( Iop_F64toI64U, 12585 mkU32( Irrm_ZERO ), 12586 unop( Iop_F32toF64, 12587 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ), 12588 binop( Iop_F64toI64U, 12589 mkU32( Irrm_ZERO ), 12590 unop( Iop_F32toF64, 12591 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) ); 12592 break; 12593 case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and 12594 // Convert to Signed Integer Doubleword format with Saturate) 12595 DIP("xvcvdpsxds v%u,v%u\n", (UInt)XT, (UInt)XB); 12596 putVSReg( XT, 12597 binop( Iop_64HLtoV128, 12598 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ), 12599 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) ); 12600 break; 12601 case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword 12602 // to Double-Precision format) 12603 DIP("xvcvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12604 putVSReg( XT, 12605 binop( Iop_64HLtoV128, 12606 unop( Iop_ReinterpF64asI64, 12607 binop( Iop_I64StoF64, 12608 get_IR_roundingmode(), 12609 mkexpr( xB ) ) ), 12610 unop( Iop_ReinterpF64asI64, 12611 binop( Iop_I64StoF64, 12612 get_IR_roundingmode(), 12613 mkexpr( xB2 ) ) ) ) ); 12614 break; 12615 case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword 12616 // to Double-Precision format) 12617 DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12618 putVSReg( XT, 12619 binop( Iop_64HLtoV128, 12620 unop( Iop_ReinterpF64asI64, 12621 binop( Iop_I64UtoF64, 12622 get_IR_roundingmode(), 12623 mkexpr( xB ) ) ), 12624 unop( Iop_ReinterpF64asI64, 12625 binop( Iop_I64UtoF64, 12626 get_IR_roundingmode(), 12627 mkexpr( xB2 ) ) ) ) ); 12628 12629 break; 12630 case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword 12631 // to Single-Precision format) 12632 DIP("xvcvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12633 putVSReg( XT, 12634 binop( Iop_64HLtoV128, 12635 binop( Iop_32HLto64, 12636 unop( Iop_ReinterpF32asI32, 12637 unop( Iop_TruncF64asF32, 12638 binop( Iop_RoundF64toF32, 12639 get_IR_roundingmode(), 12640 binop( Iop_I64StoF64, 12641 get_IR_roundingmode(), 12642 mkexpr( xB ) ) ) ) ), 12643 mkU32( 0 ) ), 12644 binop( Iop_32HLto64, 12645 unop( Iop_ReinterpF32asI32, 12646 unop( Iop_TruncF64asF32, 12647 binop( Iop_RoundF64toF32, 12648 get_IR_roundingmode(), 12649 binop( Iop_I64StoF64, 12650 get_IR_roundingmode(), 12651 mkexpr( xB2 ) ) ) ) ), 12652 mkU32( 0 ) ) ) ); 12653 break; 12654 case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword 12655 // to Single-Precision format) 12656 DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB); 12657 putVSReg( XT, 12658 binop( Iop_64HLtoV128, 12659 binop( Iop_32HLto64, 12660 unop( Iop_ReinterpF32asI32, 12661 unop( Iop_TruncF64asF32, 12662 binop( Iop_RoundF64toF32, 12663 get_IR_roundingmode(), 12664 binop( Iop_I64UtoF64, 12665 get_IR_roundingmode(), 12666 mkexpr( xB ) ) ) ) ), 12667 mkU32( 0 ) ), 12668 binop( Iop_32HLto64, 12669 unop( Iop_ReinterpF32asI32, 12670 unop( Iop_TruncF64asF32, 12671 binop( Iop_RoundF64toF32, 12672 get_IR_roundingmode(), 12673 binop( Iop_I64UtoF64, 12674 get_IR_roundingmode(), 12675 mkexpr( xB2 ) ) ) ) ), 12676 mkU32( 0 ) ) ) ); 12677 break; 12678 12679 case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format) 12680 DIP("xvcvsxwdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12681 putVSReg( XT, 12682 binop( Iop_64HLtoV128, 12683 unop( Iop_ReinterpF64asI64, 12684 binop( Iop_I64StoF64, get_IR_roundingmode(), 12685 unop( Iop_32Sto64, mkexpr( b3 ) ) ) ), 12686 unop( Iop_ReinterpF64asI64, 12687 binop( Iop_I64StoF64, get_IR_roundingmode(), 12688 unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) ); 12689 break; 12690 case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format) 12691 DIP("xvcvuxwdp v%u,v%u\n", (UInt)XT, (UInt)XB); 12692 putVSReg( XT, 12693 binop( Iop_64HLtoV128, 12694 unop( Iop_ReinterpF64asI64, 12695 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12696 unop( Iop_32Uto64, mkexpr( b3 ) ) ) ), 12697 unop( Iop_ReinterpF64asI64, 12698 binop( Iop_I64UtoF64, get_IR_roundingmode(), 12699 unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) ); 12700 break; 12701 case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format) 12702 DIP("xvcvsxwsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12703 putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) ); 12704 break; 12705 case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format) 12706 DIP("xvcvuxwsp v%u,v%u\n", (UInt)XT, (UInt)XB); 12707 putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) ); 12708 break; 12709 12710 default: 12711 vex_printf( "dis_vx_conv(ppc)(opc2)\n" ); 12712 return False; 12713 } 12714 return True; 12715 } 12716 12717 /* 12718 * VSX vector Double Precision Floating Point Arithmetic Instructions 12719 */ 12720 static Bool 12721 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 ) 12722 { 12723 /* XX3-Form */ 12724 UChar opc1 = ifieldOPC( theInstr ); 12725 UChar XT = ifieldRegXT( theInstr ); 12726 UChar XA = ifieldRegXA( theInstr ); 12727 UChar XB = ifieldRegXB( theInstr ); 12728 IRExpr* rm = get_IR_roundingmode(); 12729 IRTemp frA = newTemp(Ity_F64); 12730 IRTemp frB = newTemp(Ity_F64); 12731 IRTemp frA2 = newTemp(Ity_F64); 12732 IRTemp frB2 = newTemp(Ity_F64); 12733 12734 if (opc1 != 0x3C) { 12735 vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" ); 12736 return False; 12737 } 12738 12739 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 12740 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 12741 assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA )))); 12742 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB )))); 12743 12744 switch (opc2) { 12745 case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision) 12746 case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision) 12747 case 0x180: // xvadddp (VSX Vector Add Double-Precision) 12748 case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision) 12749 { 12750 IROp mOp; 12751 const HChar * oper_name; 12752 switch (opc2) { 12753 case 0x1E0: 12754 mOp = Iop_DivF64; 12755 oper_name = "div"; 12756 break; 12757 case 0x1C0: 12758 mOp = Iop_MulF64; 12759 oper_name = "mul"; 12760 break; 12761 case 0x180: 12762 mOp = Iop_AddF64; 12763 oper_name = "add"; 12764 break; 12765 case 0x1A0: 12766 mOp = Iop_SubF64; 12767 oper_name = "sub"; 12768 break; 12769 12770 default: 12771 vpanic("The impossible happened: dis_vxv_dp_arith(ppc)"); 12772 } 12773 IRTemp hiResult = newTemp(Ity_I64); 12774 IRTemp loResult = newTemp(Ity_I64); 12775 DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB); 12776 12777 assign( hiResult, 12778 unop( Iop_ReinterpF64asI64, 12779 triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) ); 12780 assign( loResult, 12781 unop( Iop_ReinterpF64asI64, 12782 triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) ); 12783 putVSReg( XT, 12784 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 12785 break; 12786 } 12787 case 0x196: // xvsqrtdp 12788 { 12789 IRTemp hiResult = newTemp(Ity_I64); 12790 IRTemp loResult = newTemp(Ity_I64); 12791 DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 12792 12793 assign( hiResult, 12794 unop( Iop_ReinterpF64asI64, 12795 binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) ); 12796 assign( loResult, 12797 unop( Iop_ReinterpF64asI64, 12798 binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) ); 12799 putVSReg( XT, 12800 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 12801 break; 12802 } 12803 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision) 12804 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision) 12805 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision) 12806 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision) 12807 { 12808 /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . . 12809 * XT == FRC 12810 * XA == FRA 12811 * XB == FRB 12812 * 12813 * and for xvm{add|sub}adp . . . 12814 * XT == FRB 12815 * XA == FRA 12816 * XB == FRC 12817 */ 12818 Bool negate; 12819 IROp mOp = Iop_INVALID; 12820 const HChar * oper_name = NULL; 12821 Bool mdp = False; 12822 12823 switch (opc2) { 12824 case 0x184: case 0x1A4: 12825 case 0x384: case 0x3A4: 12826 mOp = Iop_MAddF64; 12827 oper_name = "add"; 12828 mdp = (opc2 & 0x0FF) == 0x0A4; 12829 break; 12830 12831 case 0x1C4: case 0x1E4: 12832 case 0x3C4: case 0x3E4: 12833 mOp = Iop_MSubF64; 12834 oper_name = "sub"; 12835 mdp = (opc2 & 0x0FF) == 0x0E4; 12836 break; 12837 12838 default: 12839 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 12840 } 12841 12842 switch (opc2) { 12843 case 0x384: case 0x3A4: 12844 case 0x3C4: case 0x3E4: 12845 negate = True; 12846 break; 12847 default: 12848 negate = False; 12849 } 12850 IRTemp hiResult = newTemp(Ity_I64); 12851 IRTemp loResult = newTemp(Ity_I64); 12852 IRTemp frT = newTemp(Ity_F64); 12853 IRTemp frT2 = newTemp(Ity_F64); 12854 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp", 12855 (UInt)XT, (UInt)XA, (UInt)XB); 12856 assign(frT, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) ); 12857 assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) ); 12858 12859 assign( hiResult, 12860 unop( Iop_ReinterpF64asI64, 12861 qop( mOp, 12862 rm, 12863 mkexpr( frA ), 12864 mkexpr( mdp ? frT : frB ), 12865 mkexpr( mdp ? frB : frT ) ) ) ); 12866 assign( loResult, 12867 unop( Iop_ReinterpF64asI64, 12868 qop( mOp, 12869 rm, 12870 mkexpr( frA2 ), 12871 mkexpr( mdp ? frT2 : frB2 ), 12872 mkexpr( mdp ? frB2 : frT2 ) ) ) ); 12873 putVSReg( XT, 12874 binop( Iop_64HLtoV128, 12875 mkexpr( negate ? getNegatedResult( hiResult ) 12876 : hiResult ), 12877 mkexpr( negate ? getNegatedResult( loResult ) 12878 : loResult ) ) ); 12879 break; 12880 } 12881 case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision) 12882 { 12883 IRTemp frBHi_I64 = newTemp(Ity_I64); 12884 IRTemp frBLo_I64 = newTemp(Ity_I64); 12885 IRTemp flagsHi = newTemp(Ity_I32); 12886 IRTemp flagsLo = newTemp(Ity_I32); 12887 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 12888 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 12889 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 12890 12891 DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB); 12892 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 12893 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 12894 do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi); 12895 do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo); 12896 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 12897 * where fl_flag == 1 on ppc64. 12898 */ 12899 assign( flagsHi, 12900 binop( Iop_Or32, 12901 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12902 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 12903 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 12904 assign( flagsLo, 12905 binop( Iop_Or32, 12906 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12907 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 12908 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 12909 putGST_field( PPC_GST_CR, 12910 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 12911 crfD ); 12912 break; 12913 } 12914 case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision) 12915 { 12916 IRTemp frBHi_I64 = newTemp(Ity_I64); 12917 IRTemp frBLo_I64 = newTemp(Ity_I64); 12918 IRTemp frAHi_I64 = newTemp(Ity_I64); 12919 IRTemp frALo_I64 = newTemp(Ity_I64); 12920 IRTemp flagsHi = newTemp(Ity_I32); 12921 IRTemp flagsLo = newTemp(Ity_I32); 12922 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 12923 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo; 12924 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID; 12925 12926 DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB); 12927 assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) ); 12928 assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) ); 12929 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 12930 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) ); 12931 12932 _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi); 12933 _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo); 12934 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 12935 * where fl_flag == 1 on ppc64. 12936 */ 12937 assign( flagsHi, 12938 binop( Iop_Or32, 12939 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12940 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ), 12941 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) ); 12942 assign( flagsLo, 12943 binop( Iop_Or32, 12944 binop( Iop_Or32, mkU32( 8 ), // fl_flag 12945 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ), 12946 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) ); 12947 putGST_field( PPC_GST_CR, 12948 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ), 12949 crfD ); 12950 break; 12951 } 12952 12953 default: 12954 vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" ); 12955 return False; 12956 } 12957 return True; 12958 } 12959 12960 /* 12961 * VSX vector Single Precision Floating Point Arithmetic Instructions 12962 */ 12963 static Bool 12964 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 ) 12965 { 12966 /* XX3-Form */ 12967 UChar opc1 = ifieldOPC( theInstr ); 12968 UChar XT = ifieldRegXT( theInstr ); 12969 UChar XA = ifieldRegXA( theInstr ); 12970 UChar XB = ifieldRegXB( theInstr ); 12971 IRExpr* rm = get_IR_roundingmode(); 12972 IRTemp a3, a2, a1, a0; 12973 IRTemp b3, b2, b1, b0; 12974 IRTemp res0 = newTemp(Ity_I32); 12975 IRTemp res1 = newTemp(Ity_I32); 12976 IRTemp res2 = newTemp(Ity_I32); 12977 IRTemp res3 = newTemp(Ity_I32); 12978 12979 a3 = a2 = a1 = a0 = IRTemp_INVALID; 12980 b3 = b2 = b1 = b0 = IRTemp_INVALID; 12981 12982 if (opc1 != 0x3C) { 12983 vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" ); 12984 return False; 12985 } 12986 12987 switch (opc2) { 12988 case 0x100: // xvaddsp (VSX Vector Add Single-Precision) 12989 DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 12990 // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4 12991 putVSReg( XT, triop(Iop_Add32Fx4, rm, 12992 getVSReg( XA ), getVSReg( XB )) ); 12993 break; 12994 12995 case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision) 12996 DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 12997 // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4 12998 putVSReg( XT, triop(Iop_Mul32Fx4, rm, 12999 getVSReg( XA ), getVSReg( XB )) ); 13000 break; 13001 13002 case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision) 13003 DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13004 // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4 13005 putVSReg( XT, triop(Iop_Sub32Fx4, rm, 13006 getVSReg( XA ), getVSReg( XB )) ); 13007 break; 13008 13009 case 0x160: // xvdivsp (VSX Vector Divide Single-Precision) 13010 { 13011 /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c. 13012 * So there are two choices: 13013 * 1. Implement the xvdivsp with a native insn; or 13014 * 2. Extract the 4 single precision floats from each vector 13015 * register inputs and perform fdivs on each pair 13016 * I will do the latter, due to the general philosophy of 13017 * reusing existing implementations when practical. 13018 */ 13019 DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13020 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13021 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13022 13023 assign( res0, 13024 unop( Iop_ReinterpF32asI32, 13025 unop( Iop_TruncF64asF32, 13026 triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) ); 13027 assign( res1, 13028 unop( Iop_ReinterpF32asI32, 13029 unop( Iop_TruncF64asF32, 13030 triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) ); 13031 assign( res2, 13032 unop( Iop_ReinterpF32asI32, 13033 unop( Iop_TruncF64asF32, 13034 triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) ); 13035 assign( res3, 13036 unop( Iop_ReinterpF32asI32, 13037 unop( Iop_TruncF64asF32, 13038 triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) ); 13039 13040 putVSReg( XT, 13041 binop( Iop_64HLtoV128, 13042 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13043 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13044 break; 13045 } 13046 case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision) 13047 { 13048 DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB); 13049 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13050 /* Note: The native xvsqrtsp insruction does not always give the same precision 13051 * as what we get with Iop_SqrtF64. But it doesn't seem worthwhile to implement 13052 * an Iop_SqrtF32 that would give us a lower precision result, albeit more true 13053 * to the actual instruction. 13054 */ 13055 13056 assign( res0, 13057 unop( Iop_ReinterpF32asI32, 13058 unop( Iop_TruncF64asF32, 13059 binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) ); 13060 assign( res1, 13061 unop( Iop_ReinterpF32asI32, 13062 unop( Iop_TruncF64asF32, 13063 binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) ); 13064 assign( res2, 13065 unop( Iop_ReinterpF32asI32, 13066 unop( Iop_TruncF64asF32, 13067 binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) ); 13068 assign( res3, 13069 unop( Iop_ReinterpF32asI32, 13070 unop( Iop_TruncF64asF32, 13071 binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) ); 13072 13073 putVSReg( XT, 13074 binop( Iop_64HLtoV128, 13075 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13076 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13077 break; 13078 } 13079 13080 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision) 13081 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision) 13082 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision) 13083 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision) 13084 { 13085 IRTemp t3, t2, t1, t0; 13086 Bool msp = False; 13087 Bool negate; 13088 const HChar * oper_name = NULL; 13089 IROp mOp = Iop_INVALID; 13090 switch (opc2) { 13091 case 0x104: case 0x124: 13092 case 0x304: case 0x324: 13093 msp = (opc2 & 0x0FF) == 0x024; 13094 mOp = Iop_MAddF64r32; 13095 oper_name = "madd"; 13096 break; 13097 13098 case 0x144: case 0x164: 13099 case 0x344: case 0x364: 13100 msp = (opc2 & 0x0FF) == 0x064; 13101 mOp = Iop_MSubF64r32; 13102 oper_name = "sub"; 13103 break; 13104 13105 default: 13106 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)"); 13107 } 13108 13109 switch (opc2) { 13110 case 0x304: case 0x324: 13111 case 0x344: case 0x364: 13112 negate = True; 13113 break; 13114 13115 default: 13116 negate = False; 13117 } 13118 13119 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp", 13120 (UInt)XT, (UInt)XA, (UInt)XB); 13121 13122 t3 = t2 = t1 = t0 = IRTemp_INVALID; 13123 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13124 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13125 breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 ); 13126 13127 assign( res0, 13128 unop( Iop_ReinterpF32asI32, 13129 unop( Iop_TruncF64asF32, 13130 qop( mOp, 13131 rm, 13132 mkexpr( a0 ), 13133 mkexpr( msp ? t0 : b0 ), 13134 mkexpr( msp ? b0 : t0 ) ) ) ) ); 13135 assign( res1, 13136 unop( Iop_ReinterpF32asI32, 13137 unop( Iop_TruncF64asF32, 13138 qop( mOp, 13139 rm, 13140 mkexpr( a1 ), 13141 mkexpr( msp ? t1 : b1 ), 13142 mkexpr( msp ? b1 : t1 ) ) ) ) ); 13143 assign( res2, 13144 unop( Iop_ReinterpF32asI32, 13145 unop( Iop_TruncF64asF32, 13146 qop( mOp, 13147 rm, 13148 mkexpr( a2 ), 13149 mkexpr( msp ? t2 : b2 ), 13150 mkexpr( msp ? b2 : t2 ) ) ) ) ); 13151 assign( res3, 13152 unop( Iop_ReinterpF32asI32, 13153 unop( Iop_TruncF64asF32, 13154 qop( mOp, 13155 rm, 13156 mkexpr( a3 ), 13157 mkexpr( msp ? t3 : b3 ), 13158 mkexpr( msp ? b3 : t3 ) ) ) ) ); 13159 13160 putVSReg( XT, 13161 binop( Iop_64HLtoV128, 13162 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ), 13163 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ), 13164 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ), 13165 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) ); 13166 13167 break; 13168 } 13169 case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision) 13170 { 13171 IRTemp flags0 = newTemp(Ity_I32); 13172 IRTemp flags1 = newTemp(Ity_I32); 13173 IRTemp flags2 = newTemp(Ity_I32); 13174 IRTemp flags3 = newTemp(Ity_I32); 13175 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13176 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 13177 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 13178 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 13179 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 13180 DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB); 13181 13182 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13183 do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0); 13184 do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1); 13185 do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2); 13186 do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3); 13187 13188 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13189 * where fl_flag == 1 on ppc64. 13190 */ 13191 assign( flags0, 13192 binop( Iop_Or32, 13193 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13194 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 13195 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 13196 assign( flags1, 13197 binop( Iop_Or32, 13198 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13199 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 13200 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 13201 assign( flags2, 13202 binop( Iop_Or32, 13203 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13204 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 13205 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 13206 assign( flags3, 13207 binop( Iop_Or32, 13208 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13209 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 13210 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 13211 putGST_field( PPC_GST_CR, 13212 binop( Iop_Or32, 13213 mkexpr( flags0 ), 13214 binop( Iop_Or32, 13215 mkexpr( flags1 ), 13216 binop( Iop_Or32, 13217 mkexpr( flags2 ), 13218 mkexpr( flags3 ) ) ) ), 13219 crfD ); 13220 13221 break; 13222 } 13223 case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision) 13224 { 13225 IRTemp flags0 = newTemp(Ity_I32); 13226 IRTemp flags1 = newTemp(Ity_I32); 13227 IRTemp flags2 = newTemp(Ity_I32); 13228 IRTemp flags3 = newTemp(Ity_I32); 13229 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 13230 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1; 13231 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3; 13232 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID; 13233 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID; 13234 DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB); 13235 13236 breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13237 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13238 _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0); 13239 _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1); 13240 _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2); 13241 _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3); 13242 13243 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 13244 * where fl_flag == 1 on ppc64. 13245 */ 13246 assign( flags0, 13247 binop( Iop_Or32, 13248 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13249 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ), 13250 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) ); 13251 assign( flags1, 13252 binop( Iop_Or32, 13253 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13254 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ), 13255 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) ); 13256 assign( flags2, 13257 binop( Iop_Or32, 13258 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13259 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ), 13260 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) ); 13261 assign( flags3, 13262 binop( Iop_Or32, 13263 binop( Iop_Or32, mkU32( 8 ), // fl_flag 13264 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ), 13265 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) ); 13266 putGST_field( PPC_GST_CR, 13267 binop( Iop_Or32, 13268 mkexpr( flags0 ), 13269 binop( Iop_Or32, 13270 mkexpr( flags1 ), 13271 binop( Iop_Or32, 13272 mkexpr( flags2 ), 13273 mkexpr( flags3 ) ) ) ), 13274 crfD ); 13275 13276 break; 13277 } 13278 13279 default: 13280 vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" ); 13281 return False; 13282 } 13283 return True; 13284 } 13285 13286 /* 13287 * Vector Population Count/bit matrix transpose 13288 */ 13289 static Bool 13290 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 ) 13291 { 13292 UChar vRB_addr = ifieldRegB(theInstr); 13293 UChar vRT_addr = ifieldRegDS(theInstr); 13294 UChar opc1 = ifieldOPC( theInstr ); 13295 IRTemp vB = newTemp(Ity_V128); 13296 assign( vB, getVReg(vRB_addr)); 13297 13298 if (opc1 != 0x4) { 13299 vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" ); 13300 return False; 13301 } 13302 13303 switch (opc2) { 13304 case 0x702: // vclzb 13305 DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr); 13306 putVReg( vRT_addr, unop(Iop_Clz8Sx16, mkexpr( vB ) ) ); 13307 break; 13308 13309 case 0x742: // vclzh 13310 DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr); 13311 putVReg( vRT_addr, unop(Iop_Clz16Sx8, mkexpr( vB ) ) ); 13312 break; 13313 13314 case 0x782: // vclzw 13315 DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr); 13316 putVReg( vRT_addr, unop(Iop_Clz32Sx4, mkexpr( vB ) ) ); 13317 break; 13318 13319 case 0x7C2: // vclzd 13320 DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr); 13321 putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) ); 13322 break; 13323 13324 case 0x703: // vpopcntb 13325 { 13326 /* Break vector into 32-bit words and do the population count 13327 * on byte in the words 13328 */ 13329 IRType ty = Ity_I32; 13330 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13331 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13332 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13333 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13334 13335 DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr); 13336 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13337 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, BYTE); 13338 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, BYTE); 13339 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, BYTE); 13340 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE); 13341 13342 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13343 cnt_bits32_63, cnt_bits0_31) ); 13344 break; 13345 } 13346 13347 case 0x743: // vpopcnth 13348 { 13349 /* Break vector into 32-bit words and do the population count 13350 * for each half word 13351 */ 13352 IRType ty = Ity_I32; 13353 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13354 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13355 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13356 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13357 13358 DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr); 13359 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13360 13361 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, HWORD); 13362 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, HWORD); 13363 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, HWORD); 13364 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD); 13365 13366 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13367 cnt_bits32_63, cnt_bits0_31) ); 13368 break; 13369 } 13370 13371 case 0x783: // vpopcntw 13372 { 13373 /* Break vector into 32-bit words and do the population count 13374 * on each word. 13375 */ 13376 IRType ty = Ity_I32; 13377 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13378 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13379 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127; 13380 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID; 13381 13382 DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr); 13383 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13384 13385 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, WORD); 13386 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, WORD); 13387 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, WORD); 13388 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD); 13389 13390 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95, 13391 cnt_bits32_63, cnt_bits0_31) ); 13392 break; 13393 } 13394 13395 case 0x7C3: // vpopcntd 13396 { 13397 if (mode64) { 13398 /* Break vector into 64-bit double words and do the population count 13399 * on each double word. 13400 */ 13401 IRType ty = Ity_I64; 13402 IRTemp bits0_63 = newTemp(Ity_I64); 13403 IRTemp bits64_127 = newTemp(Ity_I64); 13404 IRTemp cnt_bits0_63 = newTemp(Ity_I64); 13405 IRTemp cnt_bits64_127 = newTemp(Ity_I64); 13406 13407 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr); 13408 13409 assign(bits0_63, unop( Iop_V128to64, mkexpr( vB ) ) ); 13410 assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) ); 13411 cnt_bits0_63 = gen_POPCOUNT(ty, bits0_63, DWORD); 13412 cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD); 13413 13414 putVReg( vRT_addr, binop( Iop_64HLtoV128, 13415 mkexpr( cnt_bits64_127 ), 13416 mkexpr( cnt_bits0_63 ) ) ); 13417 } else { 13418 /* Break vector into 32-bit words and do the population count 13419 * on each doubleword. 13420 */ 13421 IRTemp bits0_31, bits32_63, bits64_95, bits96_127; 13422 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID; 13423 IRTemp cnt_bits0_63 = newTemp(Ity_I64); 13424 IRTemp cnt_bits64_127 = newTemp(Ity_I64); 13425 13426 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr); 13427 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 ); 13428 13429 cnt_bits0_63 = gen_vpopcntd_mode32(bits0_31, bits32_63); 13430 cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127); 13431 13432 putVReg( vRT_addr, binop( Iop_64HLtoV128, 13433 mkexpr( cnt_bits64_127 ), 13434 mkexpr( cnt_bits0_63 ) ) ); 13435 } 13436 break; 13437 } 13438 13439 case 0x50C: // vgbbd Vector Gather Bits by Bytes by Doubleword 13440 DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr); 13441 putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) ); 13442 break; 13443 13444 default: 13445 vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n"); 13446 return False; 13447 break; 13448 } 13449 return True; 13450 } 13451 13452 typedef enum { 13453 PPC_CMP_EQ = 2, 13454 PPC_CMP_GT = 4, 13455 PPC_CMP_GE = 6, 13456 PPC_CMP_LT = 8 13457 } ppc_cmp_t; 13458 13459 13460 /* 13461 This helper function takes as input the IRExpr returned 13462 from a binop( Iop_CmpF64, fpA, fpB), whose result is returned 13463 in IR form. This helper function converts it to PPC form. 13464 13465 Map compare result from IR to PPC 13466 13467 FP cmp result | PPC | IR 13468 -------------------------- 13469 UN | 0x1 | 0x45 13470 EQ | 0x2 | 0x40 13471 GT | 0x4 | 0x00 13472 LT | 0x8 | 0x01 13473 13474 condcode = Shl(1, (~(ccIR>>5) & 2) 13475 | ((ccIR ^ (ccIR>>6)) & 1) 13476 */ 13477 static IRTemp 13478 get_fp_cmp_CR_val (IRExpr * ccIR_expr) 13479 { 13480 IRTemp condcode = newTemp( Ity_I32 ); 13481 IRTemp ccIR = newTemp( Ity_I32 ); 13482 13483 assign(ccIR, ccIR_expr); 13484 assign( condcode, 13485 binop( Iop_Shl32, 13486 mkU32( 1 ), 13487 unop( Iop_32to8, 13488 binop( Iop_Or32, 13489 binop( Iop_And32, 13490 unop( Iop_Not32, 13491 binop( Iop_Shr32, 13492 mkexpr( ccIR ), 13493 mkU8( 5 ) ) ), 13494 mkU32( 2 ) ), 13495 binop( Iop_And32, 13496 binop( Iop_Xor32, 13497 mkexpr( ccIR ), 13498 binop( Iop_Shr32, 13499 mkexpr( ccIR ), 13500 mkU8( 6 ) ) ), 13501 mkU32( 1 ) ) ) ) ) ); 13502 return condcode; 13503 } 13504 13505 /* 13506 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles 13507 * following these special rules: 13508 * - The max/min of a QNaN and any value is that value 13509 * (When two QNaNs are being compared, the frA QNaN is the return value.) 13510 * - The max/min of any value and an SNaN is that SNaN converted to a QNaN 13511 * (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.) 13512 */ 13513 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64) 13514 { 13515 IRTemp frA_isNaN = newTemp(Ity_I1); 13516 IRTemp frB_isNaN = newTemp(Ity_I1); 13517 IRTemp frA_isSNaN = newTemp(Ity_I1); 13518 IRTemp frB_isSNaN = newTemp(Ity_I1); 13519 IRTemp frA_isQNaN = newTemp(Ity_I1); 13520 IRTemp frB_isQNaN = newTemp(Ity_I1); 13521 13522 assign( frA_isNaN, is_NaN( frA_I64 ) ); 13523 assign( frB_isNaN, is_NaN( frB_I64 ) ); 13524 // If operand is a NAN and bit 12 is '0', then it's an SNaN 13525 assign( frA_isSNaN, 13526 mkAND1( mkexpr(frA_isNaN), 13527 binop( Iop_CmpEQ32, 13528 binop( Iop_And32, 13529 unop( Iop_64HIto32, mkexpr( frA_I64 ) ), 13530 mkU32( 0x00080000 ) ), 13531 mkU32( 0 ) ) ) ); 13532 assign( frB_isSNaN, 13533 mkAND1( mkexpr(frB_isNaN), 13534 binop( Iop_CmpEQ32, 13535 binop( Iop_And32, 13536 unop( Iop_64HIto32, mkexpr( frB_I64 ) ), 13537 mkU32( 0x00080000 ) ), 13538 mkU32( 0 ) ) ) ); 13539 assign( frA_isQNaN, 13540 mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) ); 13541 assign( frB_isQNaN, 13542 mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) ); 13543 13544 /* Based on the rules specified in the function prologue, the algorithm is as follows: 13545 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 13546 * if frA is a SNaN 13547 * result = frA converted to QNaN 13548 * else if frB is a SNaN 13549 * result = frB converted to QNaN 13550 * else if frB is a QNaN 13551 * result = frA 13552 * // One of frA or frB was a NaN in order for this function to be called, so 13553 * // if we get to this point, we KNOW that frA must be a QNaN. 13554 * else // frA is a QNaN 13555 * result = frB 13556 * <<<<<<<<<>>>>>>>>>>>>>>>>>> 13557 */ 13558 13559 #define SNAN_MASK 0x0008000000000000ULL 13560 return 13561 IRExpr_ITE(mkexpr(frA_isSNaN), 13562 /* then: result = frA converted to QNaN */ 13563 binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)), 13564 /* else: if frB is a SNaN */ 13565 IRExpr_ITE(mkexpr(frB_isSNaN), 13566 /* then: result = frB converted to QNaN */ 13567 binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)), 13568 /* else: if frB is a QNaN */ 13569 IRExpr_ITE(mkexpr(frB_isQNaN), 13570 /* then: result = frA */ 13571 mkexpr(frA_I64), 13572 /* else: frA is a QNaN, so result = frB */ 13573 mkexpr(frB_I64)))); 13574 } 13575 13576 /* 13577 * Helper function for get_max_min_fp. 13578 */ 13579 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin) 13580 { 13581 IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64, 13582 unop( Iop_ReinterpI64asF64, 13583 mkexpr( src1 ) ), 13584 unop( Iop_ReinterpI64asF64, 13585 mkexpr( src2 ) ) ) ); 13586 13587 return IRExpr_ITE( binop( Iop_CmpEQ32, 13588 mkexpr( src1cmpsrc2 ), 13589 mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ), 13590 /* then: use src1 */ 13591 mkexpr( src1 ), 13592 /* else: use src2 */ 13593 mkexpr( src2 ) ); 13594 } 13595 13596 /* 13597 * Helper function for "Maximum/Minimum Double Precision" operations. 13598 * Arguments: frA and frb are Ity_I64 13599 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question 13600 */ 13601 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin) 13602 { 13603 /* There are three special cases where get_fp_cmp_CR_val is not helpful 13604 * for ascertaining the maximum between two doubles: 13605 * 1. The max/min of +0 and -0 is +0. 13606 * 2. The max/min of a QNaN and any value is that value. 13607 * 3. The max/min of any value and an SNaN is that SNaN converted to a QNaN. 13608 * We perform the check for [+/-]0 here in this function and use the 13609 * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp 13610 * to do the standard comparison function. 13611 */ 13612 IRTemp anyNaN = newTemp(Ity_I1); 13613 IRTemp frA_isZero = newTemp(Ity_I1); 13614 IRTemp frB_isZero = newTemp(Ity_I1); 13615 assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ )); 13616 assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ )); 13617 assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64))); 13618 #define MINUS_ZERO 0x8000000000000000ULL 13619 13620 return IRExpr_ITE( /* If both arguments are zero . . . */ 13621 mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ), 13622 /* then: if frA is -0 and isMin==True, return -0; 13623 * else if frA is +0 and isMin==False; return +0; 13624 * otherwise, simply return frB. */ 13625 IRExpr_ITE( binop( Iop_CmpEQ32, 13626 unop( Iop_64HIto32, 13627 mkexpr( frA_I64 ) ), 13628 mkU32( isMin ? 0x80000000 : 0 ) ), 13629 mkU64( isMin ? MINUS_ZERO : 0ULL ), 13630 mkexpr( frB_I64 ) ), 13631 /* else: check if either input is a NaN*/ 13632 IRExpr_ITE( mkexpr( anyNaN ), 13633 /* then: use "NaN helper" */ 13634 _get_maxmin_fp_NaN( frA_I64, frB_I64 ), 13635 /* else: use "comparison helper" */ 13636 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) )); 13637 } 13638 13639 static const HChar * _get_vsx_rdpi_suffix(UInt opc2) 13640 { 13641 switch (opc2 & 0x7F) { 13642 case 0x72: 13643 return "m"; 13644 case 0x52: 13645 return "p"; 13646 case 0x56: 13647 return "c"; 13648 case 0x32: 13649 return "z"; 13650 case 0x12: 13651 return ""; 13652 13653 default: // Impossible to get here 13654 vex_printf("Unrecognized opcode %x\n", opc2); 13655 vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)"); 13656 } 13657 } 13658 13659 /* 13660 * Helper function for vector/scalar double precision fp round to integer instructions. 13661 */ 13662 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2) 13663 { 13664 13665 /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */ 13666 IRTemp frB = newTemp(Ity_F64); 13667 IRTemp frD = newTemp(Ity_F64); 13668 IRTemp intermediateResult = newTemp(Ity_I64); 13669 IRTemp is_SNAN = newTemp(Ity_I1); 13670 IRExpr * hi32; 13671 IRExpr * rxpi_rm; 13672 switch (opc2 & 0x7F) { 13673 case 0x72: 13674 rxpi_rm = mkU32(Irrm_NegINF); 13675 break; 13676 case 0x52: 13677 rxpi_rm = mkU32(Irrm_PosINF); 13678 break; 13679 case 0x56: 13680 rxpi_rm = get_IR_roundingmode(); 13681 break; 13682 case 0x32: 13683 rxpi_rm = mkU32(Irrm_ZERO); 13684 break; 13685 case 0x12: 13686 rxpi_rm = mkU32(Irrm_NEAREST); 13687 break; 13688 13689 default: // Impossible to get here 13690 vex_printf("Unrecognized opcode %x\n", opc2); 13691 vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)"); 13692 } 13693 assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64))); 13694 assign( intermediateResult, 13695 binop( Iop_F64toI64S, rxpi_rm, 13696 mkexpr( frB ) ) ); 13697 13698 /* don't use the rounded integer if frB is outside -9e18..9e18 */ 13699 /* F64 has only log10(2**52) significant digits anyway */ 13700 /* need to preserve sign of zero */ 13701 /* frD = (fabs(frB) > 9e18) ? frB : 13702 (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult */ 13703 assign( frD, 13704 IRExpr_ITE( 13705 binop( Iop_CmpNE8, 13706 unop( Iop_32to8, 13707 binop( Iop_CmpF64, 13708 IRExpr_Const( IRConst_F64( 9e18 ) ), 13709 unop( Iop_AbsF64, mkexpr( frB ) ) ) ), 13710 mkU8(0) ), 13711 mkexpr( frB ), 13712 IRExpr_ITE( 13713 binop( Iop_CmpNE32, 13714 binop( Iop_Shr32, 13715 unop( Iop_64HIto32, 13716 mkexpr( frB_I64 ) ), 13717 mkU8( 31 ) ), 13718 mkU32(0) ), 13719 unop( Iop_NegF64, 13720 unop( Iop_AbsF64, 13721 binop( Iop_I64StoF64, 13722 mkU32( 0 ), 13723 mkexpr( intermediateResult ) ) ) ), 13724 binop( Iop_I64StoF64, 13725 mkU32( 0 ), 13726 mkexpr( intermediateResult ) ) 13727 ) 13728 ) 13729 ); 13730 13731 /* See Appendix "Floating-Point Round to Integer Model" in ISA doc. 13732 * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'. 13733 */ 13734 #define SNAN_MASK 0x0008000000000000ULL 13735 hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) ); 13736 assign( is_SNAN, 13737 mkAND1( is_NaN( frB_I64 ), 13738 binop( Iop_CmpEQ32, 13739 binop( Iop_And32, hi32, mkU32( 0x00080000 ) ), 13740 mkU32( 0 ) ) ) ); 13741 13742 return IRExpr_ITE( mkexpr( is_SNAN ), 13743 unop( Iop_ReinterpI64asF64, 13744 binop( Iop_Xor64, 13745 mkU64( SNAN_MASK ), 13746 mkexpr( frB_I64 ) ) ), 13747 mkexpr( frD )); 13748 } 13749 13750 /* 13751 * Miscellaneous VSX vector instructions 13752 */ 13753 static Bool 13754 dis_vxv_misc ( UInt theInstr, UInt opc2 ) 13755 { 13756 /* XX3-Form */ 13757 UChar opc1 = ifieldOPC( theInstr ); 13758 UChar XT = ifieldRegXT( theInstr ); 13759 UChar XB = ifieldRegXB( theInstr ); 13760 13761 if (opc1 != 0x3C) { 13762 vex_printf( "dis_vxv_misc(ppc)(instr)\n" ); 13763 return False; 13764 } 13765 13766 switch (opc2) { 13767 case 0x1B4: // xvredp (VSX Vector Reciprocal Estimate Double-Precision) 13768 case 0x194: // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate 13769 // Double-Precision) 13770 { 13771 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 13772 IRExpr* rm = get_IR_roundingmode(); 13773 IRTemp frB = newTemp(Ity_I64); 13774 IRTemp frB2 = newTemp(Ity_I64); 13775 Bool redp = opc2 == 0x1B4; 13776 IRTemp sqrtHi = newTemp(Ity_F64); 13777 IRTemp sqrtLo = newTemp(Ity_F64); 13778 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 13779 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 13780 13781 DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB); 13782 if (!redp) { 13783 assign( sqrtHi, 13784 binop( Iop_SqrtF64, 13785 rm, 13786 unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) ); 13787 assign( sqrtLo, 13788 binop( Iop_SqrtF64, 13789 rm, 13790 unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) ); 13791 } 13792 putVSReg( XT, 13793 binop( Iop_64HLtoV128, 13794 unop( Iop_ReinterpF64asI64, 13795 triop( Iop_DivF64, 13796 rm, 13797 ieee_one, 13798 redp ? unop( Iop_ReinterpI64asF64, 13799 mkexpr( frB ) ) 13800 : mkexpr( sqrtHi ) ) ), 13801 unop( Iop_ReinterpF64asI64, 13802 triop( Iop_DivF64, 13803 rm, 13804 ieee_one, 13805 redp ? unop( Iop_ReinterpI64asF64, 13806 mkexpr( frB2 ) ) 13807 : mkexpr( sqrtLo ) ) ) ) ); 13808 break; 13809 13810 } 13811 case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision) 13812 case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision) 13813 { 13814 IRTemp b3, b2, b1, b0; 13815 IRTemp res0 = newTemp(Ity_I32); 13816 IRTemp res1 = newTemp(Ity_I32); 13817 IRTemp res2 = newTemp(Ity_I32); 13818 IRTemp res3 = newTemp(Ity_I32); 13819 IRTemp sqrt3 = newTemp(Ity_F64); 13820 IRTemp sqrt2 = newTemp(Ity_F64); 13821 IRTemp sqrt1 = newTemp(Ity_F64); 13822 IRTemp sqrt0 = newTemp(Ity_F64); 13823 IRExpr* rm = get_IR_roundingmode(); 13824 Bool resp = opc2 == 0x134; 13825 13826 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 13827 13828 b3 = b2 = b1 = b0 = IRTemp_INVALID; 13829 DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB); 13830 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13831 13832 if (!resp) { 13833 assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) ); 13834 assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) ); 13835 assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) ); 13836 assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) ); 13837 } 13838 13839 assign( res0, 13840 unop( Iop_ReinterpF32asI32, 13841 unop( Iop_TruncF64asF32, 13842 triop( Iop_DivF64r32, 13843 rm, 13844 ieee_one, 13845 resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) ); 13846 assign( res1, 13847 unop( Iop_ReinterpF32asI32, 13848 unop( Iop_TruncF64asF32, 13849 triop( Iop_DivF64r32, 13850 rm, 13851 ieee_one, 13852 resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) ); 13853 assign( res2, 13854 unop( Iop_ReinterpF32asI32, 13855 unop( Iop_TruncF64asF32, 13856 triop( Iop_DivF64r32, 13857 rm, 13858 ieee_one, 13859 resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) ); 13860 assign( res3, 13861 unop( Iop_ReinterpF32asI32, 13862 unop( Iop_TruncF64asF32, 13863 triop( Iop_DivF64r32, 13864 rm, 13865 ieee_one, 13866 resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) ); 13867 putVSReg( XT, 13868 binop( Iop_64HLtoV128, 13869 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13870 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13871 break; 13872 } 13873 case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision) 13874 case 0x320: // xvminsp (VSX Vector Minimum Single-Precision) 13875 { 13876 UChar XA = ifieldRegXA( theInstr ); 13877 IRTemp a3, a2, a1, a0; 13878 IRTemp b3, b2, b1, b0; 13879 IRTemp res0 = newTemp( Ity_I32 ); 13880 IRTemp res1 = newTemp( Ity_I32 ); 13881 IRTemp res2 = newTemp( Ity_I32 ); 13882 IRTemp res3 = newTemp( Ity_I32 ); 13883 IRTemp a0_I64 = newTemp( Ity_I64 ); 13884 IRTemp a1_I64 = newTemp( Ity_I64 ); 13885 IRTemp a2_I64 = newTemp( Ity_I64 ); 13886 IRTemp a3_I64 = newTemp( Ity_I64 ); 13887 IRTemp b0_I64 = newTemp( Ity_I64 ); 13888 IRTemp b1_I64 = newTemp( Ity_I64 ); 13889 IRTemp b2_I64 = newTemp( Ity_I64 ); 13890 IRTemp b3_I64 = newTemp( Ity_I64 ); 13891 13892 Bool isMin = opc2 == 0x320 ? True : False; 13893 13894 a3 = a2 = a1 = a0 = IRTemp_INVALID; 13895 b3 = b2 = b1 = b0 = IRTemp_INVALID; 13896 DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB); 13897 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 ); 13898 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 ); 13899 assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) ); 13900 assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) ); 13901 assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) ); 13902 assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) ); 13903 assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) ); 13904 assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) ); 13905 assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) ); 13906 assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) ); 13907 assign( res0, 13908 unop( Iop_ReinterpF32asI32, 13909 unop( Iop_TruncF64asF32, 13910 unop( Iop_ReinterpI64asF64, 13911 get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) ); 13912 assign( res1, 13913 unop( Iop_ReinterpF32asI32, 13914 unop( Iop_TruncF64asF32, 13915 unop( Iop_ReinterpI64asF64, 13916 get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) ); 13917 assign( res2, 13918 unop( Iop_ReinterpF32asI32, 13919 unop( Iop_TruncF64asF32, 13920 unop( Iop_ReinterpI64asF64, 13921 get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) ); 13922 assign( res3, 13923 unop( Iop_ReinterpF32asI32, 13924 unop( Iop_TruncF64asF32, 13925 unop( Iop_ReinterpI64asF64, 13926 get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) ); 13927 putVSReg( XT, 13928 binop( Iop_64HLtoV128, 13929 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ), 13930 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) ); 13931 break; 13932 } 13933 case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision) 13934 case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision) 13935 { 13936 UChar XA = ifieldRegXA( theInstr ); 13937 IRTemp frA = newTemp(Ity_I64); 13938 IRTemp frB = newTemp(Ity_I64); 13939 IRTemp frA2 = newTemp(Ity_I64); 13940 IRTemp frB2 = newTemp(Ity_I64); 13941 Bool isMin = opc2 == 0x3A0 ? True : False; 13942 13943 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 13944 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 13945 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 13946 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 13947 DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB); 13948 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) ); 13949 13950 break; 13951 } 13952 case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision) 13953 { 13954 UChar XA = ifieldRegXA( theInstr ); 13955 IRTemp frA = newTemp(Ity_I64); 13956 IRTemp frB = newTemp(Ity_I64); 13957 IRTemp frA2 = newTemp(Ity_I64); 13958 IRTemp frB2 = newTemp(Ity_I64); 13959 assign(frA, unop(Iop_V128HIto64, getVSReg( XA ))); 13960 assign(frB, unop(Iop_V128HIto64, getVSReg( XB ))); 13961 assign(frA2, unop(Iop_V128to64, getVSReg( XA ))); 13962 assign(frB2, unop(Iop_V128to64, getVSReg( XB ))); 13963 13964 DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 13965 putVSReg( XT, 13966 binop( Iop_64HLtoV128, 13967 binop( Iop_Or64, 13968 binop( Iop_And64, 13969 mkexpr( frA ), 13970 mkU64( SIGN_BIT ) ), 13971 binop( Iop_And64, 13972 mkexpr( frB ), 13973 mkU64( SIGN_MASK ) ) ), 13974 binop( Iop_Or64, 13975 binop( Iop_And64, 13976 mkexpr( frA2 ), 13977 mkU64( SIGN_BIT ) ), 13978 binop( Iop_And64, 13979 mkexpr( frB2 ), 13980 mkU64( SIGN_MASK ) ) ) ) ); 13981 break; 13982 } 13983 case 0x340: // xvcpsgnsp 13984 { 13985 UChar XA = ifieldRegXA( theInstr ); 13986 IRTemp a3_I64, a2_I64, a1_I64, a0_I64; 13987 IRTemp b3_I64, b2_I64, b1_I64, b0_I64; 13988 IRTemp resHi = newTemp(Ity_I64); 13989 IRTemp resLo = newTemp(Ity_I64); 13990 13991 a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID; 13992 b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID; 13993 DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB); 13994 breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 ); 13995 breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 ); 13996 13997 assign( resHi, 13998 binop( Iop_32HLto64, 13999 binop( Iop_Or32, 14000 binop( Iop_And32, 14001 unop(Iop_64to32, mkexpr( a3_I64 ) ), 14002 mkU32( SIGN_BIT32 ) ), 14003 binop( Iop_And32, 14004 unop(Iop_64to32, mkexpr( b3_I64 ) ), 14005 mkU32( SIGN_MASK32) ) ), 14006 14007 binop( Iop_Or32, 14008 binop( Iop_And32, 14009 unop(Iop_64to32, mkexpr( a2_I64 ) ), 14010 mkU32( SIGN_BIT32 ) ), 14011 binop( Iop_And32, 14012 unop(Iop_64to32, mkexpr( b2_I64 ) ), 14013 mkU32( SIGN_MASK32 ) ) ) ) ); 14014 assign( resLo, 14015 binop( Iop_32HLto64, 14016 binop( Iop_Or32, 14017 binop( Iop_And32, 14018 unop(Iop_64to32, mkexpr( a1_I64 ) ), 14019 mkU32( SIGN_BIT32 ) ), 14020 binop( Iop_And32, 14021 unop(Iop_64to32, mkexpr( b1_I64 ) ), 14022 mkU32( SIGN_MASK32 ) ) ), 14023 14024 binop( Iop_Or32, 14025 binop( Iop_And32, 14026 unop(Iop_64to32, mkexpr( a0_I64 ) ), 14027 mkU32( SIGN_BIT32 ) ), 14028 binop( Iop_And32, 14029 unop(Iop_64to32, mkexpr( b0_I64 ) ), 14030 mkU32( SIGN_MASK32 ) ) ) ) ); 14031 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) ); 14032 break; 14033 } 14034 case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision) 14035 case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision) 14036 { 14037 IRTemp frB = newTemp(Ity_F64); 14038 IRTemp frB2 = newTemp(Ity_F64); 14039 IRTemp abs_resultHi = newTemp(Ity_F64); 14040 IRTemp abs_resultLo = newTemp(Ity_F64); 14041 Bool make_negative = (opc2 == 0x3D2) ? True : False; 14042 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14043 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 14044 14045 DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB); 14046 if (make_negative) { 14047 assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) ); 14048 assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) ); 14049 14050 } else { 14051 assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) ); 14052 assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) ); 14053 } 14054 putVSReg( XT, binop( Iop_64HLtoV128, 14055 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ), 14056 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) ); 14057 break; 14058 } 14059 case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision) 14060 case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision) 14061 { 14062 /* 14063 * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction 14064 * of xvabssp, there has not been an abs(sp) type of instruction. But since emulation 14065 * of this function is so easy using shifts, I choose to emulate this instruction that 14066 * way versus a native instruction method of implementation. 14067 */ 14068 Bool make_negative = (opc2 == 0x352) ? True : False; 14069 IRTemp shiftVector = newTemp(Ity_V128); 14070 IRTemp absVal_vector = newTemp(Ity_V128); 14071 assign( shiftVector, 14072 binop( Iop_64HLtoV128, 14073 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ), 14074 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) ); 14075 assign( absVal_vector, 14076 binop( Iop_Shr32x4, 14077 binop( Iop_Shl32x4, 14078 getVSReg( XB ), 14079 mkexpr( shiftVector ) ), 14080 mkexpr( shiftVector ) ) ); 14081 if (make_negative) { 14082 IRTemp signBit_vector = newTemp(Ity_V128); 14083 assign( signBit_vector, 14084 binop( Iop_64HLtoV128, 14085 binop( Iop_32HLto64, 14086 mkU32( 0x80000000 ), 14087 mkU32( 0x80000000 ) ), 14088 binop( Iop_32HLto64, 14089 mkU32( 0x80000000 ), 14090 mkU32( 0x80000000 ) ) ) ); 14091 putVSReg( XT, 14092 binop( Iop_OrV128, 14093 mkexpr( absVal_vector ), 14094 mkexpr( signBit_vector ) ) ); 14095 } else { 14096 putVSReg( XT, mkexpr( absVal_vector ) ); 14097 } 14098 break; 14099 } 14100 case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision) 14101 { 14102 IRTemp frB = newTemp(Ity_F64); 14103 IRTemp frB2 = newTemp(Ity_F64); 14104 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14105 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB)))); 14106 DIP("xvnegdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14107 putVSReg( XT, 14108 binop( Iop_64HLtoV128, 14109 unop( Iop_ReinterpF64asI64, 14110 unop( Iop_NegF64, mkexpr( frB ) ) ), 14111 unop( Iop_ReinterpF64asI64, 14112 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) ); 14113 break; 14114 } 14115 case 0x192: // xvrdpi (VSX Vector Round to Double-Precision Integer using round toward Nearest Away) 14116 case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode) 14117 case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity) 14118 case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity) 14119 case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero) 14120 { 14121 IRTemp frBHi_I64 = newTemp(Ity_I64); 14122 IRTemp frBLo_I64 = newTemp(Ity_I64); 14123 IRExpr * frD_fp_roundHi = NULL; 14124 IRExpr * frD_fp_roundLo = NULL; 14125 14126 assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) ); 14127 frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2); 14128 assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) ); 14129 frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2); 14130 14131 DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB); 14132 putVSReg( XT, 14133 binop( Iop_64HLtoV128, 14134 unop( Iop_ReinterpF64asI64, frD_fp_roundHi ), 14135 unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) ); 14136 break; 14137 } 14138 case 0x112: // xvrspi (VSX Vector Round to Single-Precision Integer using round toward Nearest Away) 14139 case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode) 14140 case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity) 14141 case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity) 14142 case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero) 14143 { 14144 const HChar * insn_suffix = NULL; 14145 IROp op; 14146 if (opc2 != 0x156) { 14147 // Use pre-defined IRop's for vrfi{m|n|p|z} 14148 switch (opc2) { 14149 case 0x112: 14150 insn_suffix = ""; 14151 op = Iop_RoundF32x4_RN; 14152 break; 14153 case 0x172: 14154 insn_suffix = "m"; 14155 op = Iop_RoundF32x4_RM; 14156 break; 14157 case 0x152: 14158 insn_suffix = "p"; 14159 op = Iop_RoundF32x4_RP; 14160 break; 14161 case 0x132: 14162 insn_suffix = "z"; 14163 op = Iop_RoundF32x4_RZ; 14164 break; 14165 14166 default: 14167 vex_printf("Unrecognized opcode %x\n", opc2); 14168 vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n"); 14169 } 14170 DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB); 14171 putVSReg( XT, unop( op, getVSReg(XB) ) ); 14172 } else { 14173 // Handle xvrspic. Unfortunately there is no corresponding "vfric" instruction. 14174 IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0; 14175 IRTemp b3_F64, b2_F64, b1_F64, b0_F64; 14176 IRTemp b3_I64 = newTemp(Ity_I64); 14177 IRTemp b2_I64 = newTemp(Ity_I64); 14178 IRTemp b1_I64 = newTemp(Ity_I64); 14179 IRTemp b0_I64 = newTemp(Ity_I64); 14180 14181 b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID; 14182 frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL; 14183 breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64); 14184 assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64))); 14185 assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64))); 14186 assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64))); 14187 assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64))); 14188 frD_fp_roundb3 = unop(Iop_TruncF64asF32, 14189 _do_vsx_fp_roundToInt(b3_I64, opc2)); 14190 frD_fp_roundb2 = unop(Iop_TruncF64asF32, 14191 _do_vsx_fp_roundToInt(b2_I64, opc2)); 14192 frD_fp_roundb1 = unop(Iop_TruncF64asF32, 14193 _do_vsx_fp_roundToInt(b1_I64, opc2)); 14194 frD_fp_roundb0 = unop(Iop_TruncF64asF32, 14195 _do_vsx_fp_roundToInt(b0_I64, opc2)); 14196 DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB); 14197 putVSReg( XT, 14198 binop( Iop_64HLtoV128, 14199 binop( Iop_32HLto64, 14200 unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ), 14201 unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ), 14202 binop( Iop_32HLto64, 14203 unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ), 14204 unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) ); 14205 } 14206 break; 14207 } 14208 14209 default: 14210 vex_printf( "dis_vxv_misc(ppc)(opc2)\n" ); 14211 return False; 14212 } 14213 return True; 14214 } 14215 14216 14217 /* 14218 * VSX Scalar Floating Point Arithmetic Instructions 14219 */ 14220 static Bool 14221 dis_vxs_arith ( UInt theInstr, UInt opc2 ) 14222 { 14223 /* XX3-Form */ 14224 UChar opc1 = ifieldOPC( theInstr ); 14225 UChar XT = ifieldRegXT( theInstr ); 14226 UChar XA = ifieldRegXA( theInstr ); 14227 UChar XB = ifieldRegXB( theInstr ); 14228 IRExpr* rm = get_IR_roundingmode(); 14229 IRTemp frA = newTemp(Ity_F64); 14230 IRTemp frB = newTemp(Ity_F64); 14231 14232 if (opc1 != 0x3C) { 14233 vex_printf( "dis_vxs_arith(ppc)(instr)\n" ); 14234 return False; 14235 } 14236 14237 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 14238 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14239 14240 /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1 14241 * of VSX[XT] are undefined after the operation; therefore, we can simply set 14242 * element to zero where it makes sense to do so. 14243 */ 14244 switch (opc2) { 14245 case 0x000: // xsaddsp (VSX Scalar Add Single-Precision) 14246 DIP("xsaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14247 putVSReg( XT, binop( Iop_64HLtoV128, 14248 unop( Iop_ReinterpF64asI64, 14249 binop( Iop_RoundF64toF32, rm, 14250 triop( Iop_AddF64, rm, 14251 mkexpr( frA ), 14252 mkexpr( frB ) ) ) ), 14253 mkU64( 0 ) ) ); 14254 break; 14255 case 0x020: // xssubsp (VSX Scalar Subtract Single-Precision) 14256 DIP("xssubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14257 putVSReg( XT, binop( Iop_64HLtoV128, 14258 unop( Iop_ReinterpF64asI64, 14259 binop( Iop_RoundF64toF32, rm, 14260 triop( Iop_SubF64, rm, 14261 mkexpr( frA ), 14262 mkexpr( frB ) ) ) ), 14263 mkU64( 0 ) ) ); 14264 break; 14265 case 0x080: // xsadddp (VSX scalar add double-precision) 14266 DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14267 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14268 triop( Iop_AddF64, rm, 14269 mkexpr( frA ), 14270 mkexpr( frB ) ) ), 14271 mkU64( 0 ) ) ); 14272 break; 14273 case 0x060: // xsdivsp (VSX scalar divide single-precision) 14274 DIP("xsdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14275 putVSReg( XT, binop( Iop_64HLtoV128, 14276 unop( Iop_ReinterpF64asI64, 14277 binop( Iop_RoundF64toF32, rm, 14278 triop( Iop_DivF64, rm, 14279 mkexpr( frA ), 14280 mkexpr( frB ) ) ) ), 14281 mkU64( 0 ) ) ); 14282 break; 14283 case 0x0E0: // xsdivdp (VSX scalar divide double-precision) 14284 DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14285 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14286 triop( Iop_DivF64, rm, 14287 mkexpr( frA ), 14288 mkexpr( frB ) ) ), 14289 mkU64( 0 ) ) ); 14290 break; 14291 case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add 14292 * single-precision) 14293 */ 14294 { 14295 IRTemp frT = newTemp(Ity_F64); 14296 Bool mdp = opc2 == 0x024; 14297 DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14298 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14299 getVSReg( XT ) ) ) ); 14300 putVSReg( XT, 14301 binop( Iop_64HLtoV128, 14302 unop( Iop_ReinterpF64asI64, 14303 binop( Iop_RoundF64toF32, rm, 14304 qop( Iop_MAddF64, rm, 14305 mkexpr( frA ), 14306 mkexpr( mdp ? frT : frB ), 14307 mkexpr( mdp ? frB : frT ) ) ) ), 14308 mkU64( 0 ) ) ); 14309 break; 14310 } 14311 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision) 14312 { 14313 IRTemp frT = newTemp(Ity_F64); 14314 Bool mdp = opc2 == 0x0A4; 14315 DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14316 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14317 getVSReg( XT ) ) ) ); 14318 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14319 qop( Iop_MAddF64, rm, 14320 mkexpr( frA ), 14321 mkexpr( mdp ? frT : frB ), 14322 mkexpr( mdp ? frB : frT ) ) ), 14323 mkU64( 0 ) ) ); 14324 break; 14325 } 14326 case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar 14327 * multiply-subtract single-precision) 14328 */ 14329 { 14330 IRTemp frT = newTemp(Ity_F64); 14331 Bool mdp = opc2 == 0x064; 14332 DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14333 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14334 getVSReg( XT ) ) ) ); 14335 putVSReg( XT, 14336 binop( Iop_64HLtoV128, 14337 unop( Iop_ReinterpF64asI64, 14338 binop( Iop_RoundF64toF32, rm, 14339 qop( Iop_MSubF64, rm, 14340 mkexpr( frA ), 14341 mkexpr( mdp ? frT : frB ), 14342 mkexpr( mdp ? frB : frT ) ) ) ), 14343 mkU64( 0 ) ) ); 14344 break; 14345 } 14346 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision) 14347 { 14348 IRTemp frT = newTemp(Ity_F64); 14349 Bool mdp = opc2 == 0x0E4; 14350 DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14351 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14352 getVSReg( XT ) ) ) ); 14353 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14354 qop( Iop_MSubF64, rm, 14355 mkexpr( frA ), 14356 mkexpr( mdp ? frT : frB ), 14357 mkexpr( mdp ? frB : frT ) ) ), 14358 mkU64( 0 ) ) ); 14359 break; 14360 } 14361 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision) 14362 { 14363 /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation 14364 * of fnmadd and use pretty much the same code. However, that code has a bug in the 14365 * way it blindly negates the signbit, even if the floating point result is a NaN. 14366 * So, the TODO is to fix fnmadd (which I'll do in a different patch). 14367 * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign 14368 * bit for NaN result. 14369 */ 14370 Bool mdp = opc2 == 0x2A4; 14371 IRTemp frT = newTemp(Ity_F64); 14372 IRTemp maddResult = newTemp(Ity_I64); 14373 14374 DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14375 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14376 getVSReg( XT ) ) ) ); 14377 assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm, 14378 mkexpr( frA ), 14379 mkexpr( mdp ? frT : frB ), 14380 mkexpr( mdp ? frB : frT ) ) ) ); 14381 14382 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ), 14383 mkU64( 0 ) ) ); 14384 break; 14385 } 14386 case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar 14387 * multiply-add single-precision) 14388 */ 14389 { 14390 Bool mdp = opc2 == 0x224; 14391 IRTemp frT = newTemp(Ity_F64); 14392 IRTemp maddResult = newTemp(Ity_I64); 14393 14394 DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14395 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14396 getVSReg( XT ) ) ) ); 14397 assign( maddResult, 14398 unop( Iop_ReinterpF64asI64, 14399 binop( Iop_RoundF64toF32, rm, 14400 qop( Iop_MAddF64, rm, 14401 mkexpr( frA ), 14402 mkexpr( mdp ? frT : frB ), 14403 mkexpr( mdp ? frB : frT ) ) ) ) ); 14404 14405 putVSReg( XT, binop( Iop_64HLtoV128, 14406 mkexpr( getNegatedResult(maddResult) ), 14407 mkU64( 0 ) ) ); 14408 break; 14409 } 14410 case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative 14411 * Multiply-Subtract Single-Precision) 14412 */ 14413 { 14414 IRTemp frT = newTemp(Ity_F64); 14415 Bool mdp = opc2 == 0x264; 14416 IRTemp msubResult = newTemp(Ity_I64); 14417 14418 DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14419 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14420 getVSReg( XT ) ) ) ); 14421 assign( msubResult, 14422 unop( Iop_ReinterpF64asI64, 14423 binop( Iop_RoundF64toF32, rm, 14424 qop( Iop_MSubF64, rm, 14425 mkexpr( frA ), 14426 mkexpr( mdp ? frT : frB ), 14427 mkexpr( mdp ? frB : frT ) ) ) ) ); 14428 14429 putVSReg( XT, binop( Iop_64HLtoV128, 14430 mkexpr( getNegatedResult(msubResult) ), 14431 mkU64( 0 ) ) ); 14432 14433 break; 14434 } 14435 14436 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision) 14437 { 14438 IRTemp frT = newTemp(Ity_F64); 14439 Bool mdp = opc2 == 0x2E4; 14440 IRTemp msubResult = newTemp(Ity_I64); 14441 14442 DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB); 14443 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64, 14444 getVSReg( XT ) ) ) ); 14445 assign(msubResult, unop( Iop_ReinterpF64asI64, 14446 qop( Iop_MSubF64, 14447 rm, 14448 mkexpr( frA ), 14449 mkexpr( mdp ? frT : frB ), 14450 mkexpr( mdp ? frB : frT ) ) )); 14451 14452 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) ); 14453 14454 break; 14455 } 14456 14457 case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision) 14458 DIP("xsmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14459 putVSReg( XT, binop( Iop_64HLtoV128, 14460 unop( Iop_ReinterpF64asI64, 14461 binop( Iop_RoundF64toF32, rm, 14462 triop( Iop_MulF64, rm, 14463 mkexpr( frA ), 14464 mkexpr( frB ) ) ) ), 14465 mkU64( 0 ) ) ); 14466 break; 14467 14468 case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision) 14469 DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14470 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14471 triop( Iop_MulF64, rm, 14472 mkexpr( frA ), 14473 mkexpr( frB ) ) ), 14474 mkU64( 0 ) ) ); 14475 break; 14476 case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision) 14477 DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14478 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14479 triop( Iop_SubF64, rm, 14480 mkexpr( frA ), 14481 mkexpr( frB ) ) ), 14482 mkU64( 0 ) ) ); 14483 break; 14484 14485 case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision) 14486 DIP("xssqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB); 14487 putVSReg( XT, 14488 binop( Iop_64HLtoV128, 14489 unop( Iop_ReinterpF64asI64, 14490 binop( Iop_RoundF64toF32, rm, 14491 binop( Iop_SqrtF64, rm, 14492 mkexpr( frB ) ) ) ), 14493 mkU64( 0 ) ) ); 14494 break; 14495 14496 case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision) 14497 DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14498 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64, 14499 binop( Iop_SqrtF64, rm, 14500 mkexpr( frB ) ) ), 14501 mkU64( 0 ) ) ); 14502 break; 14503 14504 case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision) 14505 { 14506 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14507 IRTemp frA_I64 = newTemp(Ity_I64); 14508 IRTemp frB_I64 = newTemp(Ity_I64); 14509 DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB); 14510 assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) ); 14511 assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) ); 14512 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD ); 14513 break; 14514 } 14515 case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision) 14516 { 14517 IRTemp frB_I64 = newTemp(Ity_I64); 14518 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14519 IRTemp flags = newTemp(Ity_I32); 14520 IRTemp fe_flag, fg_flag; 14521 fe_flag = fg_flag = IRTemp_INVALID; 14522 DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14523 assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) ); 14524 do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag); 14525 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0 14526 * where fl_flag == 1 on ppc64. 14527 */ 14528 assign( flags, 14529 binop( Iop_Or32, 14530 binop( Iop_Or32, mkU32( 8 ), // fl_flag 14531 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ), 14532 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) ); 14533 putGST_field( PPC_GST_CR, mkexpr(flags), crfD ); 14534 break; 14535 } 14536 14537 default: 14538 vex_printf( "dis_vxs_arith(ppc)(opc2)\n" ); 14539 return False; 14540 } 14541 14542 return True; 14543 } 14544 14545 14546 /* 14547 * VSX Floating Point Compare Instructions 14548 */ 14549 static Bool 14550 dis_vx_cmp( UInt theInstr, UInt opc2 ) 14551 { 14552 /* XX3-Form and XX2-Form */ 14553 UChar opc1 = ifieldOPC( theInstr ); 14554 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); 14555 IRTemp ccPPC32; 14556 UChar XA = ifieldRegXA ( theInstr ); 14557 UChar XB = ifieldRegXB ( theInstr ); 14558 IRTemp frA = newTemp(Ity_F64); 14559 IRTemp frB = newTemp(Ity_F64); 14560 14561 if (opc1 != 0x3C) { 14562 vex_printf( "dis_vx_cmp(ppc)(instr)\n" ); 14563 return False; 14564 } 14565 14566 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA )))); 14567 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB )))); 14568 switch (opc2) { 14569 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 14570 /* Note: Differences between xscmpudp and xscmpodp are only in 14571 * exception flag settings, which aren't supported anyway. */ 14572 DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o", 14573 crfD, (UInt)XA, (UInt)XB); 14574 ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB))); 14575 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD ); 14576 break; 14577 14578 default: 14579 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" ); 14580 return False; 14581 } 14582 return True; 14583 } 14584 14585 static void 14586 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC, 14587 ppc_cmp_t cmp_type ) 14588 { 14589 IRTemp frA_hi = newTemp(Ity_F64); 14590 IRTemp frB_hi = newTemp(Ity_F64); 14591 IRTemp frA_lo = newTemp(Ity_F64); 14592 IRTemp frB_lo = newTemp(Ity_F64); 14593 IRTemp ccPPC32 = newTemp(Ity_I32); 14594 IRTemp ccIR_hi; 14595 IRTemp ccIR_lo; 14596 14597 IRTemp hiResult = newTemp(Ity_I64); 14598 IRTemp loResult = newTemp(Ity_I64); 14599 IRTemp hiEQlo = newTemp(Ity_I1); 14600 IRTemp all_elem_true = newTemp(Ity_I32); 14601 IRTemp all_elem_false = newTemp(Ity_I32); 14602 14603 assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA )))); 14604 assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB )))); 14605 assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA )))); 14606 assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB )))); 14607 14608 ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64, 14609 mkexpr( frA_hi ), 14610 mkexpr( frB_hi ) ) ); 14611 ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64, 14612 mkexpr( frA_lo ), 14613 mkexpr( frB_lo ) ) ); 14614 14615 if (cmp_type != PPC_CMP_GE) { 14616 assign( hiResult, 14617 unop( Iop_1Sto64, 14618 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) ); 14619 assign( loResult, 14620 unop( Iop_1Sto64, 14621 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) ); 14622 } else { 14623 // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and 14624 // the other element compare may return "2" (for "equal to"). 14625 IRTemp lo_GE = newTemp(Ity_I1); 14626 IRTemp hi_GE = newTemp(Ity_I1); 14627 14628 assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ), 14629 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) ); 14630 assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) ); 14631 14632 assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ), 14633 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) ); 14634 assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) ); 14635 } 14636 14637 // The [hi/lo]Result will be all 1's or all 0's. We just look at the lower word. 14638 assign( hiEQlo, 14639 binop( Iop_CmpEQ32, 14640 unop( Iop_64to32, mkexpr( hiResult ) ), 14641 unop( Iop_64to32, mkexpr( loResult ) ) ) ); 14642 putVSReg( XT, 14643 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) ); 14644 14645 assign( all_elem_true, 14646 unop( Iop_1Uto32, 14647 mkAND1( mkexpr( hiEQlo ), 14648 binop( Iop_CmpEQ32, 14649 mkU32( 0xffffffff ), 14650 unop( Iop_64to32, 14651 mkexpr( hiResult ) ) ) ) ) ); 14652 14653 assign( all_elem_false, 14654 unop( Iop_1Uto32, 14655 mkAND1( mkexpr( hiEQlo ), 14656 binop( Iop_CmpEQ32, 14657 mkU32( 0 ), 14658 unop( Iop_64to32, 14659 mkexpr( hiResult ) ) ) ) ) ); 14660 assign( ccPPC32, 14661 binop( Iop_Or32, 14662 binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ), 14663 binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) ); 14664 14665 if (flag_rC) { 14666 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 ); 14667 } 14668 } 14669 14670 /* 14671 * VSX Vector Compare Instructions 14672 */ 14673 static Bool 14674 dis_vvec_cmp( UInt theInstr, UInt opc2 ) 14675 { 14676 /* XX3-Form */ 14677 UChar opc1 = ifieldOPC( theInstr ); 14678 UChar XT = ifieldRegXT ( theInstr ); 14679 UChar XA = ifieldRegXA ( theInstr ); 14680 UChar XB = ifieldRegXB ( theInstr ); 14681 UChar flag_rC = ifieldBIT10(theInstr); 14682 IRTemp vA = newTemp( Ity_V128 ); 14683 IRTemp vB = newTemp( Ity_V128 ); 14684 14685 if (opc1 != 0x3C) { 14686 vex_printf( "dis_vvec_cmp(ppc)(instr)\n" ); 14687 return False; 14688 } 14689 14690 assign( vA, getVSReg( XA ) ); 14691 assign( vB, getVSReg( XB ) ); 14692 14693 switch (opc2) { 14694 case 0x18C: case 0x38C: // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ]) 14695 { 14696 DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 14697 (UInt)XT, (UInt)XA, (UInt)XB); 14698 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ); 14699 break; 14700 } 14701 14702 case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ]) 14703 { 14704 DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 14705 (UInt)XT, (UInt)XA, (UInt)XB); 14706 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE); 14707 break; 14708 } 14709 14710 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ]) 14711 { 14712 DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 14713 (UInt)XT, (UInt)XA, (UInt)XB); 14714 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT); 14715 break; 14716 } 14717 14718 case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ]) 14719 { 14720 IRTemp vD = newTemp(Ity_V128); 14721 14722 DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 14723 (UInt)XT, (UInt)XA, (UInt)XB); 14724 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 14725 putVSReg( XT, mkexpr(vD) ); 14726 if (flag_rC) { 14727 set_AV_CR6( mkexpr(vD), True ); 14728 } 14729 break; 14730 } 14731 14732 case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ]) 14733 { 14734 IRTemp vD = newTemp(Ity_V128); 14735 14736 DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 14737 (UInt)XT, (UInt)XA, (UInt)XB); 14738 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 14739 putVSReg( XT, mkexpr(vD) ); 14740 if (flag_rC) { 14741 set_AV_CR6( mkexpr(vD), True ); 14742 } 14743 break; 14744 } 14745 14746 case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ]) 14747 { 14748 IRTemp vD = newTemp(Ity_V128); 14749 14750 DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""), 14751 (UInt)XT, (UInt)XA, (UInt)XB); 14752 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 14753 putVSReg( XT, mkexpr(vD) ); 14754 if (flag_rC) { 14755 set_AV_CR6( mkexpr(vD), True ); 14756 } 14757 break; 14758 } 14759 14760 default: 14761 vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" ); 14762 return False; 14763 } 14764 return True; 14765 } 14766 /* 14767 * Miscellaneous VSX Scalar Instructions 14768 */ 14769 static Bool 14770 dis_vxs_misc( UInt theInstr, UInt opc2 ) 14771 { 14772 /* XX3-Form and XX2-Form */ 14773 UChar opc1 = ifieldOPC( theInstr ); 14774 UChar XT = ifieldRegXT ( theInstr ); 14775 UChar XA = ifieldRegXA ( theInstr ); 14776 UChar XB = ifieldRegXB ( theInstr ); 14777 IRTemp vA = newTemp( Ity_V128 ); 14778 IRTemp vB = newTemp( Ity_V128 ); 14779 14780 if (opc1 != 0x3C) { 14781 vex_printf( "dis_vxs_misc(ppc)(instr)\n" ); 14782 return False; 14783 } 14784 14785 assign( vA, getVSReg( XA ) ); 14786 assign( vB, getVSReg( XB ) ); 14787 14788 /* For all the VSX move instructions, the contents of doubleword element 1 14789 * of VSX[XT] are undefined after the operation; therefore, we can simply 14790 * move the entire array element where it makes sense to do so. 14791 */ 14792 14793 switch (opc2) { 14794 case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision 14795 { 14796 /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */ 14797 IRTemp absVal = newTemp(Ity_V128); 14798 assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1))); 14799 DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14800 putVSReg(XT, mkexpr(absVal)); 14801 break; 14802 } 14803 case 0x2C0: // xscpsgndp 14804 { 14805 /* Scalar copy sign double-precision */ 14806 IRTemp vecA_signbit = newTemp(Ity_V128); 14807 IRTemp vecB_no_signbit = newTemp(Ity_V128); 14808 IRTemp vec_result = newTemp(Ity_V128); 14809 DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 14810 assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128, 14811 mkexpr( vB ), 14812 mkU8( 1 ) ), 14813 mkU8( 1 ) ) ); 14814 assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128, 14815 mkexpr( vA ), 14816 mkU8( 127 ) ), 14817 mkU8( 127 ) ) ); 14818 assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) ); 14819 putVSReg(XT, mkexpr(vec_result)); 14820 break; 14821 } 14822 case 0x2D2: // xsnabsdp 14823 { 14824 /* Scalar negative absolute value double-precision */ 14825 IRTemp vec_neg_signbit = newTemp(Ity_V128); 14826 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14827 assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128, 14828 mkV128( 0xffff ), 14829 mkU8( 1 ) ) ) ); 14830 putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB))); 14831 break; 14832 } 14833 case 0x2F2: // xsnegdp 14834 { 14835 /* Scalar negate double-precision */ 14836 IRTemp vecB_no_signbit = newTemp(Ity_V128); 14837 IRTemp vecB_signbit_comp = newTemp(Ity_V128); 14838 DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB); 14839 assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128, 14840 mkexpr( vB ), 14841 mkU8( 1 ) ), 14842 mkU8( 1 ) ) ); 14843 assign( vecB_signbit_comp, binop( Iop_ShlV128, 14844 unop( Iop_NotV128, 14845 binop( Iop_ShrV128, 14846 mkexpr( vB ), 14847 mkU8( 127 ) ) ), 14848 mkU8( 127 ) ) ); 14849 putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ), 14850 mkexpr( vecB_signbit_comp ) ) ); 14851 break; 14852 } 14853 case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision) 14854 case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision) 14855 { 14856 IRTemp frA = newTemp(Ity_I64); 14857 IRTemp frB = newTemp(Ity_I64); 14858 Bool isMin = opc2 == 0x2A0 ? True : False; 14859 DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB); 14860 14861 assign(frA, unop(Iop_V128HIto64, mkexpr( vA ))); 14862 assign(frB, unop(Iop_V128HIto64, mkexpr( vB ))); 14863 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) ); 14864 14865 break; 14866 } 14867 case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity) 14868 case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity) 14869 case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode) 14870 case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero) 14871 case 0x092: // xsrdpi (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away) 14872 { 14873 IRTemp frB_I64 = newTemp(Ity_I64); 14874 IRExpr * frD_fp_round = NULL; 14875 14876 assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB ))); 14877 frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2); 14878 14879 DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB); 14880 putVSReg( XT, 14881 binop( Iop_64HLtoV128, 14882 unop( Iop_ReinterpF64asI64, frD_fp_round), 14883 mkU64( 0 ) ) ); 14884 break; 14885 } 14886 case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision) 14887 case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate 14888 * single-Precision) 14889 */ 14890 { 14891 IRTemp frB = newTemp(Ity_F64); 14892 IRTemp sqrt = newTemp(Ity_F64); 14893 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 14894 IRExpr* rm = get_IR_roundingmode(); 14895 Bool redp = opc2 == 0x034; 14896 DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", (UInt)XT, 14897 (UInt)XB); 14898 14899 assign( frB, 14900 unop( Iop_ReinterpI64asF64, 14901 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 14902 14903 if (!redp) 14904 assign( sqrt, 14905 binop( Iop_SqrtF64, 14906 rm, 14907 mkexpr(frB) ) ); 14908 putVSReg( XT, 14909 binop( Iop_64HLtoV128, 14910 unop( Iop_ReinterpF64asI64, 14911 binop( Iop_RoundF64toF32, rm, 14912 triop( Iop_DivF64, 14913 rm, 14914 ieee_one, 14915 redp ? mkexpr( frB ) : 14916 mkexpr( sqrt ) ) ) ), 14917 mkU64( 0 ) ) ); 14918 break; 14919 } 14920 14921 case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision) 14922 case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision) 14923 14924 { 14925 IRTemp frB = newTemp(Ity_F64); 14926 IRTemp sqrt = newTemp(Ity_F64); 14927 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)); 14928 IRExpr* rm = get_IR_roundingmode(); 14929 Bool redp = opc2 == 0x0B4; 14930 DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB); 14931 assign( frB, 14932 unop( Iop_ReinterpI64asF64, 14933 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 14934 14935 if (!redp) 14936 assign( sqrt, 14937 binop( Iop_SqrtF64, 14938 rm, 14939 mkexpr(frB) ) ); 14940 putVSReg( XT, 14941 binop( Iop_64HLtoV128, 14942 unop( Iop_ReinterpF64asI64, 14943 triop( Iop_DivF64, 14944 rm, 14945 ieee_one, 14946 redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ), 14947 mkU64( 0 ) ) ); 14948 break; 14949 } 14950 14951 case 0x232: // xsrsp (VSX Scalar Round to Single-Precision) 14952 { 14953 IRTemp frB = newTemp(Ity_F64); 14954 IRExpr* rm = get_IR_roundingmode(); 14955 DIP("xsrsp v%d, v%d\n", (UInt)XT, (UInt)XB); 14956 assign( frB, 14957 unop( Iop_ReinterpI64asF64, 14958 unop( Iop_V128HIto64, mkexpr( vB ) ) ) ); 14959 14960 putVSReg( XT, binop( Iop_64HLtoV128, 14961 unop( Iop_ReinterpF64asI64, 14962 binop( Iop_RoundF64toF32, 14963 rm, 14964 mkexpr( frB ) ) ), 14965 mkU64( 0 ) ) ); 14966 break; 14967 } 14968 14969 default: 14970 vex_printf( "dis_vxs_misc(ppc)(opc2)\n" ); 14971 return False; 14972 } 14973 return True; 14974 } 14975 14976 /* 14977 * VSX Logical Instructions 14978 */ 14979 static Bool 14980 dis_vx_logic ( UInt theInstr, UInt opc2 ) 14981 { 14982 /* XX3-Form */ 14983 UChar opc1 = ifieldOPC( theInstr ); 14984 UChar XT = ifieldRegXT ( theInstr ); 14985 UChar XA = ifieldRegXA ( theInstr ); 14986 UChar XB = ifieldRegXB ( theInstr ); 14987 IRTemp vA = newTemp( Ity_V128 ); 14988 IRTemp vB = newTemp( Ity_V128 ); 14989 14990 if (opc1 != 0x3C) { 14991 vex_printf( "dis_vx_logic(ppc)(instr)\n" ); 14992 return False; 14993 } 14994 14995 assign( vA, getVSReg( XA ) ); 14996 assign( vB, getVSReg( XB ) ); 14997 14998 switch (opc2) { 14999 case 0x268: // xxlxor 15000 DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15001 putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) ); 15002 break; 15003 case 0x248: // xxlor 15004 DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15005 putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) ); 15006 break; 15007 case 0x288: // xxlnor 15008 DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15009 putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ), 15010 mkexpr( vB ) ) ) ); 15011 break; 15012 case 0x208: // xxland 15013 DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15014 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) ); 15015 break; 15016 case 0x228: //xxlandc 15017 DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15018 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128, 15019 mkexpr( vB ) ) ) ); 15020 break; 15021 case 0x2A8: // xxlorc (VSX Logical OR with complement) 15022 DIP("xxlorc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15023 putVSReg( XT, binop( Iop_OrV128, 15024 mkexpr( vA ), 15025 unop( Iop_NotV128, mkexpr( vB ) ) ) ); 15026 break; 15027 case 0x2C8: // xxlnand (VSX Logical NAND) 15028 DIP("xxlnand v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15029 putVSReg( XT, unop( Iop_NotV128, 15030 binop( Iop_AndV128, mkexpr( vA ), 15031 mkexpr( vB ) ) ) ); 15032 break; 15033 case 0x2E8: // xxleqv (VSX Logical Equivalence) 15034 DIP("xxleqv v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB); 15035 putVSReg( XT, unop( Iop_NotV128, 15036 binop( Iop_XorV128, 15037 mkexpr( vA ), mkexpr( vB ) ) ) ); 15038 break; 15039 default: 15040 vex_printf( "dis_vx_logic(ppc)(opc2)\n" ); 15041 return False; 15042 } 15043 return True; 15044 } 15045 15046 /* 15047 * VSX Load Instructions 15048 * NOTE: VSX supports word-aligned storage access. 15049 */ 15050 static Bool 15051 dis_vx_load ( UInt theInstr ) 15052 { 15053 /* XX1-Form */ 15054 UChar opc1 = ifieldOPC( theInstr ); 15055 UChar XT = ifieldRegXT ( theInstr ); 15056 UChar rA_addr = ifieldRegA( theInstr ); 15057 UChar rB_addr = ifieldRegB( theInstr ); 15058 UInt opc2 = ifieldOPClo10( theInstr ); 15059 15060 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15061 IRTemp EA = newTemp( ty ); 15062 15063 if (opc1 != 0x1F) { 15064 vex_printf( "dis_vx_load(ppc)(instr)\n" ); 15065 return False; 15066 } 15067 15068 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 15069 15070 switch (opc2) { 15071 case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed) 15072 { 15073 IRExpr * exp; 15074 DIP("lxsiwzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15075 exp = unop( Iop_64HIto32, loadBE( Ity_I64, mkexpr( EA ) ) ); 15076 putVSReg( XT, binop( Iop_64HLtoV128, 15077 unop( Iop_32Uto64, exp), 15078 mkU64(0) ) ); 15079 break; 15080 } 15081 case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed) 15082 { 15083 IRExpr * exp; 15084 DIP("lxsiwax %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15085 exp = unop( Iop_64HIto32, loadBE( Ity_I64, mkexpr( EA ) ) ); 15086 putVSReg( XT, binop( Iop_64HLtoV128, 15087 unop( Iop_32Sto64, exp), 15088 mkU64(0) ) ); 15089 break; 15090 } 15091 case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed) 15092 { 15093 IRExpr * exp; 15094 DIP("lxsspx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15095 /* Take 32-bit floating point value in the upper half of the fetched 15096 * 64-bit value, convert to 64-bit floating point value and load into 15097 * top word of V128. 15098 */ 15099 exp = unop( Iop_ReinterpF64asI64, 15100 unop( Iop_F32toF64, 15101 unop( Iop_ReinterpI32asF32, 15102 unop( Iop_64HIto32, 15103 loadBE( Ity_I64, mkexpr( EA ) ) ) ) ) ); 15104 15105 putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) ); 15106 break; 15107 } 15108 case 0x24C: // lxsdx 15109 { 15110 IRExpr * exp; 15111 DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15112 exp = loadBE( Ity_I64, mkexpr( EA ) ); 15113 // We need to pass an expression of type Ity_V128 with putVSReg, but the load 15114 // we just performed is only a DW. But since the contents of VSR[XT] element 1 15115 // are undefined after this operation, we can just do a splat op. 15116 putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) ); 15117 break; 15118 } 15119 case 0x34C: // lxvd2x 15120 { 15121 IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32; 15122 IRExpr * high, *low; 15123 ULong ea_off = 8; 15124 IRExpr* high_addr; 15125 DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15126 high = loadBE( Ity_I64, mkexpr( EA ) ); 15127 high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off ) 15128 : mkU32( ea_off ) ); 15129 low = loadBE( Ity_I64, high_addr ); 15130 putVSReg( XT, binop( Iop_64HLtoV128, high, low ) ); 15131 break; 15132 } 15133 case 0x14C: // lxvdsx 15134 { 15135 IRTemp data = newTemp(Ity_I64); 15136 DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15137 assign( data, loadBE( Ity_I64, mkexpr( EA ) ) ); 15138 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) ); 15139 break; 15140 } 15141 case 0x30C: 15142 { 15143 IRExpr * t3, *t2, *t1, *t0; 15144 UInt ea_off = 0; 15145 IRExpr* irx_addr; 15146 15147 DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); 15148 t3 = loadBE( Ity_I32, mkexpr( EA ) ); 15149 ea_off += 4; 15150 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15151 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15152 t2 = loadBE( Ity_I32, irx_addr ); 15153 ea_off += 4; 15154 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15155 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15156 t1 = loadBE( Ity_I32, irx_addr ); 15157 ea_off += 4; 15158 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15159 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15160 t0 = loadBE( Ity_I32, irx_addr ); 15161 putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ), 15162 binop( Iop_32HLto64, t1, t0 ) ) ); 15163 break; 15164 } 15165 default: 15166 vex_printf( "dis_vx_load(ppc)(opc2)\n" ); 15167 return False; 15168 } 15169 return True; 15170 } 15171 15172 /* 15173 * VSX Store Instructions 15174 * NOTE: VSX supports word-aligned storage access. 15175 */ 15176 static Bool 15177 dis_vx_store ( UInt theInstr ) 15178 { 15179 /* XX1-Form */ 15180 UChar opc1 = ifieldOPC( theInstr ); 15181 UChar XS = ifieldRegXS( theInstr ); 15182 UChar rA_addr = ifieldRegA( theInstr ); 15183 UChar rB_addr = ifieldRegB( theInstr ); 15184 IRTemp vS = newTemp( Ity_V128 ); 15185 UInt opc2 = ifieldOPClo10( theInstr ); 15186 15187 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15188 IRTemp EA = newTemp( ty ); 15189 15190 if (opc1 != 0x1F) { 15191 vex_printf( "dis_vx_store(ppc)(instr)\n" ); 15192 return False; 15193 } 15194 15195 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) ); 15196 assign( vS, getVSReg( XS ) ); 15197 15198 switch (opc2) { 15199 case 0x08C: 15200 { 15201 /* Need the next to the most significant 32-bit word from 15202 * the 128-bit vector. 15203 */ 15204 IRExpr * high64, * low32; 15205 DIP("stxsiwx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15206 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15207 low32 = unop( Iop_64to32, high64 ); 15208 storeBE( mkexpr( EA ), low32 ); 15209 break; 15210 } 15211 case 0x28C: 15212 { 15213 IRTemp high64 = newTemp(Ity_F64); 15214 IRTemp val32 = newTemp(Ity_I32); 15215 DIP("stxsspx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15216 assign(high64, unop( Iop_ReinterpI64asF64, 15217 unop( Iop_V128HIto64, mkexpr( vS ) ) ) ); 15218 assign(val32, unop( Iop_ReinterpF32asI32, 15219 unop( Iop_TruncF64asF32, 15220 mkexpr(high64) ) ) ); 15221 storeBE( mkexpr( EA ), mkexpr( val32 ) ); 15222 break; 15223 } 15224 case 0x2CC: 15225 { 15226 IRExpr * high64; 15227 DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15228 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15229 storeBE( mkexpr( EA ), high64 ); 15230 break; 15231 } 15232 case 0x3CC: 15233 { 15234 IRExpr * high64, *low64; 15235 DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15236 high64 = unop( Iop_V128HIto64, mkexpr( vS ) ); 15237 low64 = unop( Iop_V128to64, mkexpr( vS ) ); 15238 storeBE( mkexpr( EA ), high64 ); 15239 storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 ) 15240 : mkU32( 8 ) ), low64 ); 15241 break; 15242 } 15243 case 0x38C: 15244 { 15245 UInt ea_off = 0; 15246 IRExpr* irx_addr; 15247 IRTemp hi64 = newTemp( Ity_I64 ); 15248 IRTemp lo64 = newTemp( Ity_I64 ); 15249 15250 DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr); 15251 15252 // This instruction supports word-aligned stores, so EA may not be 15253 // quad-word aligned. Therefore, do 4 individual word-size stores. 15254 assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) ); 15255 assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) ); 15256 15257 storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) ); 15258 ea_off += 4; 15259 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15260 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15261 storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) ); 15262 ea_off += 4; 15263 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15264 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15265 storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) ); 15266 ea_off += 4; 15267 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), 15268 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) ); 15269 storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) ); 15270 15271 break; 15272 } 15273 default: 15274 vex_printf( "dis_vx_store(ppc)(opc2)\n" ); 15275 return False; 15276 } 15277 return True; 15278 } 15279 15280 /* 15281 * VSX permute and other miscealleous instructions 15282 */ 15283 static Bool 15284 dis_vx_permute_misc( UInt theInstr, UInt opc2 ) 15285 { 15286 /* XX3-Form */ 15287 UChar opc1 = ifieldOPC( theInstr ); 15288 UChar XT = ifieldRegXT ( theInstr ); 15289 UChar XA = ifieldRegXA ( theInstr ); 15290 UChar XB = ifieldRegXB ( theInstr ); 15291 IRTemp vT = newTemp( Ity_V128 ); 15292 IRTemp vA = newTemp( Ity_V128 ); 15293 IRTemp vB = newTemp( Ity_V128 ); 15294 15295 if (opc1 != 0x3C) { 15296 vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" ); 15297 return False; 15298 } 15299 15300 assign( vA, getVSReg( XA ) ); 15301 assign( vB, getVSReg( XB ) ); 15302 15303 switch (opc2) { 15304 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate) 15305 { 15306 UChar SHW = ifieldSHW ( theInstr ); 15307 IRTemp result = newTemp(Ity_V128); 15308 if ( SHW != 0 ) { 15309 IRTemp hi = newTemp(Ity_V128); 15310 IRTemp lo = newTemp(Ity_V128); 15311 assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) ); 15312 assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) ); 15313 assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) ); 15314 } else 15315 assign ( result, mkexpr(vA) ); 15316 DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW); 15317 putVSReg( XT, mkexpr(result) ); 15318 break; 15319 } 15320 case 0x28: // xpermdi (VSX Permute Doubleword Immediate) 15321 { 15322 UChar DM = ifieldDM ( theInstr ); 15323 IRTemp hi = newTemp(Ity_I64); 15324 IRTemp lo = newTemp(Ity_I64); 15325 15326 if (DM & 0x2) 15327 assign( hi, unop(Iop_V128to64, mkexpr(vA)) ); 15328 else 15329 assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) ); 15330 15331 if (DM & 0x1) 15332 assign( lo, unop(Iop_V128to64, mkexpr(vB)) ); 15333 else 15334 assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) ); 15335 15336 assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) ); 15337 15338 DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM); 15339 putVSReg( XT, mkexpr( vT ) ); 15340 break; 15341 } 15342 case 0x48: // xxmrghw (VSX Merge High Word) 15343 case 0xc8: // xxmrglw (VSX Merge Low Word) 15344 { 15345 const HChar type = (opc2 == 0x48) ? 'h' : 'l'; 15346 IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64; 15347 IRTemp a64 = newTemp(Ity_I64); 15348 IRTemp ahi32 = newTemp(Ity_I32); 15349 IRTemp alo32 = newTemp(Ity_I32); 15350 IRTemp b64 = newTemp(Ity_I64); 15351 IRTemp bhi32 = newTemp(Ity_I32); 15352 IRTemp blo32 = newTemp(Ity_I32); 15353 15354 assign( a64, unop(word_op, mkexpr(vA)) ); 15355 assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) ); 15356 assign( alo32, unop(Iop_64to32, mkexpr(a64)) ); 15357 15358 assign( b64, unop(word_op, mkexpr(vB)) ); 15359 assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) ); 15360 assign( blo32, unop(Iop_64to32, mkexpr(b64)) ); 15361 15362 assign( vT, binop(Iop_64HLtoV128, 15363 binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)), 15364 binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) ); 15365 15366 DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB); 15367 putVSReg( XT, mkexpr( vT ) ); 15368 break; 15369 } 15370 case 0x018: // xxsel (VSX Select) 15371 { 15372 UChar XC = ifieldRegXC(theInstr); 15373 IRTemp vC = newTemp( Ity_V128 ); 15374 assign( vC, getVSReg( XC ) ); 15375 DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC); 15376 /* vD = (vA & ~vC) | (vB & vC) */ 15377 putVSReg( XT, binop(Iop_OrV128, 15378 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 15379 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 15380 break; 15381 } 15382 case 0x148: // xxspltw (VSX Splat Word) 15383 { 15384 UChar UIM = ifieldRegA(theInstr) & 3; 15385 UChar sh_uim = (3 - (UIM)) * 32; 15386 DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM); 15387 putVSReg( XT, 15388 unop( Iop_Dup32x4, 15389 unop( Iop_V128to32, 15390 binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) ); 15391 break; 15392 } 15393 15394 default: 15395 vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" ); 15396 return False; 15397 } 15398 return True; 15399 } 15400 15401 /* 15402 AltiVec Load Instructions 15403 */ 15404 static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr ) 15405 { 15406 /* X-Form */ 15407 UChar opc1 = ifieldOPC(theInstr); 15408 UChar vD_addr = ifieldRegDS(theInstr); 15409 UChar rA_addr = ifieldRegA(theInstr); 15410 UChar rB_addr = ifieldRegB(theInstr); 15411 UInt opc2 = ifieldOPClo10(theInstr); 15412 UChar b0 = ifieldBIT0(theInstr); 15413 15414 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15415 IRTemp EA = newTemp(ty); 15416 IRTemp EA_align16 = newTemp(ty); 15417 15418 if (opc1 != 0x1F || b0 != 0) { 15419 vex_printf("dis_av_load(ppc)(instr)\n"); 15420 return False; 15421 } 15422 15423 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 15424 assign( EA_align16, addr_align( mkexpr(EA), 16 ) ); 15425 15426 switch (opc2) { 15427 15428 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123) 15429 IRDirty* d; 15430 UInt vD_off = vectorGuestRegOffset(vD_addr); 15431 IRExpr** args = mkIRExprVec_4( 15432 IRExpr_BBPTR(), 15433 mkU32(vD_off), 15434 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15435 mkU32(0xF)), 15436 mkU32(0)/*left*/ ); 15437 if (!mode64) { 15438 d = unsafeIRDirty_0_N ( 15439 0/*regparms*/, 15440 "ppc32g_dirtyhelper_LVS", 15441 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 15442 args ); 15443 } else { 15444 d = unsafeIRDirty_0_N ( 15445 0/*regparms*/, 15446 "ppc64g_dirtyhelper_LVS", 15447 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 15448 args ); 15449 } 15450 DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15451 /* declare guest state effects */ 15452 d->nFxState = 1; 15453 vex_bzero(&d->fxState, sizeof(d->fxState)); 15454 d->fxState[0].fx = Ifx_Write; 15455 d->fxState[0].offset = vD_off; 15456 d->fxState[0].size = sizeof(U128); 15457 15458 /* execute the dirty call, side-effecting guest state */ 15459 stmt( IRStmt_Dirty(d) ); 15460 break; 15461 } 15462 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125) 15463 IRDirty* d; 15464 UInt vD_off = vectorGuestRegOffset(vD_addr); 15465 IRExpr** args = mkIRExprVec_4( 15466 IRExpr_BBPTR(), 15467 mkU32(vD_off), 15468 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)), 15469 mkU32(0xF)), 15470 mkU32(1)/*right*/ ); 15471 if (!mode64) { 15472 d = unsafeIRDirty_0_N ( 15473 0/*regparms*/, 15474 "ppc32g_dirtyhelper_LVS", 15475 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS), 15476 args ); 15477 } else { 15478 d = unsafeIRDirty_0_N ( 15479 0/*regparms*/, 15480 "ppc64g_dirtyhelper_LVS", 15481 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS), 15482 args ); 15483 } 15484 DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15485 /* declare guest state effects */ 15486 d->nFxState = 1; 15487 vex_bzero(&d->fxState, sizeof(d->fxState)); 15488 d->fxState[0].fx = Ifx_Write; 15489 d->fxState[0].offset = vD_off; 15490 d->fxState[0].size = sizeof(U128); 15491 15492 /* execute the dirty call, side-effecting guest state */ 15493 stmt( IRStmt_Dirty(d) ); 15494 break; 15495 } 15496 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119) 15497 DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15498 /* loads addressed byte into vector[EA[0:3] 15499 since all other destination bytes are undefined, 15500 can simply load entire vector from 16-aligned EA */ 15501 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 15502 break; 15503 15504 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121) 15505 DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15506 /* see note for lvebx */ 15507 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 15508 break; 15509 15510 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122) 15511 DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15512 /* see note for lvebx */ 15513 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 15514 break; 15515 15516 case 0x067: // lvx (Load Vector Indexed, AV p127) 15517 DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15518 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 15519 break; 15520 15521 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128) 15522 DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); 15523 putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) ); 15524 break; 15525 15526 default: 15527 vex_printf("dis_av_load(ppc)(opc2)\n"); 15528 return False; 15529 } 15530 return True; 15531 } 15532 15533 /* 15534 AltiVec Store Instructions 15535 */ 15536 static Bool dis_av_store ( UInt theInstr ) 15537 { 15538 /* X-Form */ 15539 UChar opc1 = ifieldOPC(theInstr); 15540 UChar vS_addr = ifieldRegDS(theInstr); 15541 UChar rA_addr = ifieldRegA(theInstr); 15542 UChar rB_addr = ifieldRegB(theInstr); 15543 UInt opc2 = ifieldOPClo10(theInstr); 15544 UChar b0 = ifieldBIT0(theInstr); 15545 15546 IRType ty = mode64 ? Ity_I64 : Ity_I32; 15547 IRTemp EA = newTemp(ty); 15548 IRTemp addr_aligned = newTemp(ty); 15549 IRTemp vS = newTemp(Ity_V128); 15550 IRTemp eb = newTemp(Ity_I8); 15551 IRTemp idx = newTemp(Ity_I8); 15552 15553 if (opc1 != 0x1F || b0 != 0) { 15554 vex_printf("dis_av_store(ppc)(instr)\n"); 15555 return False; 15556 } 15557 15558 assign( vS, getVReg(vS_addr)); 15559 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) ); 15560 15561 switch (opc2) { 15562 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131) 15563 DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15564 assign( eb, binop(Iop_And8, mkU8(0xF), 15565 unop(Iop_32to8, 15566 mkNarrowTo32(ty, mkexpr(EA)) )) ); 15567 assign( idx, binop(Iop_Shl8, 15568 binop(Iop_Sub8, mkU8(15), mkexpr(eb)), 15569 mkU8(3)) ); 15570 storeBE( mkexpr(EA), 15571 unop(Iop_32to8, unop(Iop_V128to32, 15572 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 15573 break; 15574 } 15575 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132) 15576 DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15577 assign( addr_aligned, addr_align(mkexpr(EA), 2) ); 15578 assign( eb, binop(Iop_And8, mkU8(0xF), 15579 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 15580 assign( idx, binop(Iop_Shl8, 15581 binop(Iop_Sub8, mkU8(14), mkexpr(eb)), 15582 mkU8(3)) ); 15583 storeBE( mkexpr(addr_aligned), 15584 unop(Iop_32to16, unop(Iop_V128to32, 15585 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) ); 15586 break; 15587 } 15588 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133) 15589 DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15590 assign( addr_aligned, addr_align(mkexpr(EA), 4) ); 15591 assign( eb, binop(Iop_And8, mkU8(0xF), 15592 mkNarrowTo8(ty, mkexpr(addr_aligned) )) ); 15593 assign( idx, binop(Iop_Shl8, 15594 binop(Iop_Sub8, mkU8(12), mkexpr(eb)), 15595 mkU8(3)) ); 15596 storeBE( mkexpr(addr_aligned), 15597 unop(Iop_V128to32, 15598 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) ); 15599 break; 15600 } 15601 15602 case 0x0E7: // stvx (Store Vector Indexed, AV p134) 15603 DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15604 storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 15605 break; 15606 15607 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135) 15608 DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr); 15609 storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) ); 15610 break; 15611 15612 default: 15613 vex_printf("dis_av_store(ppc)(opc2)\n"); 15614 return False; 15615 } 15616 return True; 15617 } 15618 15619 /* 15620 AltiVec Arithmetic Instructions 15621 */ 15622 static Bool dis_av_arith ( UInt theInstr ) 15623 { 15624 /* VX-Form */ 15625 UChar opc1 = ifieldOPC(theInstr); 15626 UChar vD_addr = ifieldRegDS(theInstr); 15627 UChar vA_addr = ifieldRegA(theInstr); 15628 UChar vB_addr = ifieldRegB(theInstr); 15629 UInt opc2 = IFIELD( theInstr, 0, 11 ); 15630 15631 IRTemp vA = newTemp(Ity_V128); 15632 IRTemp vB = newTemp(Ity_V128); 15633 IRTemp z3 = newTemp(Ity_I64); 15634 IRTemp z2 = newTemp(Ity_I64); 15635 IRTemp z1 = newTemp(Ity_I64); 15636 IRTemp z0 = newTemp(Ity_I64); 15637 IRTemp aEvn, aOdd; 15638 IRTemp a15, a14, a13, a12, a11, a10, a9, a8; 15639 IRTemp a7, a6, a5, a4, a3, a2, a1, a0; 15640 IRTemp b3, b2, b1, b0; 15641 15642 aEvn = aOdd = IRTemp_INVALID; 15643 a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID; 15644 a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID; 15645 b3 = b2 = b1 = b0 = IRTemp_INVALID; 15646 15647 assign( vA, getVReg(vA_addr)); 15648 assign( vB, getVReg(vB_addr)); 15649 15650 if (opc1 != 0x4) { 15651 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n"); 15652 return False; 15653 } 15654 15655 switch (opc2) { 15656 /* Add */ 15657 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136) 15658 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15659 /* unsigned_ov(x+y) = (y >u not(x)) */ 15660 putVReg( vD_addr, binop(Iop_ShrN32x4, 15661 binop(Iop_CmpGT32Ux4, mkexpr(vB), 15662 unop(Iop_NotV128, mkexpr(vA))), 15663 mkU8(31)) ); 15664 break; 15665 } 15666 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141) 15667 DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15668 putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) ); 15669 break; 15670 15671 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143) 15672 DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15673 putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) ); 15674 break; 15675 15676 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145) 15677 DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15678 putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) ); 15679 break; 15680 15681 case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo) 15682 DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15683 putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) ); 15684 break; 15685 15686 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142) 15687 DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15688 putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) ); 15689 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16 15690 break; 15691 15692 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144) 15693 DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15694 putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) ); 15695 // TODO: set VSCR[SAT] 15696 break; 15697 15698 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146) 15699 DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15700 putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) ); 15701 // TODO: set VSCR[SAT] 15702 break; 15703 15704 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138) 15705 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15706 putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) ); 15707 // TODO: set VSCR[SAT] 15708 break; 15709 15710 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139) 15711 DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15712 putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) ); 15713 // TODO: set VSCR[SAT] 15714 break; 15715 15716 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140) 15717 DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15718 putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) ); 15719 // TODO: set VSCR[SAT] 15720 break; 15721 15722 15723 /* Subtract */ 15724 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260) 15725 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15726 /* unsigned_ov(x-y) = (y >u x) */ 15727 putVReg( vD_addr, binop(Iop_ShrN32x4, 15728 unop(Iop_NotV128, 15729 binop(Iop_CmpGT32Ux4, mkexpr(vB), 15730 mkexpr(vA))), 15731 mkU8(31)) ); 15732 break; 15733 } 15734 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265) 15735 DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15736 putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) ); 15737 break; 15738 15739 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267) 15740 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15741 putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) ); 15742 break; 15743 15744 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269) 15745 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15746 putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) ); 15747 break; 15748 15749 case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo) 15750 DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15751 putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) ); 15752 break; 15753 15754 case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266) 15755 DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15756 putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) ); 15757 // TODO: set VSCR[SAT] 15758 break; 15759 15760 case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268) 15761 DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15762 putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) ); 15763 // TODO: set VSCR[SAT] 15764 break; 15765 15766 case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270) 15767 DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15768 putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) ); 15769 // TODO: set VSCR[SAT] 15770 break; 15771 15772 case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262) 15773 DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15774 putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) ); 15775 // TODO: set VSCR[SAT] 15776 break; 15777 15778 case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263) 15779 DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15780 putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) ); 15781 // TODO: set VSCR[SAT] 15782 break; 15783 15784 case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264) 15785 DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15786 putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) ); 15787 // TODO: set VSCR[SAT] 15788 break; 15789 15790 15791 /* Maximum */ 15792 case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182) 15793 DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15794 putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) ); 15795 break; 15796 15797 case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183) 15798 DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15799 putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) ); 15800 break; 15801 15802 case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184) 15803 DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15804 putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) ); 15805 break; 15806 15807 case 0x0C2: // vmaxud (Maximum Unsigned Double word) 15808 DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15809 putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) ); 15810 break; 15811 15812 case 0x102: // vmaxsb (Maximum Signed Byte, AV p179) 15813 DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15814 putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) ); 15815 break; 15816 15817 case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180) 15818 DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15819 putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) ); 15820 break; 15821 15822 case 0x182: // vmaxsw (Maximum Signed Word, AV p181) 15823 DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15824 putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) ); 15825 break; 15826 15827 case 0x1C2: // vmaxsd (Maximum Signed Double word) 15828 DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15829 putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) ); 15830 break; 15831 15832 /* Minimum */ 15833 case 0x202: // vminub (Minimum Unsigned Byte, AV p191) 15834 DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15835 putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) ); 15836 break; 15837 15838 case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192) 15839 DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15840 putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) ); 15841 break; 15842 15843 case 0x282: // vminuw (Minimum Unsigned Word, AV p193) 15844 DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15845 putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) ); 15846 break; 15847 15848 case 0x2C2: // vminud (Minimum Unsigned Double Word) 15849 DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15850 putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) ); 15851 break; 15852 15853 case 0x302: // vminsb (Minimum Signed Byte, AV p188) 15854 DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15855 putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) ); 15856 break; 15857 15858 case 0x342: // vminsh (Minimum Signed Half Word, AV p189) 15859 DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15860 putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) ); 15861 break; 15862 15863 case 0x382: // vminsw (Minimum Signed Word, AV p190) 15864 DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15865 putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) ); 15866 break; 15867 15868 case 0x3C2: // vminsd (Minimum Signed Double Word) 15869 DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15870 putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) ); 15871 break; 15872 15873 15874 /* Average */ 15875 case 0x402: // vavgub (Average Unsigned Byte, AV p152) 15876 DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15877 putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) ); 15878 break; 15879 15880 case 0x442: // vavguh (Average Unsigned Half Word, AV p153) 15881 DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15882 putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) ); 15883 break; 15884 15885 case 0x482: // vavguw (Average Unsigned Word, AV p154) 15886 DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15887 putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) ); 15888 break; 15889 15890 case 0x502: // vavgsb (Average Signed Byte, AV p149) 15891 DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15892 putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) ); 15893 break; 15894 15895 case 0x542: // vavgsh (Average Signed Half Word, AV p150) 15896 DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15897 putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) ); 15898 break; 15899 15900 case 0x582: // vavgsw (Average Signed Word, AV p151) 15901 DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15902 putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) ); 15903 break; 15904 15905 15906 /* Multiply */ 15907 case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213) 15908 DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15909 putVReg( vD_addr, 15910 binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB))); 15911 break; 15912 15913 case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214) 15914 DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15915 putVReg( vD_addr, 15916 binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB))); 15917 break; 15918 15919 case 0x088: // vmulouw (Multiply Odd Unsigned Word) 15920 DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15921 putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) ); 15922 break; 15923 15924 case 0x089: // vmuluwm (Multiply Unsigned Word Modulo) 15925 DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15926 putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) ); 15927 break; 15928 15929 case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211) 15930 DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15931 putVReg( vD_addr, 15932 binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB))); 15933 break; 15934 15935 case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212) 15936 DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15937 putVReg( vD_addr, 15938 binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB))); 15939 break; 15940 15941 case 0x188: // vmulosw (Multiply Odd Signed Word) 15942 DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15943 putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) ); 15944 break; 15945 15946 case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209) 15947 DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15948 putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 15949 break; 15950 15951 case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210) 15952 DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15953 putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 15954 break; 15955 15956 case 0x288: // vmuleuw (Multiply Even Unsigned Word) 15957 DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15958 putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) ); 15959 break; 15960 15961 case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207) 15962 DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15963 putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) )); 15964 break; 15965 15966 case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208) 15967 DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15968 putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 15969 break; 15970 15971 case 0x388: // vmulesw (Multiply Even Signed Word) 15972 DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15973 putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) ); 15974 break; 15975 15976 /* Sum Across Partial */ 15977 case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275) 15978 IRTemp aEE, aEO, aOE, aOO; 15979 aEE = aEO = aOE = aOO = IRTemp_INVALID; 15980 DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 15981 15982 /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */ 15983 expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 15984 expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 15985 expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 15986 15987 /* break V128 to 4xI32's, zero-extending to I64's */ 15988 breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 15989 breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 15990 breakV128to4x64U( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 15991 breakV128to4x64U( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 15992 breakV128to4x64U( mkexpr(vB), &b3, &b2, &b1, &b0 ); 15993 15994 /* add lanes */ 15995 assign( z3, binop(Iop_Add64, mkexpr(b3), 15996 binop(Iop_Add64, 15997 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 15998 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 15999 assign( z2, binop(Iop_Add64, mkexpr(b2), 16000 binop(Iop_Add64, 16001 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 16002 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 16003 assign( z1, binop(Iop_Add64, mkexpr(b1), 16004 binop(Iop_Add64, 16005 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 16006 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 16007 assign( z0, binop(Iop_Add64, mkexpr(b0), 16008 binop(Iop_Add64, 16009 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 16010 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 16011 16012 /* saturate-narrow to 32bit, and combine to V128 */ 16013 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 16014 mkexpr(z1), mkexpr(z0)) ); 16015 break; 16016 } 16017 case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273) 16018 IRTemp aEE, aEO, aOE, aOO; 16019 aEE = aEO = aOE = aOO = IRTemp_INVALID; 16020 DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16021 16022 /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */ 16023 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...) 16024 expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...) 16025 expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...) 16026 16027 /* break V128 to 4xI32's, sign-extending to I64's */ 16028 breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 ); 16029 breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 ); 16030 breakV128to4x64S( mkexpr(aEO), &a13, &a9, &a5, &a1 ); 16031 breakV128to4x64S( mkexpr(aOO), &a12, &a8, &a4, &a0 ); 16032 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16033 16034 /* add lanes */ 16035 assign( z3, binop(Iop_Add64, mkexpr(b3), 16036 binop(Iop_Add64, 16037 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)), 16038 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) ); 16039 assign( z2, binop(Iop_Add64, mkexpr(b2), 16040 binop(Iop_Add64, 16041 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)), 16042 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) ); 16043 assign( z1, binop(Iop_Add64, mkexpr(b1), 16044 binop(Iop_Add64, 16045 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)), 16046 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) ); 16047 assign( z0, binop(Iop_Add64, mkexpr(b0), 16048 binop(Iop_Add64, 16049 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 16050 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 16051 16052 /* saturate-narrow to 32bit, and combine to V128 */ 16053 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 16054 mkexpr(z1), mkexpr(z0)) ); 16055 break; 16056 } 16057 case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274) 16058 DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16059 16060 /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */ 16061 expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...) 16062 16063 /* break V128 to 4xI32's, sign-extending to I64's */ 16064 breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 ); 16065 breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 ); 16066 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16067 16068 /* add lanes */ 16069 assign( z3, binop(Iop_Add64, mkexpr(b3), 16070 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)))); 16071 assign( z2, binop(Iop_Add64, mkexpr(b2), 16072 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))); 16073 assign( z1, binop(Iop_Add64, mkexpr(b1), 16074 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)))); 16075 assign( z0, binop(Iop_Add64, mkexpr(b0), 16076 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))); 16077 16078 /* saturate-narrow to 32bit, and combine to V128 */ 16079 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 16080 mkexpr(z1), mkexpr(z0)) ); 16081 break; 16082 } 16083 case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272) 16084 DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16085 16086 /* break V128 to 4xI32's, sign-extending to I64's */ 16087 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 16088 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16089 16090 /* add lanes */ 16091 assign( z2, binop(Iop_Add64, mkexpr(b2), 16092 binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) ); 16093 assign( z0, binop(Iop_Add64, mkexpr(b0), 16094 binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) ); 16095 16096 /* saturate-narrow to 32bit, and combine to V128 */ 16097 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2), 16098 mkU64(0), mkexpr(z0)) ); 16099 break; 16100 } 16101 case 0x788: { // vsumsws (Sum SW Saturate, AV p271) 16102 DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16103 16104 /* break V128 to 4xI32's, sign-extending to I64's */ 16105 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 ); 16106 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 ); 16107 16108 /* add lanes */ 16109 assign( z0, binop(Iop_Add64, mkexpr(b0), 16110 binop(Iop_Add64, 16111 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)), 16112 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) ); 16113 16114 /* saturate-narrow to 32bit, and combine to V128 */ 16115 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0), 16116 mkU64(0), mkexpr(z0)) ); 16117 break; 16118 } 16119 default: 16120 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2); 16121 return False; 16122 } 16123 return True; 16124 } 16125 16126 /* 16127 AltiVec Logic Instructions 16128 */ 16129 static Bool dis_av_logic ( UInt theInstr ) 16130 { 16131 /* VX-Form */ 16132 UChar opc1 = ifieldOPC(theInstr); 16133 UChar vD_addr = ifieldRegDS(theInstr); 16134 UChar vA_addr = ifieldRegA(theInstr); 16135 UChar vB_addr = ifieldRegB(theInstr); 16136 UInt opc2 = IFIELD( theInstr, 0, 11 ); 16137 16138 IRTemp vA = newTemp(Ity_V128); 16139 IRTemp vB = newTemp(Ity_V128); 16140 assign( vA, getVReg(vA_addr)); 16141 assign( vB, getVReg(vB_addr)); 16142 16143 if (opc1 != 0x4) { 16144 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n"); 16145 return False; 16146 } 16147 16148 switch (opc2) { 16149 case 0x404: // vand (And, AV p147) 16150 DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16151 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) ); 16152 break; 16153 16154 case 0x444: // vandc (And, AV p148) 16155 DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16156 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), 16157 unop(Iop_NotV128, mkexpr(vB))) ); 16158 break; 16159 16160 case 0x484: // vor (Or, AV p217) 16161 DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16162 putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) ); 16163 break; 16164 16165 case 0x4C4: // vxor (Xor, AV p282) 16166 DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16167 putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) ); 16168 break; 16169 16170 case 0x504: // vnor (Nor, AV p216) 16171 DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16172 putVReg( vD_addr, 16173 unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) ); 16174 break; 16175 16176 case 0x544: // vorc (vA Or'd with complement of vb) 16177 DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16178 putVReg( vD_addr, binop( Iop_OrV128, 16179 mkexpr( vA ), 16180 unop( Iop_NotV128, mkexpr( vB ) ) ) ); 16181 break; 16182 16183 case 0x584: // vnand (Nand) 16184 DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16185 putVReg( vD_addr, unop( Iop_NotV128, 16186 binop(Iop_AndV128, mkexpr( vA ), 16187 mkexpr( vB ) ) ) ); 16188 break; 16189 16190 case 0x684: // veqv (complemented XOr) 16191 DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16192 putVReg( vD_addr, unop( Iop_NotV128, 16193 binop( Iop_XorV128, mkexpr( vA ), 16194 mkexpr( vB ) ) ) ); 16195 break; 16196 16197 default: 16198 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2); 16199 return False; 16200 } 16201 return True; 16202 } 16203 16204 /* 16205 AltiVec Compare Instructions 16206 */ 16207 static Bool dis_av_cmp ( UInt theInstr ) 16208 { 16209 /* VXR-Form */ 16210 UChar opc1 = ifieldOPC(theInstr); 16211 UChar vD_addr = ifieldRegDS(theInstr); 16212 UChar vA_addr = ifieldRegA(theInstr); 16213 UChar vB_addr = ifieldRegB(theInstr); 16214 UChar flag_rC = ifieldBIT10(theInstr); 16215 UInt opc2 = IFIELD( theInstr, 0, 10 ); 16216 16217 IRTemp vA = newTemp(Ity_V128); 16218 IRTemp vB = newTemp(Ity_V128); 16219 IRTemp vD = newTemp(Ity_V128); 16220 assign( vA, getVReg(vA_addr)); 16221 assign( vB, getVReg(vB_addr)); 16222 16223 if (opc1 != 0x4) { 16224 vex_printf("dis_av_cmp(ppc)(instr)\n"); 16225 return False; 16226 } 16227 16228 switch (opc2) { 16229 case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160) 16230 DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16231 vD_addr, vA_addr, vB_addr); 16232 assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) ); 16233 break; 16234 16235 case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161) 16236 DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16237 vD_addr, vA_addr, vB_addr); 16238 assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) ); 16239 break; 16240 16241 case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162) 16242 DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16243 vD_addr, vA_addr, vB_addr); 16244 assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) ); 16245 break; 16246 16247 case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword) 16248 DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16249 vD_addr, vA_addr, vB_addr); 16250 assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) ); 16251 break; 16252 16253 case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168) 16254 DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16255 vD_addr, vA_addr, vB_addr); 16256 assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) ); 16257 break; 16258 16259 case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169) 16260 DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16261 vD_addr, vA_addr, vB_addr); 16262 assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) ); 16263 break; 16264 16265 case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170) 16266 DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16267 vD_addr, vA_addr, vB_addr); 16268 assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) ); 16269 break; 16270 16271 case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double) 16272 DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16273 vD_addr, vA_addr, vB_addr); 16274 assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) ); 16275 break; 16276 16277 case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165) 16278 DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16279 vD_addr, vA_addr, vB_addr); 16280 assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) ); 16281 break; 16282 16283 case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166) 16284 DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16285 vD_addr, vA_addr, vB_addr); 16286 assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) ); 16287 break; 16288 16289 case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167) 16290 DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16291 vD_addr, vA_addr, vB_addr); 16292 assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) ); 16293 break; 16294 16295 case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double) 16296 DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 16297 vD_addr, vA_addr, vB_addr); 16298 assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) ); 16299 break; 16300 16301 default: 16302 vex_printf("dis_av_cmp(ppc)(opc2)\n"); 16303 return False; 16304 } 16305 16306 putVReg( vD_addr, mkexpr(vD) ); 16307 16308 if (flag_rC) { 16309 set_AV_CR6( mkexpr(vD), True ); 16310 } 16311 return True; 16312 } 16313 16314 /* 16315 AltiVec Multiply-Sum Instructions 16316 */ 16317 static Bool dis_av_multarith ( UInt theInstr ) 16318 { 16319 /* VA-Form */ 16320 UChar opc1 = ifieldOPC(theInstr); 16321 UChar vD_addr = ifieldRegDS(theInstr); 16322 UChar vA_addr = ifieldRegA(theInstr); 16323 UChar vB_addr = ifieldRegB(theInstr); 16324 UChar vC_addr = ifieldRegC(theInstr); 16325 UChar opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 16326 16327 IRTemp vA = newTemp(Ity_V128); 16328 IRTemp vB = newTemp(Ity_V128); 16329 IRTemp vC = newTemp(Ity_V128); 16330 IRTemp zeros = newTemp(Ity_V128); 16331 IRTemp aLo = newTemp(Ity_V128); 16332 IRTemp bLo = newTemp(Ity_V128); 16333 IRTemp cLo = newTemp(Ity_V128); 16334 IRTemp zLo = newTemp(Ity_V128); 16335 IRTemp aHi = newTemp(Ity_V128); 16336 IRTemp bHi = newTemp(Ity_V128); 16337 IRTemp cHi = newTemp(Ity_V128); 16338 IRTemp zHi = newTemp(Ity_V128); 16339 IRTemp abEvn = newTemp(Ity_V128); 16340 IRTemp abOdd = newTemp(Ity_V128); 16341 IRTemp z3 = newTemp(Ity_I64); 16342 IRTemp z2 = newTemp(Ity_I64); 16343 IRTemp z1 = newTemp(Ity_I64); 16344 IRTemp z0 = newTemp(Ity_I64); 16345 IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0; 16346 IRTemp c3, c2, c1, c0; 16347 16348 ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID; 16349 c3 = c2 = c1 = c0 = IRTemp_INVALID; 16350 16351 assign( vA, getVReg(vA_addr)); 16352 assign( vB, getVReg(vB_addr)); 16353 assign( vC, getVReg(vC_addr)); 16354 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 16355 16356 if (opc1 != 0x4) { 16357 vex_printf("dis_av_multarith(ppc)(instr)\n"); 16358 return False; 16359 } 16360 16361 switch (opc2) { 16362 /* Multiply-Add */ 16363 case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185) 16364 IRTemp cSigns = newTemp(Ity_V128); 16365 DIP("vmhaddshs v%d,v%d,v%d,v%d\n", 16366 vD_addr, vA_addr, vB_addr, vC_addr); 16367 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC))); 16368 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 16369 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 16370 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 16371 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 16372 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 16373 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 16374 16375 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 16376 binop(Iop_SarN32x4, 16377 binop(Iop_MullEven16Sx8, 16378 mkexpr(aLo), mkexpr(bLo)), 16379 mkU8(15))) ); 16380 16381 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 16382 binop(Iop_SarN32x4, 16383 binop(Iop_MullEven16Sx8, 16384 mkexpr(aHi), mkexpr(bHi)), 16385 mkU8(15))) ); 16386 16387 putVReg( vD_addr, 16388 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 16389 break; 16390 } 16391 case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186) 16392 IRTemp zKonst = newTemp(Ity_V128); 16393 IRTemp cSigns = newTemp(Ity_V128); 16394 DIP("vmhraddshs v%d,v%d,v%d,v%d\n", 16395 vD_addr, vA_addr, vB_addr, vC_addr); 16396 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) ); 16397 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 16398 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 16399 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC))); 16400 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 16401 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 16402 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC))); 16403 16404 /* shifting our const avoids store/load version of Dup */ 16405 assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)), 16406 mkU8(14)) ); 16407 16408 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo), 16409 binop(Iop_SarN32x4, 16410 binop(Iop_Add32x4, mkexpr(zKonst), 16411 binop(Iop_MullEven16Sx8, 16412 mkexpr(aLo), mkexpr(bLo))), 16413 mkU8(15))) ); 16414 16415 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi), 16416 binop(Iop_SarN32x4, 16417 binop(Iop_Add32x4, mkexpr(zKonst), 16418 binop(Iop_MullEven16Sx8, 16419 mkexpr(aHi), mkexpr(bHi))), 16420 mkU8(15))) ); 16421 16422 putVReg( vD_addr, 16423 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) ); 16424 break; 16425 } 16426 case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194) 16427 DIP("vmladduhm v%d,v%d,v%d,v%d\n", 16428 vD_addr, vA_addr, vB_addr, vC_addr); 16429 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA))); 16430 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB))); 16431 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC))); 16432 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA))); 16433 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB))); 16434 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC))); 16435 assign(zLo, binop(Iop_Add32x4, 16436 binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)), 16437 mkexpr(cLo)) ); 16438 assign(zHi, binop(Iop_Add32x4, 16439 binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)), 16440 mkexpr(cHi))); 16441 putVReg( vD_addr, 16442 binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) ); 16443 break; 16444 } 16445 16446 16447 /* Multiply-Sum */ 16448 case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204) 16449 IRTemp abEE, abEO, abOE, abOO; 16450 abEE = abEO = abOE = abOO = IRTemp_INVALID; 16451 DIP("vmsumubm v%d,v%d,v%d,v%d\n", 16452 vD_addr, vA_addr, vB_addr, vC_addr); 16453 16454 /* multiply vA,vB (unsigned, widening) */ 16455 assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) )); 16456 assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) ); 16457 16458 /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */ 16459 expand16Ux8( mkexpr(abEvn), &abEE, &abEO ); 16460 expand16Ux8( mkexpr(abOdd), &abOE, &abOO ); 16461 16462 putVReg( vD_addr, 16463 binop(Iop_Add32x4, mkexpr(vC), 16464 binop(Iop_Add32x4, 16465 binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)), 16466 binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) ); 16467 break; 16468 } 16469 case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201) 16470 IRTemp aEvn, aOdd, bEvn, bOdd; 16471 IRTemp abEE = newTemp(Ity_V128); 16472 IRTemp abEO = newTemp(Ity_V128); 16473 IRTemp abOE = newTemp(Ity_V128); 16474 IRTemp abOO = newTemp(Ity_V128); 16475 aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID; 16476 DIP("vmsummbm v%d,v%d,v%d,v%d\n", 16477 vD_addr, vA_addr, vB_addr, vC_addr); 16478 16479 /* sign-extend vA, zero-extend vB, for mixed-sign multiply 16480 (separating out adjacent lanes to different vectors) */ 16481 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); 16482 expand8Ux16( mkexpr(vB), &bEvn, &bOdd ); 16483 16484 /* multiply vA, vB, again separating adjacent lanes */ 16485 assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) )); 16486 assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) ); 16487 assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) )); 16488 assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) ); 16489 16490 /* add results together, + vC */ 16491 putVReg( vD_addr, 16492 binop(Iop_QAdd32Sx4, mkexpr(vC), 16493 binop(Iop_QAdd32Sx4, 16494 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)), 16495 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) ); 16496 break; 16497 } 16498 case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205) 16499 DIP("vmsumuhm v%d,v%d,v%d,v%d\n", 16500 vD_addr, vA_addr, vB_addr, vC_addr); 16501 assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) )); 16502 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 16503 putVReg( vD_addr, 16504 binop(Iop_Add32x4, mkexpr(vC), 16505 binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) ); 16506 break; 16507 } 16508 case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206) 16509 DIP("vmsumuhs v%d,v%d,v%d,v%d\n", 16510 vD_addr, vA_addr, vB_addr, vC_addr); 16511 /* widening multiply, separating lanes */ 16512 assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) )); 16513 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) ); 16514 16515 /* break V128 to 4xI32's, zero-extending to I64's */ 16516 breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 16517 breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 16518 breakV128to4x64U( mkexpr(vC), &c3, &c2, &c1, &c0 ); 16519 16520 /* add lanes */ 16521 assign( z3, binop(Iop_Add64, mkexpr(c3), 16522 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 16523 assign( z2, binop(Iop_Add64, mkexpr(c2), 16524 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 16525 assign( z1, binop(Iop_Add64, mkexpr(c1), 16526 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 16527 assign( z0, binop(Iop_Add64, mkexpr(c0), 16528 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 16529 16530 /* saturate-narrow to 32bit, and combine to V128 */ 16531 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2), 16532 mkexpr(z1), mkexpr(z0)) ); 16533 16534 break; 16535 } 16536 case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202) 16537 DIP("vmsumshm v%d,v%d,v%d,v%d\n", 16538 vD_addr, vA_addr, vB_addr, vC_addr); 16539 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 16540 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 16541 putVReg( vD_addr, 16542 binop(Iop_Add32x4, mkexpr(vC), 16543 binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) ); 16544 break; 16545 } 16546 case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203) 16547 DIP("vmsumshs v%d,v%d,v%d,v%d\n", 16548 vD_addr, vA_addr, vB_addr, vC_addr); 16549 /* widening multiply, separating lanes */ 16550 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) )); 16551 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) ); 16552 16553 /* break V128 to 4xI32's, sign-extending to I64's */ 16554 breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 ); 16555 breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 ); 16556 breakV128to4x64S( mkexpr(vC), &c3, &c2, &c1, &c0 ); 16557 16558 /* add lanes */ 16559 assign( z3, binop(Iop_Add64, mkexpr(c3), 16560 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6)))); 16561 assign( z2, binop(Iop_Add64, mkexpr(c2), 16562 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4)))); 16563 assign( z1, binop(Iop_Add64, mkexpr(c1), 16564 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2)))); 16565 assign( z0, binop(Iop_Add64, mkexpr(c0), 16566 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0)))); 16567 16568 /* saturate-narrow to 32bit, and combine to V128 */ 16569 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2), 16570 mkexpr(z1), mkexpr(z0)) ); 16571 break; 16572 } 16573 default: 16574 vex_printf("dis_av_multarith(ppc)(opc2)\n"); 16575 return False; 16576 } 16577 return True; 16578 } 16579 16580 /* 16581 AltiVec Polynomial Multiply-Sum Instructions 16582 */ 16583 static Bool dis_av_polymultarith ( UInt theInstr ) 16584 { 16585 /* VA-Form */ 16586 UChar opc1 = ifieldOPC(theInstr); 16587 UChar vD_addr = ifieldRegDS(theInstr); 16588 UChar vA_addr = ifieldRegA(theInstr); 16589 UChar vB_addr = ifieldRegB(theInstr); 16590 UChar vC_addr = ifieldRegC(theInstr); 16591 UInt opc2 = IFIELD(theInstr, 0, 11); 16592 IRTemp vA = newTemp(Ity_V128); 16593 IRTemp vB = newTemp(Ity_V128); 16594 IRTemp vC = newTemp(Ity_V128); 16595 16596 assign( vA, getVReg(vA_addr)); 16597 assign( vB, getVReg(vB_addr)); 16598 assign( vC, getVReg(vC_addr)); 16599 16600 if (opc1 != 0x4) { 16601 vex_printf("dis_av_polymultarith(ppc)(instr)\n"); 16602 return False; 16603 } 16604 16605 switch (opc2) { 16606 /* Polynomial Multiply-Add */ 16607 case 0x408: // vpmsumb Vector Polynomial Multipy-sum Byte 16608 DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16609 putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16, 16610 mkexpr(vA), mkexpr(vB)) ); 16611 break; 16612 case 0x448: // vpmsumd Vector Polynomial Multipy-sum Double Word 16613 DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16614 putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2, 16615 mkexpr(vA), mkexpr(vB)) ); 16616 break; 16617 case 0x488: // vpmsumw Vector Polynomial Multipy-sum Word 16618 DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16619 putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4, 16620 mkexpr(vA), mkexpr(vB)) ); 16621 break; 16622 case 0x4C8: // vpmsumh Vector Polynomial Multipy-sum Half Word 16623 DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16624 putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8, 16625 mkexpr(vA), mkexpr(vB)) ); 16626 break; 16627 default: 16628 vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2); 16629 return False; 16630 } 16631 return True; 16632 } 16633 16634 /* 16635 AltiVec Shift/Rotate Instructions 16636 */ 16637 static Bool dis_av_shift ( UInt theInstr ) 16638 { 16639 /* VX-Form */ 16640 UChar opc1 = ifieldOPC(theInstr); 16641 UChar vD_addr = ifieldRegDS(theInstr); 16642 UChar vA_addr = ifieldRegA(theInstr); 16643 UChar vB_addr = ifieldRegB(theInstr); 16644 UInt opc2 = IFIELD( theInstr, 0, 11 ); 16645 16646 IRTemp vA = newTemp(Ity_V128); 16647 IRTemp vB = newTemp(Ity_V128); 16648 assign( vA, getVReg(vA_addr)); 16649 assign( vB, getVReg(vB_addr)); 16650 16651 if (opc1 != 0x4){ 16652 vex_printf("dis_av_shift(ppc)(instr)\n"); 16653 return False; 16654 } 16655 16656 switch (opc2) { 16657 /* Rotate */ 16658 case 0x004: // vrlb (Rotate Left Integer B, AV p234) 16659 DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16660 putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) ); 16661 break; 16662 16663 case 0x044: // vrlh (Rotate Left Integer HW, AV p235) 16664 DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16665 putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) ); 16666 break; 16667 16668 case 0x084: // vrlw (Rotate Left Integer W, AV p236) 16669 DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16670 putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) ); 16671 break; 16672 16673 case 0x0C4: // vrld (Rotate Left Integer Double Word) 16674 DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16675 putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) ); 16676 break; 16677 16678 16679 /* Shift Left */ 16680 case 0x104: // vslb (Shift Left Integer B, AV p240) 16681 DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16682 putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) ); 16683 break; 16684 16685 case 0x144: // vslh (Shift Left Integer HW, AV p242) 16686 DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16687 putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) ); 16688 break; 16689 16690 case 0x184: // vslw (Shift Left Integer W, AV p244) 16691 DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16692 putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) ); 16693 break; 16694 16695 case 0x5C4: // vsld (Shift Left Integer Double Word) 16696 DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16697 putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) ); 16698 break; 16699 16700 case 0x1C4: { // vsl (Shift Left, AV p239) 16701 IRTemp sh = newTemp(Ity_I8); 16702 DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16703 assign( sh, binop(Iop_And8, mkU8(0x7), 16704 unop(Iop_32to8, 16705 unop(Iop_V128to32, mkexpr(vB)))) ); 16706 putVReg( vD_addr, 16707 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 16708 break; 16709 } 16710 case 0x40C: { // vslo (Shift Left by Octet, AV p243) 16711 IRTemp sh = newTemp(Ity_I8); 16712 DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16713 assign( sh, binop(Iop_And8, mkU8(0x78), 16714 unop(Iop_32to8, 16715 unop(Iop_V128to32, mkexpr(vB)))) ); 16716 putVReg( vD_addr, 16717 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) ); 16718 break; 16719 } 16720 16721 16722 /* Shift Right */ 16723 case 0x204: // vsrb (Shift Right B, AV p256) 16724 DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16725 putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) ); 16726 break; 16727 16728 case 0x244: // vsrh (Shift Right HW, AV p257) 16729 DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16730 putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) ); 16731 break; 16732 16733 case 0x284: // vsrw (Shift Right W, AV p259) 16734 DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16735 putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) ); 16736 break; 16737 16738 case 0x2C4: { // vsr (Shift Right, AV p251) 16739 IRTemp sh = newTemp(Ity_I8); 16740 DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16741 assign( sh, binop(Iop_And8, mkU8(0x7), 16742 unop(Iop_32to8, 16743 unop(Iop_V128to32, mkexpr(vB)))) ); 16744 putVReg( vD_addr, 16745 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 16746 break; 16747 } 16748 case 0x304: // vsrab (Shift Right Alg B, AV p253) 16749 DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16750 putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) ); 16751 break; 16752 16753 case 0x344: // vsrah (Shift Right Alg HW, AV p254) 16754 DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16755 putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) ); 16756 break; 16757 16758 case 0x384: // vsraw (Shift Right Alg W, AV p255) 16759 DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16760 putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) ); 16761 break; 16762 16763 case 0x3C4: // vsrad (Shift Right Alg Double Word) 16764 DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16765 putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) ); 16766 break; 16767 16768 case 0x44C: { // vsro (Shift Right by Octet, AV p258) 16769 IRTemp sh = newTemp(Ity_I8); 16770 DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16771 assign( sh, binop(Iop_And8, mkU8(0x78), 16772 unop(Iop_32to8, 16773 unop(Iop_V128to32, mkexpr(vB)))) ); 16774 putVReg( vD_addr, 16775 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) ); 16776 break; 16777 } 16778 16779 case 0x6C4: // vsrd (Shift Right Double Word) 16780 DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16781 putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) ); 16782 break; 16783 16784 16785 default: 16786 vex_printf("dis_av_shift(ppc)(opc2)\n"); 16787 return False; 16788 } 16789 return True; 16790 } 16791 16792 /* 16793 AltiVec Permute Instructions 16794 */ 16795 static Bool dis_av_permute ( UInt theInstr ) 16796 { 16797 /* VA-Form, VX-Form */ 16798 UChar opc1 = ifieldOPC(theInstr); 16799 UChar vD_addr = ifieldRegDS(theInstr); 16800 UChar vA_addr = ifieldRegA(theInstr); 16801 UChar UIMM_5 = vA_addr; 16802 UChar vB_addr = ifieldRegB(theInstr); 16803 UChar vC_addr = ifieldRegC(theInstr); 16804 UChar b10 = ifieldBIT10(theInstr); 16805 UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) ); 16806 UInt opc2 = toUChar( IFIELD( theInstr, 0, 6 ) ); 16807 16808 UChar SIMM_8 = extend_s_5to8(UIMM_5); 16809 16810 IRTemp vA = newTemp(Ity_V128); 16811 IRTemp vB = newTemp(Ity_V128); 16812 IRTemp vC = newTemp(Ity_V128); 16813 assign( vA, getVReg(vA_addr)); 16814 assign( vB, getVReg(vB_addr)); 16815 assign( vC, getVReg(vC_addr)); 16816 16817 if (opc1 != 0x4) { 16818 vex_printf("dis_av_permute(ppc)(instr)\n"); 16819 return False; 16820 } 16821 16822 switch (opc2) { 16823 case 0x2A: // vsel (Conditional Select, AV p238) 16824 DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr); 16825 /* vD = (vA & ~vC) | (vB & vC) */ 16826 putVReg( vD_addr, binop(Iop_OrV128, 16827 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))), 16828 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) ); 16829 return True; 16830 16831 case 0x2B: { // vperm (Permute, AV p218) 16832 /* limited to two args for IR, so have to play games... */ 16833 IRTemp a_perm = newTemp(Ity_V128); 16834 IRTemp b_perm = newTemp(Ity_V128); 16835 IRTemp mask = newTemp(Ity_V128); 16836 IRTemp vC_andF = newTemp(Ity_V128); 16837 DIP("vperm v%d,v%d,v%d,v%d\n", 16838 vD_addr, vA_addr, vB_addr, vC_addr); 16839 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what 16840 IR specifies, and also to hide irrelevant bits from 16841 memcheck */ 16842 assign( vC_andF, 16843 binop(Iop_AndV128, mkexpr(vC), 16844 unop(Iop_Dup8x16, mkU8(0xF))) ); 16845 assign( a_perm, 16846 binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) ); 16847 assign( b_perm, 16848 binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) ); 16849 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0 16850 assign( mask, binop(Iop_SarN8x16, 16851 binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)), 16852 mkU8(7)) ); 16853 // dst = (a & ~mask) | (b & mask) 16854 putVReg( vD_addr, binop(Iop_OrV128, 16855 binop(Iop_AndV128, mkexpr(a_perm), 16856 unop(Iop_NotV128, mkexpr(mask))), 16857 binop(Iop_AndV128, mkexpr(b_perm), 16858 mkexpr(mask))) ); 16859 return True; 16860 } 16861 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241) 16862 if (b10 != 0) { 16863 vex_printf("dis_av_permute(ppc)(vsldoi)\n"); 16864 return False; 16865 } 16866 DIP("vsldoi v%d,v%d,v%d,%d\n", 16867 vD_addr, vA_addr, vB_addr, SHB_uimm4); 16868 if (SHB_uimm4 == 0) 16869 putVReg( vD_addr, mkexpr(vA) ); 16870 else 16871 putVReg( vD_addr, 16872 binop(Iop_OrV128, 16873 binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)), 16874 binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) ); 16875 return True; 16876 case 0x2D: { // vpermxor (Vector Permute and Exclusive-OR) 16877 IRTemp a_perm = newTemp(Ity_V128); 16878 IRTemp b_perm = newTemp(Ity_V128); 16879 IRTemp vrc_a = newTemp(Ity_V128); 16880 IRTemp vrc_b = newTemp(Ity_V128); 16881 16882 /* IBM index is 0:7, Change index value to index 7:0 */ 16883 assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ), 16884 unop( Iop_Dup8x16, mkU8( 0xF ) ) ) ); 16885 assign( vrc_a, binop( Iop_ShrV128, 16886 binop( Iop_AndV128, mkexpr( vC ), 16887 unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ), 16888 mkU8 ( 4 ) ) ); 16889 assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) ); 16890 assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) ); 16891 putVReg( vD_addr, binop( Iop_XorV128, 16892 mkexpr( a_perm ), mkexpr( b_perm) ) ); 16893 return True; 16894 } 16895 default: 16896 break; // Fall through... 16897 } 16898 16899 opc2 = IFIELD( theInstr, 0, 11 ); 16900 switch (opc2) { 16901 16902 /* Merge */ 16903 case 0x00C: // vmrghb (Merge High B, AV p195) 16904 DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16905 putVReg( vD_addr, 16906 binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) ); 16907 break; 16908 16909 case 0x04C: // vmrghh (Merge High HW, AV p196) 16910 DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16911 putVReg( vD_addr, 16912 binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) ); 16913 break; 16914 16915 case 0x08C: // vmrghw (Merge High W, AV p197) 16916 DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16917 putVReg( vD_addr, 16918 binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) ); 16919 break; 16920 16921 case 0x10C: // vmrglb (Merge Low B, AV p198) 16922 DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16923 putVReg( vD_addr, 16924 binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) ); 16925 break; 16926 16927 case 0x14C: // vmrglh (Merge Low HW, AV p199) 16928 DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16929 putVReg( vD_addr, 16930 binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) ); 16931 break; 16932 16933 case 0x18C: // vmrglw (Merge Low W, AV p200) 16934 DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16935 putVReg( vD_addr, 16936 binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) ); 16937 break; 16938 16939 16940 /* Splat */ 16941 case 0x20C: { // vspltb (Splat Byte, AV p245) 16942 /* vD = Dup8x16( vB[UIMM_5] ) */ 16943 UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8; 16944 DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 16945 putVReg( vD_addr, unop(Iop_Dup8x16, 16946 unop(Iop_32to8, unop(Iop_V128to32, 16947 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 16948 break; 16949 } 16950 case 0x24C: { // vsplth (Splat Half Word, AV p246) 16951 UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16; 16952 DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 16953 putVReg( vD_addr, unop(Iop_Dup16x8, 16954 unop(Iop_32to16, unop(Iop_V128to32, 16955 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) ); 16956 break; 16957 } 16958 case 0x28C: { // vspltw (Splat Word, AV p250) 16959 /* vD = Dup32x4( vB[UIMM_5] ) */ 16960 UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32; 16961 DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 16962 putVReg( vD_addr, unop(Iop_Dup32x4, 16963 unop(Iop_V128to32, 16964 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) ); 16965 break; 16966 } 16967 case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247) 16968 DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8); 16969 putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) ); 16970 break; 16971 16972 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248) 16973 DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8); 16974 putVReg( vD_addr, 16975 unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) ); 16976 break; 16977 16978 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249) 16979 DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8); 16980 putVReg( vD_addr, 16981 unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) ); 16982 break; 16983 16984 case 0x68C: // vmrgow (Merge Odd Word) 16985 DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16986 /* VD[0] <- VA[1] 16987 VD[1] <- VB[1] 16988 VD[2] <- VA[3] 16989 VD[3] <- VB[3] 16990 */ 16991 putVReg( vD_addr, 16992 binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) ); 16993 break; 16994 16995 case 0x78C: // vmrgew (Merge Even Word) 16996 DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 16997 /* VD[0] <- VA[0] 16998 VD[1] <- VB[0] 16999 VD[2] <- VA[2] 17000 VD[3] <- VB[2] 17001 */ 17002 putVReg( vD_addr, 17003 binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) ); 17004 break; 17005 17006 default: 17007 vex_printf("dis_av_permute(ppc)(opc2)\n"); 17008 return False; 17009 } 17010 return True; 17011 } 17012 17013 /* 17014 AltiVec Pack/Unpack Instructions 17015 */ 17016 static Bool dis_av_pack ( UInt theInstr ) 17017 { 17018 /* VX-Form */ 17019 UChar opc1 = ifieldOPC(theInstr); 17020 UChar vD_addr = ifieldRegDS(theInstr); 17021 UChar vA_addr = ifieldRegA(theInstr); 17022 UChar vB_addr = ifieldRegB(theInstr); 17023 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17024 17025 IRTemp signs = IRTemp_INVALID; 17026 IRTemp zeros = IRTemp_INVALID; 17027 IRTemp vA = newTemp(Ity_V128); 17028 IRTemp vB = newTemp(Ity_V128); 17029 assign( vA, getVReg(vA_addr)); 17030 assign( vB, getVReg(vB_addr)); 17031 17032 if (opc1 != 0x4) { 17033 vex_printf("dis_av_pack(ppc)(instr)\n"); 17034 return False; 17035 } 17036 switch (opc2) { 17037 /* Packing */ 17038 case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224) 17039 DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17040 putVReg( vD_addr, 17041 binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) ); 17042 return True; 17043 17044 case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226) 17045 DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17046 putVReg( vD_addr, 17047 binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) ); 17048 return True; 17049 17050 case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225) 17051 DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17052 putVReg( vD_addr, 17053 binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) ); 17054 // TODO: set VSCR[SAT] 17055 return True; 17056 17057 case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227) 17058 DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17059 putVReg( vD_addr, 17060 binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) ); 17061 // TODO: set VSCR[SAT] 17062 return True; 17063 17064 case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221) 17065 // This insn does a signed->unsigned saturating conversion. 17066 // Conversion done here, then uses unsigned->unsigned vpk insn: 17067 // => UnsignedSaturatingNarrow( x & ~ (x >>s 15) ) 17068 IRTemp vA_tmp = newTemp(Ity_V128); 17069 IRTemp vB_tmp = newTemp(Ity_V128); 17070 DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17071 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 17072 unop(Iop_NotV128, 17073 binop(Iop_SarN16x8, 17074 mkexpr(vA), mkU8(15)))) ); 17075 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 17076 unop(Iop_NotV128, 17077 binop(Iop_SarN16x8, 17078 mkexpr(vB), mkU8(15)))) ); 17079 putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16, 17080 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 17081 // TODO: set VSCR[SAT] 17082 return True; 17083 } 17084 case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223) 17085 // This insn does a signed->unsigned saturating conversion. 17086 // Conversion done here, then uses unsigned->unsigned vpk insn: 17087 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) ) 17088 IRTemp vA_tmp = newTemp(Ity_V128); 17089 IRTemp vB_tmp = newTemp(Ity_V128); 17090 DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17091 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 17092 unop(Iop_NotV128, 17093 binop(Iop_SarN32x4, 17094 mkexpr(vA), mkU8(31)))) ); 17095 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 17096 unop(Iop_NotV128, 17097 binop(Iop_SarN32x4, 17098 mkexpr(vB), mkU8(31)))) ); 17099 putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8, 17100 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 17101 // TODO: set VSCR[SAT] 17102 return True; 17103 } 17104 case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220) 17105 DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17106 putVReg( vD_addr, 17107 binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) ); 17108 // TODO: set VSCR[SAT] 17109 return True; 17110 17111 case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222) 17112 DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17113 putVReg( vD_addr, 17114 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) ); 17115 // TODO: set VSCR[SAT] 17116 return True; 17117 17118 case 0x30E: { // vpkpx (Pack Pixel, AV p219) 17119 /* CAB: Worth a new primop? */ 17120 /* Using shifts to compact pixel elements, then packing them */ 17121 IRTemp a1 = newTemp(Ity_V128); 17122 IRTemp a2 = newTemp(Ity_V128); 17123 IRTemp a3 = newTemp(Ity_V128); 17124 IRTemp a_tmp = newTemp(Ity_V128); 17125 IRTemp b1 = newTemp(Ity_V128); 17126 IRTemp b2 = newTemp(Ity_V128); 17127 IRTemp b3 = newTemp(Ity_V128); 17128 IRTemp b_tmp = newTemp(Ity_V128); 17129 DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17130 assign( a1, binop(Iop_ShlN16x8, 17131 binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)), 17132 mkU8(10)) ); 17133 assign( a2, binop(Iop_ShlN16x8, 17134 binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)), 17135 mkU8(5)) ); 17136 assign( a3, binop(Iop_ShrN16x8, 17137 binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)), 17138 mkU8(11)) ); 17139 assign( a_tmp, binop(Iop_OrV128, mkexpr(a1), 17140 binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) ); 17141 17142 assign( b1, binop(Iop_ShlN16x8, 17143 binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)), 17144 mkU8(10)) ); 17145 assign( b2, binop(Iop_ShlN16x8, 17146 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)), 17147 mkU8(5)) ); 17148 assign( b3, binop(Iop_ShrN16x8, 17149 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)), 17150 mkU8(11)) ); 17151 assign( b_tmp, binop(Iop_OrV128, mkexpr(b1), 17152 binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) ); 17153 17154 putVReg( vD_addr, binop(Iop_NarrowBin32to16x8, 17155 mkexpr(a_tmp), mkexpr(b_tmp)) ); 17156 return True; 17157 } 17158 17159 case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo) 17160 DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17161 putVReg( vD_addr, 17162 binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) ); 17163 return True; 17164 17165 case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate) 17166 DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17167 putVReg( vD_addr, 17168 binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) ); 17169 // TODO: set VSCR[SAT] 17170 return True; 17171 17172 case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate) 17173 // This insn does a doubled signed->double unsigned saturating conversion 17174 // Conversion done here, then uses unsigned->unsigned vpk insn: 17175 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) ) 17176 // This is similar to the technique used for vpkswus, except done 17177 // with double word integers versus word integers. 17178 IRTemp vA_tmp = newTemp(Ity_V128); 17179 IRTemp vB_tmp = newTemp(Ity_V128); 17180 DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17181 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA), 17182 unop(Iop_NotV128, 17183 binop(Iop_SarN64x2, 17184 mkexpr(vA), mkU8(63)))) ); 17185 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB), 17186 unop(Iop_NotV128, 17187 binop(Iop_SarN64x2, 17188 mkexpr(vB), mkU8(63)))) ); 17189 putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4, 17190 mkexpr(vA_tmp), mkexpr(vB_tmp)) ); 17191 // TODO: set VSCR[SAT] 17192 return True; 17193 } 17194 17195 case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate) 17196 DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17197 putVReg( vD_addr, 17198 binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) ); 17199 // TODO: set VSCR[SAT] 17200 return True; 17201 default: 17202 break; // Fall through... 17203 } 17204 17205 17206 if (vA_addr != 0) { 17207 vex_printf("dis_av_pack(ppc)(vA_addr)\n"); 17208 return False; 17209 } 17210 17211 signs = newTemp(Ity_V128); 17212 zeros = newTemp(Ity_V128); 17213 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 17214 17215 switch (opc2) { 17216 /* Unpacking */ 17217 case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277) 17218 DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr); 17219 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 17220 putVReg( vD_addr, 17221 binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) ); 17222 break; 17223 } 17224 case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278) 17225 DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr); 17226 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 17227 putVReg( vD_addr, 17228 binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) ); 17229 break; 17230 } 17231 case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280) 17232 DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr); 17233 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) ); 17234 putVReg( vD_addr, 17235 binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) ); 17236 break; 17237 } 17238 case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281) 17239 DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr); 17240 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) ); 17241 putVReg( vD_addr, 17242 binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) ); 17243 break; 17244 } 17245 case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276) 17246 /* CAB: Worth a new primop? */ 17247 /* Using shifts to isolate pixel elements, then expanding them */ 17248 IRTemp z0 = newTemp(Ity_V128); 17249 IRTemp z1 = newTemp(Ity_V128); 17250 IRTemp z01 = newTemp(Ity_V128); 17251 IRTemp z2 = newTemp(Ity_V128); 17252 IRTemp z3 = newTemp(Ity_V128); 17253 IRTemp z23 = newTemp(Ity_V128); 17254 DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr); 17255 assign( z0, binop(Iop_ShlN16x8, 17256 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 17257 mkU8(8)) ); 17258 assign( z1, binop(Iop_ShrN16x8, 17259 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 17260 mkU8(11)) ); 17261 assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 17262 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 17263 assign( z2, binop(Iop_ShrN16x8, 17264 binop(Iop_ShlN16x8, 17265 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 17266 mkU8(11)), 17267 mkU8(3)) ); 17268 assign( z3, binop(Iop_ShrN16x8, 17269 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 17270 mkU8(11)) ); 17271 assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros), 17272 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 17273 putVReg( vD_addr, 17274 binop(Iop_OrV128, 17275 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 17276 mkexpr(z23)) ); 17277 break; 17278 } 17279 case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279) 17280 /* identical to vupkhpx, except interleaving LO */ 17281 IRTemp z0 = newTemp(Ity_V128); 17282 IRTemp z1 = newTemp(Ity_V128); 17283 IRTemp z01 = newTemp(Ity_V128); 17284 IRTemp z2 = newTemp(Ity_V128); 17285 IRTemp z3 = newTemp(Ity_V128); 17286 IRTemp z23 = newTemp(Ity_V128); 17287 DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr); 17288 assign( z0, binop(Iop_ShlN16x8, 17289 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)), 17290 mkU8(8)) ); 17291 assign( z1, binop(Iop_ShrN16x8, 17292 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)), 17293 mkU8(11)) ); 17294 assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 17295 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) ); 17296 assign( z2, binop(Iop_ShrN16x8, 17297 binop(Iop_ShlN16x8, 17298 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)), 17299 mkU8(11)), 17300 mkU8(3)) ); 17301 assign( z3, binop(Iop_ShrN16x8, 17302 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)), 17303 mkU8(11)) ); 17304 assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros), 17305 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) ); 17306 putVReg( vD_addr, 17307 binop(Iop_OrV128, 17308 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)), 17309 mkexpr(z23)) ); 17310 break; 17311 } 17312 case 0x64E: { // vupkhsw (Unpack High Signed Word) 17313 DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr); 17314 assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) ); 17315 putVReg( vD_addr, 17316 binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) ); 17317 break; 17318 } 17319 case 0x6CE: { // vupklsw (Unpack Low Signed Word) 17320 DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr); 17321 assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) ); 17322 putVReg( vD_addr, 17323 binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) ); 17324 break; 17325 } 17326 default: 17327 vex_printf("dis_av_pack(ppc)(opc2)\n"); 17328 return False; 17329 } 17330 return True; 17331 } 17332 17333 /* 17334 AltiVec Cipher Instructions 17335 */ 17336 static Bool dis_av_cipher ( UInt theInstr ) 17337 { 17338 /* VX-Form */ 17339 UChar opc1 = ifieldOPC(theInstr); 17340 UChar vD_addr = ifieldRegDS(theInstr); 17341 UChar vA_addr = ifieldRegA(theInstr); 17342 UChar vB_addr = ifieldRegB(theInstr); 17343 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17344 17345 IRTemp vA = newTemp(Ity_V128); 17346 IRTemp vB = newTemp(Ity_V128); 17347 assign( vA, getVReg(vA_addr)); 17348 assign( vB, getVReg(vB_addr)); 17349 17350 if (opc1 != 0x4) { 17351 vex_printf("dis_av_cipher(ppc)(instr)\n"); 17352 return False; 17353 } 17354 switch (opc2) { 17355 case 0x508: // vcipher (Vector Inverser Cipher) 17356 DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17357 putVReg( vD_addr, 17358 binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) ); 17359 return True; 17360 17361 case 0x509: // vcipherlast (Vector Inverser Cipher Last) 17362 DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17363 putVReg( vD_addr, 17364 binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) ); 17365 return True; 17366 17367 case 0x548: // vncipher (Vector Inverser Cipher) 17368 DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17369 putVReg( vD_addr, 17370 binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) ); 17371 return True; 17372 17373 case 0x549: // vncipherlast (Vector Inverser Cipher Last) 17374 DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17375 putVReg( vD_addr, 17376 binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) ); 17377 return True; 17378 17379 case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher 17380 * subBytes transform) 17381 */ 17382 DIP("vsbox v%d,v%d\n", vD_addr, vA_addr); 17383 putVReg( vD_addr, 17384 unop(Iop_CipherSV128, mkexpr(vA) ) ); 17385 return True; 17386 17387 default: 17388 vex_printf("dis_av_cipher(ppc)(opc2)\n"); 17389 return False; 17390 } 17391 return True; 17392 } 17393 17394 /* 17395 AltiVec Secure Hash Instructions 17396 */ 17397 static Bool dis_av_hash ( UInt theInstr ) 17398 { 17399 /* VX-Form */ 17400 UChar opc1 = ifieldOPC(theInstr); 17401 UChar vRT_addr = ifieldRegDS(theInstr); 17402 UChar vRA_addr = ifieldRegA(theInstr); 17403 UChar s_field = IFIELD( theInstr, 11, 5 ); // st and six field 17404 UChar st = IFIELD( theInstr, 15, 1 ); // st 17405 UChar six = IFIELD( theInstr, 11, 4 ); // six field 17406 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17407 17408 IRTemp vA = newTemp(Ity_V128); 17409 IRTemp dst = newTemp(Ity_V128); 17410 assign( vA, getVReg(vRA_addr)); 17411 17412 if (opc1 != 0x4) { 17413 vex_printf("dis_av_hash(ppc)(instr)\n"); 17414 return False; 17415 } 17416 17417 switch (opc2) { 17418 case 0x682: // vshasigmaw 17419 DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six); 17420 assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) ); 17421 putVReg( vRT_addr, mkexpr(dst)); 17422 return True; 17423 17424 case 0x6C2: // vshasigmad, 17425 DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six); 17426 putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) ); 17427 return True; 17428 17429 default: 17430 vex_printf("dis_av_hash(ppc)(opc2)\n"); 17431 return False; 17432 } 17433 return True; 17434 } 17435 17436 /* 17437 * This function is used by the Vector add/subtract [extended] modulo/carry 17438 * instructions. 17439 * - For the non-extended add instructions, the cin arg is set to zero. 17440 * - For the extended add instructions, cin is the integer value of 17441 * src3.bit[127]. 17442 * - For the non-extended subtract instructions, src1 is added to the one's 17443 * complement of src2 + 1. We re-use the cin argument to hold the '1' 17444 * value for this operation. 17445 * - For the extended subtract instructions, cin is the integer value of src3.bit[127]. 17446 */ 17447 static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB, 17448 IRExpr * cin, Bool modulo) 17449 { 17450 IRTemp _vecA_32 = IRTemp_INVALID; 17451 IRTemp _vecB_32 = IRTemp_INVALID; 17452 IRTemp res_32 = IRTemp_INVALID; 17453 IRTemp result = IRTemp_INVALID; 17454 IRTemp tmp_result = IRTemp_INVALID; 17455 IRTemp carry = IRTemp_INVALID; 17456 Int i; 17457 IRExpr * _vecA_low64 = unop( Iop_V128to64, vecA ); 17458 IRExpr * _vecB_low64 = unop( Iop_V128to64, vecB ); 17459 IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA ); 17460 IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB ); 17461 17462 for (i = 0; i < 4; i++) { 17463 _vecA_32 = newTemp(Ity_I32); 17464 _vecB_32 = newTemp(Ity_I32); 17465 res_32 = newTemp(Ity_I32); 17466 switch (i) { 17467 case 0: 17468 assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) ); 17469 assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) ); 17470 break; 17471 case 1: 17472 assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) ); 17473 assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) ); 17474 break; 17475 case 2: 17476 assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) ); 17477 assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) ); 17478 break; 17479 case 3: 17480 assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) ); 17481 assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) ); 17482 break; 17483 } 17484 17485 assign(res_32, binop( Iop_Add32, 17486 binop( Iop_Add32, 17487 binop ( Iop_Add32, 17488 mkexpr(_vecA_32), 17489 mkexpr(_vecB_32) ), 17490 (i == 0) ? mkU32(0) : mkexpr(carry) ), 17491 (i == 0) ? cin : mkU32(0) ) ); 17492 if (modulo) { 17493 result = newTemp(Ity_V128); 17494 assign(result, binop( Iop_OrV128, 17495 (i == 0) ? binop( Iop_64HLtoV128, 17496 mkU64(0), 17497 mkU64(0) ) : mkexpr(tmp_result), 17498 binop( Iop_ShlV128, 17499 binop( Iop_64HLtoV128, 17500 mkU64(0), 17501 binop( Iop_32HLto64, 17502 mkU32(0), 17503 mkexpr(res_32) ) ), 17504 mkU8(i * 32) ) ) ); 17505 tmp_result = newTemp(Ity_V128); 17506 assign(tmp_result, mkexpr(result)); 17507 } 17508 carry = newTemp(Ity_I32); 17509 assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U, 17510 mkexpr(res_32), 17511 mkexpr(_vecA_32 ) ) ) ); 17512 } 17513 if (modulo) 17514 return result; 17515 else 17516 return carry; 17517 } 17518 17519 17520 static Bool dis_av_quad ( UInt theInstr ) 17521 { 17522 /* VX-Form */ 17523 UChar opc1 = ifieldOPC(theInstr); 17524 UChar vRT_addr = ifieldRegDS(theInstr); 17525 UChar vRA_addr = ifieldRegA(theInstr); 17526 UChar vRB_addr = ifieldRegB(theInstr); 17527 UChar vRC_addr; 17528 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17529 17530 IRTemp vA = newTemp(Ity_V128); 17531 IRTemp vB = newTemp(Ity_V128); 17532 IRTemp vC = IRTemp_INVALID; 17533 IRTemp cin = IRTemp_INVALID; 17534 assign( vA, getVReg(vRA_addr)); 17535 assign( vB, getVReg(vRB_addr)); 17536 17537 if (opc1 != 0x4) { 17538 vex_printf("dis_av_quad(ppc)(instr)\n"); 17539 return False; 17540 } 17541 17542 switch (opc2) { 17543 case 0x140: // vaddcuq 17544 DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 17545 putVReg( vRT_addr, unop( Iop_32UtoV128, 17546 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 17547 mkexpr(vB), 17548 mkU32(0), False) ) ) ); 17549 return True; 17550 case 0x100: // vadduqm 17551 DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 17552 putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 17553 mkexpr(vB), mkU32(0), True) ) ); 17554 return True; 17555 case 0x540: // vsubcuq 17556 DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 17557 putVReg( vRT_addr, 17558 unop( Iop_32UtoV128, 17559 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 17560 unop( Iop_NotV128, 17561 mkexpr(vB) ), 17562 mkU32(1), False) ) ) ); 17563 return True; 17564 case 0x500: // vsubuqm 17565 DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 17566 putVReg( vRT_addr, 17567 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 17568 unop( Iop_NotV128, mkexpr(vB) ), 17569 mkU32(1), True) ) ); 17570 return True; 17571 case 0x054C: // vbpermq 17572 { 17573 #define BPERMD_IDX_MASK 0x00000000000000FFULL 17574 #define BPERMD_BIT_MASK 0x8000000000000000ULL 17575 int i; 17576 IRExpr * vB_expr = mkexpr(vB); 17577 IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0)); 17578 DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr); 17579 for (i = 0; i < 16; i++) { 17580 IRTemp idx_tmp = newTemp( Ity_V128 ); 17581 IRTemp perm_bit = newTemp( Ity_V128 ); 17582 IRTemp idx = newTemp( Ity_I8 ); 17583 IRTemp idx_LT127 = newTemp( Ity_I1 ); 17584 IRTemp idx_LT127_ity128 = newTemp( Ity_V128 ); 17585 17586 assign( idx_tmp, 17587 binop( Iop_AndV128, 17588 binop( Iop_64HLtoV128, 17589 mkU64(0), 17590 mkU64(BPERMD_IDX_MASK) ), 17591 vB_expr ) ); 17592 assign( idx_LT127, 17593 binop( Iop_CmpEQ32, 17594 unop ( Iop_64to32, 17595 unop( Iop_V128to64, binop( Iop_ShrV128, 17596 mkexpr(idx_tmp), 17597 mkU8(7) ) ) ), 17598 mkU32(0) ) ); 17599 17600 /* Below, we set idx to determine which bit of vA to use for the 17601 * perm bit. If idx_LT127 is 0, the perm bit is forced to '0'. 17602 */ 17603 assign( idx, 17604 binop( Iop_And8, 17605 unop( Iop_1Sto8, 17606 mkexpr(idx_LT127) ), 17607 unop( Iop_32to8, 17608 unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) ); 17609 17610 assign( idx_LT127_ity128, 17611 binop( Iop_64HLtoV128, 17612 mkU64(0), 17613 unop( Iop_32Uto64, 17614 unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) ); 17615 assign( perm_bit, 17616 binop( Iop_AndV128, 17617 mkexpr( idx_LT127_ity128 ), 17618 binop( Iop_ShrV128, 17619 binop( Iop_AndV128, 17620 binop (Iop_64HLtoV128, 17621 mkU64( BPERMD_BIT_MASK ), 17622 mkU64(0)), 17623 binop( Iop_ShlV128, 17624 mkexpr( vA ), 17625 mkexpr( idx ) ) ), 17626 mkU8( 127 ) ) ) ); 17627 res = binop( Iop_OrV128, 17628 res, 17629 binop( Iop_ShlV128, 17630 mkexpr( perm_bit ), 17631 mkU8( i ) ) ); 17632 vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) ); 17633 } 17634 putVReg( vRT_addr, res); 17635 return True; 17636 #undef BPERMD_IDX_MASK 17637 #undef BPERMD_BIT_MASK 17638 } 17639 17640 default: 17641 break; // fall through 17642 } 17643 17644 opc2 = IFIELD( theInstr, 0, 6 ); 17645 vRC_addr = ifieldRegC(theInstr); 17646 vC = newTemp(Ity_V128); 17647 cin = newTemp(Ity_I32); 17648 switch (opc2) { 17649 case 0x3D: // vaddecuq 17650 assign( vC, getVReg(vRC_addr)); 17651 DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 17652 vRC_addr); 17653 assign(cin, binop( Iop_And32, 17654 unop( Iop_64to32, 17655 unop( Iop_V128to64, mkexpr(vC) ) ), 17656 mkU32(1) ) ); 17657 putVReg( vRT_addr, 17658 unop( Iop_32UtoV128, 17659 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB), 17660 mkexpr(cin), 17661 False) ) ) ); 17662 return True; 17663 case 0x3C: // vaddeuqm 17664 assign( vC, getVReg(vRC_addr)); 17665 DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 17666 vRC_addr); 17667 assign(cin, binop( Iop_And32, 17668 unop( Iop_64to32, 17669 unop( Iop_V128to64, mkexpr(vC) ) ), 17670 mkU32(1) ) ); 17671 putVReg( vRT_addr, 17672 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB), 17673 mkexpr(cin), 17674 True) ) ); 17675 return True; 17676 case 0x3F: // vsubecuq 17677 assign( vC, getVReg(vRC_addr)); 17678 DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 17679 vRC_addr); 17680 assign(cin, binop( Iop_And32, 17681 unop( Iop_64to32, 17682 unop( Iop_V128to64, mkexpr(vC) ) ), 17683 mkU32(1) ) ); 17684 putVReg( vRT_addr, 17685 unop( Iop_32UtoV128, 17686 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 17687 unop( Iop_NotV128, 17688 mkexpr(vB) ), 17689 mkexpr(cin), 17690 False) ) ) ); 17691 return True; 17692 case 0x3E: // vsubeuqm 17693 assign( vC, getVReg(vRC_addr)); 17694 DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr, 17695 vRC_addr); 17696 assign(cin, binop( Iop_And32, 17697 unop( Iop_64to32, 17698 unop( Iop_V128to64, mkexpr(vC) ) ), 17699 mkU32(1) ) ); 17700 putVReg( vRT_addr, 17701 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), 17702 unop( Iop_NotV128, mkexpr(vB) ), 17703 mkexpr(cin), 17704 True) ) ); 17705 return True; 17706 default: 17707 vex_printf("dis_av_quad(ppc)(opc2.2)\n"); 17708 return False; 17709 } 17710 17711 return True; 17712 } 17713 17714 17715 /* 17716 AltiVec BCD Arithmetic instructions. 17717 These instructions modify CR6 for various conditions in the result, 17718 including when an overflow occurs. We could easily detect all conditions 17719 except when an overflow occurs. But since we can't be 100% accurate 17720 in our emulation of CR6, it seems best to just not support it all. 17721 */ 17722 static Bool dis_av_bcd ( UInt theInstr ) 17723 { 17724 /* VX-Form */ 17725 UChar opc1 = ifieldOPC(theInstr); 17726 UChar vRT_addr = ifieldRegDS(theInstr); 17727 UChar vRA_addr = ifieldRegA(theInstr); 17728 UChar vRB_addr = ifieldRegB(theInstr); 17729 UChar ps = IFIELD( theInstr, 9, 1 ); 17730 UInt opc2 = IFIELD( theInstr, 0, 9 ); 17731 17732 IRTemp vA = newTemp(Ity_V128); 17733 IRTemp vB = newTemp(Ity_V128); 17734 IRTemp dst = newTemp(Ity_V128); 17735 assign( vA, getVReg(vRA_addr)); 17736 assign( vB, getVReg(vRB_addr)); 17737 17738 if (opc1 != 0x4) { 17739 vex_printf("dis_av_bcd(ppc)(instr)\n"); 17740 return False; 17741 } 17742 17743 switch (opc2) { 17744 case 0x1: // bcdadd 17745 DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps); 17746 assign( dst, triop( Iop_BCDAdd, mkexpr( vA ), 17747 mkexpr( vB ), mkU8( ps ) ) ); 17748 putVReg( vRT_addr, mkexpr(dst)); 17749 return True; 17750 17751 case 0x41: // bcdsub 17752 DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps); 17753 assign( dst, triop( Iop_BCDSub, mkexpr( vA ), 17754 mkexpr( vB ), mkU8( ps ) ) ); 17755 putVReg( vRT_addr, mkexpr(dst)); 17756 return True; 17757 17758 default: 17759 vex_printf("dis_av_bcd(ppc)(opc2)\n"); 17760 return False; 17761 } 17762 return True; 17763 } 17764 17765 /* 17766 AltiVec Floating Point Arithmetic Instructions 17767 */ 17768 static Bool dis_av_fp_arith ( UInt theInstr ) 17769 { 17770 /* VA-Form */ 17771 UChar opc1 = ifieldOPC(theInstr); 17772 UChar vD_addr = ifieldRegDS(theInstr); 17773 UChar vA_addr = ifieldRegA(theInstr); 17774 UChar vB_addr = ifieldRegB(theInstr); 17775 UChar vC_addr = ifieldRegC(theInstr); 17776 UInt opc2=0; 17777 17778 IRTemp vA = newTemp(Ity_V128); 17779 IRTemp vB = newTemp(Ity_V128); 17780 IRTemp vC = newTemp(Ity_V128); 17781 assign( vA, getVReg(vA_addr)); 17782 assign( vB, getVReg(vB_addr)); 17783 assign( vC, getVReg(vC_addr)); 17784 17785 if (opc1 != 0x4) { 17786 vex_printf("dis_av_fp_arith(ppc)(instr)\n"); 17787 return False; 17788 } 17789 17790 IRTemp rm = newTemp(Ity_I32); 17791 assign(rm, get_IR_roundingmode()); 17792 17793 opc2 = IFIELD( theInstr, 0, 6 ); 17794 switch (opc2) { 17795 case 0x2E: // vmaddfp (Multiply Add FP, AV p177) 17796 DIP("vmaddfp v%d,v%d,v%d,v%d\n", 17797 vD_addr, vA_addr, vC_addr, vB_addr); 17798 putVReg( vD_addr, 17799 triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST), 17800 mkexpr(vB), 17801 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 17802 mkexpr(vA), mkexpr(vC))) ); 17803 return True; 17804 17805 case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215) 17806 DIP("vnmsubfp v%d,v%d,v%d,v%d\n", 17807 vD_addr, vA_addr, vC_addr, vB_addr); 17808 putVReg( vD_addr, 17809 triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST), 17810 mkexpr(vB), 17811 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 17812 mkexpr(vA), mkexpr(vC))) ); 17813 return True; 17814 } 17815 17816 default: 17817 break; // Fall through... 17818 } 17819 17820 opc2 = IFIELD( theInstr, 0, 11 ); 17821 switch (opc2) { 17822 case 0x00A: // vaddfp (Add FP, AV p137) 17823 DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17824 putVReg( vD_addr, triop(Iop_Add32Fx4, 17825 mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) ); 17826 return True; 17827 17828 case 0x04A: // vsubfp (Subtract FP, AV p261) 17829 DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17830 putVReg( vD_addr, triop(Iop_Sub32Fx4, 17831 mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) ); 17832 return True; 17833 17834 case 0x40A: // vmaxfp (Maximum FP, AV p178) 17835 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17836 putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) ); 17837 return True; 17838 17839 case 0x44A: // vminfp (Minimum FP, AV p187) 17840 DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr); 17841 putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) ); 17842 return True; 17843 17844 default: 17845 break; // Fall through... 17846 } 17847 17848 17849 if (vA_addr != 0) { 17850 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n"); 17851 return False; 17852 } 17853 17854 switch (opc2) { 17855 case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228) 17856 DIP("vrefp v%d,v%d\n", vD_addr, vB_addr); 17857 putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) ); 17858 return True; 17859 17860 case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237) 17861 DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr); 17862 putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) ); 17863 return True; 17864 17865 case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173) 17866 DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr); 17867 DIP(" => not implemented\n"); 17868 return False; 17869 17870 case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175) 17871 DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr); 17872 DIP(" => not implemented\n"); 17873 return False; 17874 17875 default: 17876 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2); 17877 return False; 17878 } 17879 return True; 17880 } 17881 17882 /* 17883 AltiVec Floating Point Compare Instructions 17884 */ 17885 static Bool dis_av_fp_cmp ( UInt theInstr ) 17886 { 17887 /* VXR-Form */ 17888 UChar opc1 = ifieldOPC(theInstr); 17889 UChar vD_addr = ifieldRegDS(theInstr); 17890 UChar vA_addr = ifieldRegA(theInstr); 17891 UChar vB_addr = ifieldRegB(theInstr); 17892 UChar flag_rC = ifieldBIT10(theInstr); 17893 UInt opc2 = IFIELD( theInstr, 0, 10 ); 17894 17895 Bool cmp_bounds = False; 17896 17897 IRTemp vA = newTemp(Ity_V128); 17898 IRTemp vB = newTemp(Ity_V128); 17899 IRTemp vD = newTemp(Ity_V128); 17900 assign( vA, getVReg(vA_addr)); 17901 assign( vB, getVReg(vB_addr)); 17902 17903 if (opc1 != 0x4) { 17904 vex_printf("dis_av_fp_cmp(ppc)(instr)\n"); 17905 return False; 17906 } 17907 17908 switch (opc2) { 17909 case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159) 17910 DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 17911 vD_addr, vA_addr, vB_addr); 17912 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) ); 17913 break; 17914 17915 case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163) 17916 DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 17917 vD_addr, vA_addr, vB_addr); 17918 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) ); 17919 break; 17920 17921 case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164) 17922 DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 17923 vD_addr, vA_addr, vB_addr); 17924 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) ); 17925 break; 17926 17927 case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157) 17928 IRTemp gt = newTemp(Ity_V128); 17929 IRTemp lt = newTemp(Ity_V128); 17930 IRTemp zeros = newTemp(Ity_V128); 17931 DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""), 17932 vD_addr, vA_addr, vB_addr); 17933 cmp_bounds = True; 17934 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) ); 17935 17936 /* Note: making use of fact that the ppc backend for compare insns 17937 return zero'd lanes if either of the corresponding arg lanes is 17938 a nan. 17939 17940 Perhaps better to have an irop Iop_isNan32Fx4, but then we'd 17941 need this for the other compares too (vcmpeqfp etc)... 17942 Better still, tighten down the spec for compare irops. 17943 */ 17944 assign( gt, unop(Iop_NotV128, 17945 binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) ); 17946 assign( lt, unop(Iop_NotV128, 17947 binop(Iop_CmpGE32Fx4, mkexpr(vA), 17948 triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST), 17949 mkexpr(zeros), 17950 mkexpr(vB)))) ); 17951 17952 // finally, just shift gt,lt to correct position 17953 assign( vD, binop(Iop_ShlN32x4, 17954 binop(Iop_OrV128, 17955 binop(Iop_AndV128, mkexpr(gt), 17956 unop(Iop_Dup32x4, mkU32(0x2))), 17957 binop(Iop_AndV128, mkexpr(lt), 17958 unop(Iop_Dup32x4, mkU32(0x1)))), 17959 mkU8(30)) ); 17960 break; 17961 } 17962 17963 default: 17964 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n"); 17965 return False; 17966 } 17967 17968 putVReg( vD_addr, mkexpr(vD) ); 17969 17970 if (flag_rC) { 17971 set_AV_CR6( mkexpr(vD), !cmp_bounds ); 17972 } 17973 return True; 17974 } 17975 17976 /* 17977 AltiVec Floating Point Convert/Round Instructions 17978 */ 17979 static Bool dis_av_fp_convert ( UInt theInstr ) 17980 { 17981 /* VX-Form */ 17982 UChar opc1 = ifieldOPC(theInstr); 17983 UChar vD_addr = ifieldRegDS(theInstr); 17984 UChar UIMM_5 = ifieldRegA(theInstr); 17985 UChar vB_addr = ifieldRegB(theInstr); 17986 UInt opc2 = IFIELD( theInstr, 0, 11 ); 17987 17988 IRTemp vB = newTemp(Ity_V128); 17989 IRTemp vScale = newTemp(Ity_V128); 17990 IRTemp vInvScale = newTemp(Ity_V128); 17991 17992 float scale, inv_scale; 17993 17994 assign( vB, getVReg(vB_addr)); 17995 17996 /* scale = 2^UIMM, cast to float, reinterpreted as uint */ 17997 scale = (float)( (unsigned int) 1<<UIMM_5 ); 17998 assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) ); 17999 inv_scale = 1/scale; 18000 assign( vInvScale, 18001 unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) ); 18002 18003 if (opc1 != 0x4) { 18004 vex_printf("dis_av_fp_convert(ppc)(instr)\n"); 18005 return False; 18006 } 18007 18008 switch (opc2) { 18009 case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156) 18010 DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18011 putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18012 unop(Iop_I32UtoFx4, mkexpr(vB)), 18013 mkexpr(vInvScale)) ); 18014 return True; 18015 18016 case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155) 18017 DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18018 18019 putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18020 unop(Iop_I32StoFx4, mkexpr(vB)), 18021 mkexpr(vInvScale)) ); 18022 return True; 18023 18024 case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172) 18025 DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18026 putVReg( vD_addr, 18027 unop(Iop_QFtoI32Ux4_RZ, 18028 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18029 mkexpr(vB), mkexpr(vScale))) ); 18030 return True; 18031 18032 case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171) 18033 DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5); 18034 putVReg( vD_addr, 18035 unop(Iop_QFtoI32Sx4_RZ, 18036 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST), 18037 mkexpr(vB), mkexpr(vScale))) ); 18038 return True; 18039 18040 default: 18041 break; // Fall through... 18042 } 18043 18044 if (UIMM_5 != 0) { 18045 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n"); 18046 return False; 18047 } 18048 18049 switch (opc2) { 18050 case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231) 18051 DIP("vrfin v%d,v%d\n", vD_addr, vB_addr); 18052 putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) ); 18053 break; 18054 18055 case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233) 18056 DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr); 18057 putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) ); 18058 break; 18059 18060 case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232) 18061 DIP("vrfip v%d,v%d\n", vD_addr, vB_addr); 18062 putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) ); 18063 break; 18064 18065 case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230) 18066 DIP("vrfim v%d,v%d\n", vD_addr, vB_addr); 18067 putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) ); 18068 break; 18069 18070 default: 18071 vex_printf("dis_av_fp_convert(ppc)(opc2)\n"); 18072 return False; 18073 } 18074 return True; 18075 } 18076 18077 static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr, 18078 VexAbiInfo* vbi, 18079 /*OUT*/DisResult* dres, 18080 Bool (*resteerOkFn)(void*,Addr64), 18081 void* callback_opaque ) 18082 { 18083 UInt opc2 = IFIELD( theInstr, 1, 10 ); 18084 18085 switch (opc2) { 18086 case 0x28E: { //tbegin. 18087 /* The current implementation is to just fail the tbegin and execute 18088 * the failure path. The failure path is assumed to be functionaly 18089 * equivalent to the transactional path with the needed data locking 18090 * to ensure correctness. The tend is just a noop and shouldn't 18091 * actually get executed. 18092 * 1) set cr0 to 0x2 18093 * 2) Initialize TFHAR to CIA+4 18094 * 3) Initialize TEXASR 18095 * 4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.) 18096 * 5) Continue executing at the next instruction. 18097 */ 18098 UInt R = IFIELD( theInstr, 21, 1 ); 18099 18100 ULong tm_reason; 18101 UInt failure_code = 0; /* Forcing failure, will not be due to tabort 18102 * or treclaim. 18103 */ 18104 UInt persistant = 1; /* set persistant since we are always failing 18105 * the tbegin. 18106 */ 18107 UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this 18108 as the reason for failing the trasaction */ 18109 UInt tm_exact = 1; /* have exact address for failure */ 18110 18111 DIP("tbegin. %d\n", R); 18112 18113 /* Set the CR0 field to indicate the tbegin failed. Then let 18114 * the code do the branch to the failure path. 18115 * 18116 * 000 || 0 Transaction initiation successful, 18117 * unnested (Transaction state of 18118 * Non-transactional prior to tbegin.) 18119 * 010 || 0 Transaction initiation successful, nested 18120 * (Transaction state of Transactional 18121 * prior to tbegin.) 18122 * 001 || 0 Transaction initiation unsuccessful, 18123 * (Transaction state of Suspended prior 18124 * to tbegin.) 18125 */ 18126 putCR321( 0, mkU8( 0x2 ) ); 18127 18128 tm_reason = generate_TMreason( failure_code, persistant, 18129 nest_overflow, tm_exact ); 18130 18131 storeTMfailure( guest_CIA_curr_instr, tm_reason, 18132 guest_CIA_curr_instr+4 ); 18133 18134 return True; 18135 18136 break; 18137 } 18138 18139 case 0x2AE: { //tend. 18140 /* The tend. is just a noop. Do nothing */ 18141 UInt A = IFIELD( theInstr, 25, 1 ); 18142 18143 DIP("tend. %d\n", A); 18144 break; 18145 } 18146 18147 case 0x2EE: { //tsr. 18148 /* The tsr. is just a noop. Do nothing */ 18149 UInt L = IFIELD( theInstr, 21, 1 ); 18150 18151 DIP("tsr. %d\n", L); 18152 break; 18153 } 18154 18155 case 0x2CE: { //tcheck. 18156 /* The tcheck. is just a noop. Do nothing */ 18157 UInt BF = IFIELD( theInstr, 25, 1 ); 18158 18159 DIP("tcheck. %d\n", BF); 18160 break; 18161 } 18162 18163 case 0x30E: { //tbortwc. 18164 /* The tabortwc. is just a noop. Do nothing */ 18165 UInt TO = IFIELD( theInstr, 25, 1 ); 18166 UInt RA = IFIELD( theInstr, 16, 5 ); 18167 UInt RB = IFIELD( theInstr, 11, 5 ); 18168 18169 DIP("tabortwc. %d,%d,%d\n", TO, RA, RB); 18170 break; 18171 } 18172 18173 case 0x32E: { //tbortdc. 18174 /* The tabortdc. is just a noop. Do nothing */ 18175 UInt TO = IFIELD( theInstr, 25, 1 ); 18176 UInt RA = IFIELD( theInstr, 16, 5 ); 18177 UInt RB = IFIELD( theInstr, 11, 5 ); 18178 18179 DIP("tabortdc. %d,%d,%d\n", TO, RA, RB); 18180 break; 18181 } 18182 18183 case 0x34E: { //tbortwci. 18184 /* The tabortwci. is just a noop. Do nothing */ 18185 UInt TO = IFIELD( theInstr, 25, 1 ); 18186 UInt RA = IFIELD( theInstr, 16, 5 ); 18187 UInt SI = IFIELD( theInstr, 11, 5 ); 18188 18189 DIP("tabortwci. %d,%d,%d\n", TO, RA, SI); 18190 break; 18191 } 18192 18193 case 0x36E: { //tbortdci. 18194 /* The tabortdci. is just a noop. Do nothing */ 18195 UInt TO = IFIELD( theInstr, 25, 1 ); 18196 UInt RA = IFIELD( theInstr, 16, 5 ); 18197 UInt SI = IFIELD( theInstr, 11, 5 ); 18198 18199 DIP("tabortdci. %d,%d,%d\n", TO, RA, SI); 18200 break; 18201 } 18202 18203 case 0x38E: { //tbort. 18204 /* The tabort. is just a noop. Do nothing */ 18205 UInt RA = IFIELD( theInstr, 16, 5 ); 18206 18207 DIP("tabort. %d\n", RA); 18208 break; 18209 } 18210 18211 case 0x3AE: { //treclaim. 18212 /* The treclaim. is just a noop. Do nothing */ 18213 UInt RA = IFIELD( theInstr, 16, 5 ); 18214 18215 DIP("treclaim. %d\n", RA); 18216 break; 18217 } 18218 18219 case 0x3EE: { //trechkpt. 18220 /* The trechkpt. is just a noop. Do nothing */ 18221 DIP("trechkpt.\n"); 18222 break; 18223 } 18224 18225 default: 18226 vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n"); 18227 return False; 18228 } 18229 18230 return True; 18231 } 18232 18233 18234 /* The 0x3C primary opcode (VSX category) uses several different forms of 18235 * extended opcodes: 18236 * o XX2-form: 18237 * - [10:2] (IBM notation [21:29]) 18238 * o XX3-form variants: 18239 * - variant 1: [10:3] (IBM notation [21:28]) 18240 * - variant 2: [9:3] (IBM notation [22:28]) 18241 * - variant 3: [7:3] (IBM notation [24:28]) 18242 * o XX-4 form: 18243 * - [10:6] (IBM notation [21:25]) 18244 * 18245 * The XX2-form needs bit 0 masked from the standard extended opcode 18246 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked; 18247 * and the XX4-form needs bits 0, 1, and 2 masked. Additionally, the 18248 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the 18249 * front end since their encoding does not begin at bit 21 like the standard 18250 * format. 18251 * 18252 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the 18253 * secondary opcode for such VSX instructions. 18254 * 18255 */ 18256 18257 18258 struct vsx_insn { 18259 UInt opcode; 18260 const HChar * name; 18261 }; 18262 18263 // ATTENTION: Keep this array sorted on the opcocde!!! 18264 static struct vsx_insn vsx_all[] = { 18265 { 0x0, "xsaddsp" }, 18266 { 0x4, "xsmaddasp" }, 18267 { 0x8, "xxsldwi" }, 18268 { 0x14, "xsrsqrtesp" }, 18269 { 0x16, "xssqrtsp" }, 18270 { 0x18, "xxsel" }, 18271 { 0x20, "xssubsp" }, 18272 { 0x24, "xsmaddmsp" }, 18273 { 0x28, "xxpermdi" }, 18274 { 0x34, "xsresp" }, 18275 { 0x40, "xsmulsp" }, 18276 { 0x44, "xsmsubasp" }, 18277 { 0x48, "xxmrghw" }, 18278 { 0x60, "xsdivsp" }, 18279 { 0x64, "xsmsubmsp" }, 18280 { 0x80, "xsadddp" }, 18281 { 0x84, "xsmaddadp" }, 18282 { 0x8c, "xscmpudp" }, 18283 { 0x90, "xscvdpuxws" }, 18284 { 0x92, "xsrdpi" }, 18285 { 0x94, "xsrsqrtedp" }, 18286 { 0x96, "xssqrtdp" }, 18287 { 0xa0, "xssubdp" }, 18288 { 0xa4, "xsmaddmdp" }, 18289 { 0xac, "xscmpodp" }, 18290 { 0xb0, "xscvdpsxws" }, 18291 { 0xb2, "xsrdpiz" }, 18292 { 0xb4, "xsredp" }, 18293 { 0xc0, "xsmuldp" }, 18294 { 0xc4, "xsmsubadp" }, 18295 { 0xc8, "xxmrglw" }, 18296 { 0xd2, "xsrdpip" }, 18297 { 0xd4, "xstsqrtdp" }, 18298 { 0xd6, "xsrdpic" }, 18299 { 0xe0, "xsdivdp" }, 18300 { 0xe4, "xsmsubmdp" }, 18301 { 0xf2, "xsrdpim" }, 18302 { 0xf4, "xstdivdp" }, 18303 { 0x100, "xvaddsp" }, 18304 { 0x104, "xvmaddasp" }, 18305 { 0x10c, "xvcmpeqsp" }, 18306 { 0x110, "xvcvspuxws" }, 18307 { 0x112, "xvrspi" }, 18308 { 0x114, "xvrsqrtesp" }, 18309 { 0x116, "xvsqrtsp" }, 18310 { 0x120, "xvsubsp" }, 18311 { 0x124, "xvmaddmsp" }, 18312 { 0x12c, "xvcmpgtsp" }, 18313 { 0x130, "xvcvspsxws" }, 18314 { 0x132, "xvrspiz" }, 18315 { 0x134, "xvresp" }, 18316 { 0x140, "xvmulsp" }, 18317 { 0x144, "xvmsubasp" }, 18318 { 0x148, "xxspltw" }, 18319 { 0x14c, "xvcmpgesp" }, 18320 { 0x150, "xvcvuxwsp" }, 18321 { 0x152, "xvrspip" }, 18322 { 0x154, "xvtsqrtsp" }, 18323 { 0x156, "xvrspic" }, 18324 { 0x160, "xvdivsp" }, 18325 { 0x164, "xvmsubmsp" }, 18326 { 0x170, "xvcvsxwsp" }, 18327 { 0x172, "xvrspim" }, 18328 { 0x174, "xvtdivsp" }, 18329 { 0x180, "xvadddp" }, 18330 { 0x184, "xvmaddadp" }, 18331 { 0x18c, "xvcmpeqdp" }, 18332 { 0x190, "xvcvdpuxws" }, 18333 { 0x192, "xvrdpi" }, 18334 { 0x194, "xvrsqrtedp" }, 18335 { 0x196, "xvsqrtdp" }, 18336 { 0x1a0, "xvsubdp" }, 18337 { 0x1a4, "xvmaddmdp" }, 18338 { 0x1ac, "xvcmpgtdp" }, 18339 { 0x1b0, "xvcvdpsxws" }, 18340 { 0x1b2, "xvrdpiz" }, 18341 { 0x1b4, "xvredp" }, 18342 { 0x1c0, "xvmuldp" }, 18343 { 0x1c4, "xvmsubadp" }, 18344 { 0x1cc, "xvcmpgedp" }, 18345 { 0x1d0, "xvcvuxwdp" }, 18346 { 0x1d2, "xvrdpip" }, 18347 { 0x1d4, "xvtsqrtdp" }, 18348 { 0x1d6, "xvrdpic" }, 18349 { 0x1e0, "xvdivdp" }, 18350 { 0x1e4, "xvmsubmdp" }, 18351 { 0x1f0, "xvcvsxwdp" }, 18352 { 0x1f2, "xvrdpim" }, 18353 { 0x1f4, "xvtdivdp" }, 18354 { 0x204, "xsnmaddasp" }, 18355 { 0x208, "xxland" }, 18356 { 0x212, "xscvdpsp" }, 18357 { 0x216, "xscvdpspn" }, 18358 { 0x224, "xsnmaddmsp" }, 18359 { 0x228, "xxlandc" }, 18360 { 0x232, "xxrsp" }, 18361 { 0x244, "xsnmsubasp" }, 18362 { 0x248, "xxlor" }, 18363 { 0x250, "xscvuxdsp" }, 18364 { 0x264, "xsnmsubmsp" }, 18365 { 0x268, "xxlxor" }, 18366 { 0x270, "xscvsxdsp" }, 18367 { 0x280, "xsmaxdp" }, 18368 { 0x284, "xsnmaddadp" }, 18369 { 0x288, "xxlnor" }, 18370 { 0x290, "xscvdpuxds" }, 18371 { 0x292, "xscvspdp" }, 18372 { 0x296, "xscvspdpn" }, 18373 { 0x2a0, "xsmindp" }, 18374 { 0x2a4, "xsnmaddmdp" }, 18375 { 0x2a8, "xxlorc" }, 18376 { 0x2b0, "xscvdpsxds" }, 18377 { 0x2b2, "xsabsdp" }, 18378 { 0x2c0, "xscpsgndp" }, 18379 { 0x2c4, "xsnmsubadp" }, 18380 { 0x2c8, "xxlnand" }, 18381 { 0x2d0, "xscvuxddp" }, 18382 { 0x2d2, "xsnabsdp" }, 18383 { 0x2e4, "xsnmsubmdp" }, 18384 { 0x2e8, "xxleqv" }, 18385 { 0x2f0, "xscvsxddp" }, 18386 { 0x2f2, "xsnegdp" }, 18387 { 0x300, "xvmaxsp" }, 18388 { 0x304, "xvnmaddasp" }, 18389 { 0x30c, "xvcmpeqsp." }, 18390 { 0x310, "xvcvspuxds" }, 18391 { 0x312, "xvcvdpsp" }, 18392 { 0x320, "xvminsp" }, 18393 { 0x324, "xvnmaddmsp" }, 18394 { 0x32c, "xvcmpgtsp." }, 18395 { 0x330, "xvcvspsxds" }, 18396 { 0x332, "xvabssp" }, 18397 { 0x340, "xvcpsgnsp" }, 18398 { 0x344, "xvnmsubasp" }, 18399 { 0x34c, "xvcmpgesp." }, 18400 { 0x350, "xvcvuxdsp" }, 18401 { 0x352, "xvnabssp" }, 18402 { 0x364, "xvnmsubmsp" }, 18403 { 0x370, "xvcvsxdsp" }, 18404 { 0x372, "xvnegsp" }, 18405 { 0x380, "xvmaxdp" }, 18406 { 0x384, "xvnmaddadp" }, 18407 { 0x38c, "xvcmpeqdp." }, 18408 { 0x390, "xvcvdpuxds" }, 18409 { 0x392, "xvcvspdp" }, 18410 { 0x3a0, "xvmindp" }, 18411 { 0x3a4, "xvnmaddmdp" }, 18412 { 0x3ac, "xvcmpgtdp." }, 18413 { 0x3b0, "xvcvdpsxds" }, 18414 { 0x3b2, "xvabsdp" }, 18415 { 0x3c0, "xvcpsgndp" }, 18416 { 0x3c4, "xvnmsubadp" }, 18417 { 0x3cc, "xvcmpgedp." }, 18418 { 0x3d0, "xvcvuxddp" }, 18419 { 0x3d2, "xvnabsdp" }, 18420 { 0x3e4, "xvnmsubmdp" }, 18421 { 0x3f0, "xvcvsxddp" }, 18422 { 0x3f2, "xvnegdp" } 18423 }; 18424 #define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all) 18425 18426 18427 // ATTENTION: This search function assumes vsx_all array is sorted. 18428 static Int findVSXextOpCode(UInt opcode) 18429 { 18430 Int low, mid, high; 18431 low = 0; 18432 high = VSX_ALL_LEN - 1; 18433 while (low <= high) { 18434 mid = (low + high)/2; 18435 if (opcode < vsx_all[mid].opcode) 18436 high = mid - 1; 18437 else if (opcode > vsx_all[mid].opcode) 18438 low = mid + 1; 18439 else 18440 return mid; 18441 } 18442 return -1; 18443 } 18444 18445 18446 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is 18447 * passed, and we then try to match it up with one of the VSX forms 18448 * below. 18449 */ 18450 static UInt get_VSX60_opc2(UInt opc2_full) 18451 { 18452 #define XX2_MASK 0x000003FE 18453 #define XX3_1_MASK 0x000003FC 18454 #define XX3_2_MASK 0x000001FC 18455 #define XX3_3_MASK 0x0000007C 18456 #define XX4_MASK 0x00000018 18457 Int ret; 18458 UInt vsxExtOpcode = 0; 18459 18460 if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0) 18461 vsxExtOpcode = vsx_all[ret].opcode; 18462 else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0) 18463 vsxExtOpcode = vsx_all[ret].opcode; 18464 else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0) 18465 vsxExtOpcode = vsx_all[ret].opcode; 18466 else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0) 18467 vsxExtOpcode = vsx_all[ret].opcode; 18468 else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0) 18469 vsxExtOpcode = vsx_all[ret].opcode; 18470 18471 return vsxExtOpcode; 18472 } 18473 18474 /*------------------------------------------------------------*/ 18475 /*--- Disassemble a single instruction ---*/ 18476 /*------------------------------------------------------------*/ 18477 18478 /* Disassemble a single instruction into IR. The instruction 18479 is located in host memory at &guest_code[delta]. */ 18480 18481 static 18482 DisResult disInstr_PPC_WRK ( 18483 Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ), 18484 Bool resteerCisOk, 18485 void* callback_opaque, 18486 Long delta64, 18487 VexArchInfo* archinfo, 18488 VexAbiInfo* abiinfo, 18489 Bool sigill_diag 18490 ) 18491 { 18492 UChar opc1; 18493 UInt opc2; 18494 DisResult dres; 18495 UInt theInstr; 18496 IRType ty = mode64 ? Ity_I64 : Ity_I32; 18497 Bool allow_F = False; 18498 Bool allow_V = False; 18499 Bool allow_FX = False; 18500 Bool allow_GX = False; 18501 Bool allow_VX = False; // Equates to "supports Power ISA 2.06 18502 Bool allow_DFP = False; 18503 Bool allow_isa_2_07 = False; 18504 UInt hwcaps = archinfo->hwcaps; 18505 Long delta; 18506 18507 /* What insn variants are we supporting today? */ 18508 if (mode64) { 18509 allow_F = True; 18510 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC64_V)); 18511 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX)); 18512 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX)); 18513 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX)); 18514 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP)); 18515 allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07)); 18516 } else { 18517 allow_F = (0 != (hwcaps & VEX_HWCAPS_PPC32_F)); 18518 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC32_V)); 18519 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX)); 18520 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX)); 18521 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX)); 18522 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP)); 18523 allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07)); 18524 } 18525 18526 /* The running delta */ 18527 delta = (Long)mkSzAddr(ty, (ULong)delta64); 18528 18529 /* Set result defaults. */ 18530 dres.whatNext = Dis_Continue; 18531 dres.len = 0; 18532 dres.continueAt = 0; 18533 dres.jk_StopHere = Ijk_INVALID; 18534 18535 /* At least this is simple on PPC32: insns are all 4 bytes long, and 18536 4-aligned. So just fish the whole thing out of memory right now 18537 and have done. */ 18538 theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) ); 18539 18540 if (0) vex_printf("insn: 0x%x\n", theInstr); 18541 18542 DIP("\t0x%llx: ", (ULong)guest_CIA_curr_instr); 18543 18544 /* Spot "Special" instructions (see comment at top of file). */ 18545 { 18546 UChar* code = (UChar*)(guest_code + delta); 18547 /* Spot the 16-byte preamble: 18548 32-bit mode: 18549 5400183E rlwinm 0,0,3,0,31 18550 5400683E rlwinm 0,0,13,0,31 18551 5400E83E rlwinm 0,0,29,0,31 18552 5400983E rlwinm 0,0,19,0,31 18553 64-bit mode: 18554 78001800 rotldi 0,0,3 18555 78006800 rotldi 0,0,13 18556 7800E802 rotldi 0,0,61 18557 78009802 rotldi 0,0,51 18558 */ 18559 UInt word1 = mode64 ? 0x78001800 : 0x5400183E; 18560 UInt word2 = mode64 ? 0x78006800 : 0x5400683E; 18561 UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E; 18562 UInt word4 = mode64 ? 0x78009802 : 0x5400983E; 18563 if (getUIntBigendianly(code+ 0) == word1 && 18564 getUIntBigendianly(code+ 4) == word2 && 18565 getUIntBigendianly(code+ 8) == word3 && 18566 getUIntBigendianly(code+12) == word4) { 18567 /* Got a "Special" instruction preamble. Which one is it? */ 18568 if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) { 18569 /* %R3 = client_request ( %R4 ) */ 18570 DIP("r3 = client_request ( %%r4 )\n"); 18571 delta += 20; 18572 putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta )); 18573 dres.jk_StopHere = Ijk_ClientReq; 18574 dres.whatNext = Dis_StopHere; 18575 goto decode_success; 18576 } 18577 else 18578 if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) { 18579 /* %R3 = guest_NRADDR */ 18580 DIP("r3 = guest_NRADDR\n"); 18581 delta += 20; 18582 dres.len = 20; 18583 putIReg(3, IRExpr_Get( OFFB_NRADDR, ty )); 18584 goto decode_success; 18585 } 18586 else 18587 if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) { 18588 /* branch-and-link-to-noredir %R11 */ 18589 DIP("branch-and-link-to-noredir r11\n"); 18590 delta += 20; 18591 putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) ); 18592 putGST( PPC_GST_CIA, getIReg(11)); 18593 dres.jk_StopHere = Ijk_NoRedir; 18594 dres.whatNext = Dis_StopHere; 18595 goto decode_success; 18596 } 18597 else 18598 if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { 18599 /* %R3 = guest_NRADDR_GPR2 */ 18600 DIP("r3 = guest_NRADDR_GPR2\n"); 18601 delta += 20; 18602 dres.len = 20; 18603 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty )); 18604 goto decode_success; 18605 } 18606 else 18607 if (getUIntBigendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) { 18608 DIP("IR injection\n"); 18609 18610 vex_inject_ir(irsb, Iend_BE); 18611 18612 delta += 20; 18613 dres.len = 20; 18614 18615 // Invalidate the current insn. The reason is that the IRop we're 18616 // injecting here can change. In which case the translation has to 18617 // be redone. For ease of handling, we simply invalidate all the 18618 // time. 18619 18620 stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr))); 18621 stmt(IRStmt_Put(OFFB_CMLEN, mkSzImm(ty, 20))); 18622 18623 putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta )); 18624 dres.whatNext = Dis_StopHere; 18625 dres.jk_StopHere = Ijk_InvalICache; 18626 goto decode_success; 18627 } 18628 /* We don't know what it is. Set opc1/opc2 so decode_failure 18629 can print the insn following the Special-insn preamble. */ 18630 theInstr = getUIntBigendianly(code+16); 18631 opc1 = ifieldOPC(theInstr); 18632 opc2 = ifieldOPClo10(theInstr); 18633 goto decode_failure; 18634 /*NOTREACHED*/ 18635 } 18636 } 18637 18638 opc1 = ifieldOPC(theInstr); 18639 opc2 = ifieldOPClo10(theInstr); 18640 18641 // Note: all 'reserved' bits must be cleared, else invalid 18642 switch (opc1) { 18643 18644 /* Integer Arithmetic Instructions */ 18645 case 0x0C: case 0x0D: case 0x0E: // addic, addic., addi 18646 case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic 18647 if (dis_int_arith( theInstr )) goto decode_success; 18648 goto decode_failure; 18649 18650 /* Integer Compare Instructions */ 18651 case 0x0B: case 0x0A: // cmpi, cmpli 18652 if (dis_int_cmp( theInstr )) goto decode_success; 18653 goto decode_failure; 18654 18655 /* Integer Logical Instructions */ 18656 case 0x1C: case 0x1D: case 0x18: // andi., andis., ori 18657 case 0x19: case 0x1A: case 0x1B: // oris, xori, xoris 18658 if (dis_int_logic( theInstr )) goto decode_success; 18659 goto decode_failure; 18660 18661 /* Integer Rotate Instructions */ 18662 case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm 18663 if (dis_int_rot( theInstr )) goto decode_success; 18664 goto decode_failure; 18665 18666 /* 64bit Integer Rotate Instructions */ 18667 case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi 18668 if (!mode64) goto decode_failure; 18669 if (dis_int_rot( theInstr )) goto decode_success; 18670 goto decode_failure; 18671 18672 /* Integer Load Instructions */ 18673 case 0x22: case 0x23: case 0x2A: // lbz, lbzu, lha 18674 case 0x2B: case 0x28: case 0x29: // lhau, lhz, lhzu 18675 case 0x20: case 0x21: // lwz, lwzu 18676 if (dis_int_load( theInstr )) goto decode_success; 18677 goto decode_failure; 18678 18679 /* Integer Store Instructions */ 18680 case 0x26: case 0x27: case 0x2C: // stb, stbu, sth 18681 case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu 18682 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 18683 goto decode_failure; 18684 18685 /* Integer Load and Store Multiple Instructions */ 18686 case 0x2E: case 0x2F: // lmw, stmw 18687 if (dis_int_ldst_mult( theInstr )) goto decode_success; 18688 goto decode_failure; 18689 18690 /* Branch Instructions */ 18691 case 0x12: case 0x10: // b, bc 18692 if (dis_branch(theInstr, abiinfo, &dres, 18693 resteerOkFn, callback_opaque)) 18694 goto decode_success; 18695 goto decode_failure; 18696 18697 /* System Linkage Instructions */ 18698 case 0x11: // sc 18699 if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success; 18700 goto decode_failure; 18701 18702 /* Trap Instructions */ 18703 case 0x02: // tdi 18704 if (!mode64) goto decode_failure; 18705 if (dis_trapi(theInstr, &dres)) goto decode_success; 18706 goto decode_failure; 18707 18708 case 0x03: // twi 18709 if (dis_trapi(theInstr, &dres)) goto decode_success; 18710 goto decode_failure; 18711 18712 /* Floating Point Load Instructions */ 18713 case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd 18714 case 0x33: // lfdu 18715 if (!allow_F) goto decode_noF; 18716 if (dis_fp_load( theInstr )) goto decode_success; 18717 goto decode_failure; 18718 18719 /* Floating Point Store Instructions */ 18720 case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx 18721 case 0x37: // stfdux 18722 if (!allow_F) goto decode_noF; 18723 if (dis_fp_store( theInstr )) goto decode_success; 18724 goto decode_failure; 18725 18726 /* Floating Point Load Double Pair Instructions */ 18727 case 0x39: case 0x3D: 18728 if (!allow_F) goto decode_noF; 18729 if (dis_fp_pair( theInstr )) goto decode_success; 18730 goto decode_failure; 18731 18732 /* 128-bit Integer Load */ 18733 case 0x38: // lq 18734 if (dis_int_load( theInstr )) goto decode_success; 18735 goto decode_failure; 18736 18737 /* 64bit Integer Loads */ 18738 case 0x3A: // ld, ldu, lwa 18739 if (!mode64) goto decode_failure; 18740 if (dis_int_load( theInstr )) goto decode_success; 18741 goto decode_failure; 18742 18743 case 0x3B: 18744 if (!allow_F) goto decode_noF; 18745 opc2 = ifieldOPClo10(theInstr); 18746 18747 switch (opc2) { 18748 case 0x2: // dadd - DFP Add 18749 case 0x202: // dsub - DFP Subtract 18750 case 0x22: // dmul - DFP Mult 18751 case 0x222: // ddiv - DFP Divide 18752 if (!allow_DFP) goto decode_noDFP; 18753 if (dis_dfp_arith( theInstr )) 18754 goto decode_success; 18755 case 0x82: // dcmpo, DFP comparison ordered instruction 18756 case 0x282: // dcmpu, DFP comparison unordered instruction 18757 if (!allow_DFP) 18758 goto decode_failure; 18759 if (dis_dfp_compare( theInstr ) ) 18760 goto decode_success; 18761 goto decode_failure; 18762 case 0x102: // dctdp - DFP convert to DFP long 18763 case 0x302: // drsp - DFP round to dfp short 18764 case 0x122: // dctfix - DFP convert to fixed 18765 if (!allow_DFP) 18766 goto decode_failure; 18767 if (dis_dfp_fmt_conv( theInstr )) 18768 goto decode_success; 18769 goto decode_failure; 18770 case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed 18771 if (!allow_VX) 18772 goto decode_failure; 18773 if (dis_dfp_fmt_conv( theInstr )) 18774 goto decode_success; 18775 goto decode_failure; 18776 case 0x2A2: // dtstsf - DFP number of significant digits 18777 if (!allow_DFP) 18778 goto decode_failure; 18779 if (dis_dfp_significant_digits(theInstr)) 18780 goto decode_success; 18781 goto decode_failure; 18782 case 0x142: // ddedpd DFP Decode DPD to BCD 18783 case 0x342: // denbcd DFP Encode BCD to DPD 18784 if (!allow_DFP) 18785 goto decode_failure; 18786 if (dis_dfp_bcd(theInstr)) 18787 goto decode_success; 18788 goto decode_failure; 18789 case 0x162: // dxex - Extract exponent 18790 case 0x362: // diex - Insert exponent 18791 if (!allow_DFP) 18792 goto decode_failure; 18793 if (dis_dfp_extract_insert( theInstr ) ) 18794 goto decode_success; 18795 goto decode_failure; 18796 case 0x3CE: // fcfidus (implemented as native insn) 18797 if (!allow_VX) 18798 goto decode_noVX; 18799 if (dis_fp_round( theInstr )) 18800 goto decode_success; 18801 goto decode_failure; 18802 case 0x34E: // fcfids 18803 if (dis_fp_round( theInstr )) 18804 goto decode_success; 18805 goto decode_failure; 18806 } 18807 18808 opc2 = ifieldOPClo9( theInstr ); 18809 switch (opc2) { 18810 case 0x42: // dscli, DFP shift left 18811 case 0x62: // dscri, DFP shift right 18812 if (!allow_DFP) 18813 goto decode_failure; 18814 if (dis_dfp_shift( theInstr )) 18815 goto decode_success; 18816 goto decode_failure; 18817 case 0xc2: // dtstdc, DFP test data class 18818 case 0xe2: // dtstdg, DFP test data group 18819 if (!allow_DFP) 18820 goto decode_failure; 18821 if (dis_dfp_class_test( theInstr )) 18822 goto decode_success; 18823 goto decode_failure; 18824 } 18825 18826 opc2 = ifieldOPClo8( theInstr ); 18827 switch (opc2) { 18828 case 0x3: // dqua - DFP Quantize 18829 case 0x23: // drrnd - DFP Reround 18830 case 0x43: // dquai - DFP Quantize immediate 18831 if (!allow_DFP) 18832 goto decode_failure; 18833 if (dis_dfp_quantize_sig_rrnd( theInstr ) ) 18834 goto decode_success; 18835 goto decode_failure; 18836 case 0xA2: // dtstex - DFP Test exponent 18837 if (!allow_DFP) 18838 goto decode_failure; 18839 if (dis_dfp_exponent_test( theInstr ) ) 18840 goto decode_success; 18841 goto decode_failure; 18842 case 0x63: // drintx - Round to an integer value 18843 case 0xE3: // drintn - Round to an integer value 18844 if (!allow_DFP) 18845 goto decode_failure; 18846 if (dis_dfp_round( theInstr ) ) { 18847 goto decode_success; 18848 } 18849 goto decode_failure; 18850 default: 18851 break; /* fall through to next opc2 check */ 18852 } 18853 18854 opc2 = IFIELD(theInstr, 1, 5); 18855 switch (opc2) { 18856 /* Floating Point Arith Instructions */ 18857 case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds 18858 case 0x19: // fmuls 18859 if (dis_fp_arith(theInstr)) goto decode_success; 18860 goto decode_failure; 18861 case 0x16: // fsqrts 18862 if (!allow_FX) goto decode_noFX; 18863 if (dis_fp_arith(theInstr)) goto decode_success; 18864 goto decode_failure; 18865 case 0x18: // fres 18866 if (!allow_GX) goto decode_noGX; 18867 if (dis_fp_arith(theInstr)) goto decode_success; 18868 goto decode_failure; 18869 18870 /* Floating Point Mult-Add Instructions */ 18871 case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs 18872 case 0x1F: // fnmadds 18873 if (dis_fp_multadd(theInstr)) goto decode_success; 18874 goto decode_failure; 18875 18876 case 0x1A: // frsqrtes 18877 if (!allow_GX) goto decode_noGX; 18878 if (dis_fp_arith(theInstr)) goto decode_success; 18879 goto decode_failure; 18880 18881 default: 18882 goto decode_failure; 18883 } 18884 break; 18885 18886 case 0x3C: // VSX instructions (except load/store) 18887 { 18888 // All of these VSX instructions use some VMX facilities, so 18889 // if allow_V is not set, we'll skip trying to decode. 18890 if (!allow_V) goto decode_noVX; 18891 18892 UInt vsxOpc2 = get_VSX60_opc2(opc2); 18893 /* The vsxOpc2 returned is the "normalized" value, representing the 18894 * instructions secondary opcode as taken from the standard secondary 18895 * opcode field [21:30] (IBM notatition), even if the actual field 18896 * is non-standard. These normalized values are given in the opcode 18897 * appendices of the ISA 2.06 document. 18898 */ 18899 18900 switch (vsxOpc2) { 18901 case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw 18902 case 0x018: case 0x148: // xxsel, xxspltw 18903 if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success; 18904 goto decode_failure; 18905 case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor, 18906 case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc 18907 case 0x2C8: case 0x2E8: // xxlnand, xxleqv 18908 if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success; 18909 goto decode_failure; 18910 case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp 18911 case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp 18912 case 0x280: case 0x2A0: // xsmaxdp, xsmindp 18913 case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip 18914 case 0x034: case 0x014: // xsresp, xsrsqrtesp 18915 case 0x0B4: case 0x094: // xsredp, xsrsqrtedp 18916 case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz 18917 case 0x092: case 0x232: // xsrdpi, xsrsp 18918 if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success; 18919 goto decode_failure; 18920 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp 18921 if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success; 18922 goto decode_failure; 18923 case 0x0: case 0x020: // xsaddsp, xssubsp 18924 case 0x080: // xsadddp 18925 case 0x060: case 0x0E0: // xsdivsp, xsdivdp 18926 case 0x004: case 0x024: // xsmaddasp, xsmaddmsp 18927 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp 18928 case 0x044: case 0x064: // xsmsubasp, xsmsubmsp 18929 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp 18930 case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp 18931 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp 18932 case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp 18933 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp 18934 case 0x040: case 0x0C0: // xsmulsp, xsmuldp 18935 case 0x0A0: // xssubdp 18936 case 0x016: case 0x096: // xssqrtsp,xssqrtdp 18937 case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp 18938 if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success; 18939 goto decode_failure; 18940 case 0x180: // xvadddp 18941 case 0x1E0: // xvdivdp 18942 case 0x1C0: // xvmuldp 18943 case 0x1A0: // xvsubdp 18944 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp 18945 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp 18946 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp 18947 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp 18948 case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp 18949 case 0x196: // xvsqrtdp 18950 if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success; 18951 goto decode_failure; 18952 case 0x100: // xvaddsp 18953 case 0x160: // xvdivsp 18954 case 0x140: // xvmulsp 18955 case 0x120: // xvsubsp 18956 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp 18957 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp 18958 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp 18959 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp 18960 case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp 18961 case 0x116: // xvsqrtsp 18962 if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success; 18963 goto decode_failure; 18964 18965 case 0x250: // xscvuxdsp 18966 case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp 18967 case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp 18968 case 0x090: // xscvdpuxws 18969 // The above VSX conversion instructions employ some ISA 2.06 18970 // floating point conversion instructions under the covers, 18971 // so if allow_VX (which means "supports ISA 2.06") is not set, 18972 // we'll skip the decode. 18973 if (!allow_VX) goto decode_noVX; 18974 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success; 18975 goto decode_failure; 18976 18977 case 0x2B0: // xscvdpsxds 18978 case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp 18979 case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws 18980 case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds 18981 case 0x212: case 0x216: // xscvdpsp, xscvdpspn 18982 case 0x292: case 0x296: // xscvspdp, xscvspdpn 18983 case 0x312: // xvcvdpsp 18984 case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws 18985 case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds 18986 case 0x392: case 0x330: // xvcvspdp, xvcvspsxds 18987 case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp 18988 case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp 18989 case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp 18990 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success; 18991 goto decode_failure; 18992 18993 case 0x18C: case 0x38C: // xvcmpeqdp[.] 18994 case 0x10C: case 0x30C: // xvcmpeqsp[.] 18995 case 0x14C: case 0x34C: // xvcmpgesp[.] 18996 case 0x12C: case 0x32C: // xvcmpgtsp[.] 18997 case 0x1CC: case 0x3CC: // xvcmpgedp[.] 18998 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] 18999 if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success; 19000 goto decode_failure; 19001 19002 case 0x134: // xvresp 19003 case 0x1B4: // xvredp 19004 case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp 19005 case 0x380: case 0x3A0: // xvmaxdp, xvmindp 19006 case 0x300: case 0x320: // xvmaxsp, xvminsp 19007 case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp 19008 case 0x3B2: case 0x332: // xvabsdp, xvabssp 19009 case 0x3D2: case 0x352: // xvnabsdp, xvnabssp 19010 case 0x192: case 0x1D6: // xvrdpi, xvrdpic 19011 case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip 19012 case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp 19013 case 0x112: case 0x156: // xvrspi, xvrspic 19014 case 0x172: case 0x152: // xvrspim, xvrspip 19015 case 0x132: // xvrspiz 19016 if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success; 19017 goto decode_failure; 19018 19019 default: 19020 goto decode_failure; 19021 } 19022 break; 19023 } 19024 19025 /* 64bit Integer Stores */ 19026 case 0x3E: // std, stdu, stq 19027 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 19028 goto decode_failure; 19029 19030 case 0x3F: 19031 if (!allow_F) goto decode_noF; 19032 /* Instrs using opc[1:5] never overlap instrs using opc[1:10], 19033 so we can simply fall through the first switch statement */ 19034 19035 opc2 = IFIELD(theInstr, 1, 5); 19036 switch (opc2) { 19037 /* Floating Point Arith Instructions */ 19038 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd 19039 case 0x19: // fmul 19040 if (dis_fp_arith(theInstr)) goto decode_success; 19041 goto decode_failure; 19042 case 0x16: // fsqrt 19043 if (!allow_FX) goto decode_noFX; 19044 if (dis_fp_arith(theInstr)) goto decode_success; 19045 goto decode_failure; 19046 case 0x17: case 0x1A: // fsel, frsqrte 19047 if (!allow_GX) goto decode_noGX; 19048 if (dis_fp_arith(theInstr)) goto decode_success; 19049 goto decode_failure; 19050 19051 /* Floating Point Mult-Add Instructions */ 19052 case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub 19053 case 0x1F: // fnmadd 19054 if (dis_fp_multadd(theInstr)) goto decode_success; 19055 goto decode_failure; 19056 19057 case 0x18: // fre 19058 if (!allow_GX) goto decode_noGX; 19059 if (dis_fp_arith(theInstr)) goto decode_success; 19060 goto decode_failure; 19061 19062 default: 19063 break; // Fall through 19064 } 19065 19066 opc2 = IFIELD(theInstr, 1, 10); 19067 switch (opc2) { 19068 /* 128-bit DFP instructions */ 19069 case 0x2: // daddq - DFP Add 19070 case 0x202: // dsubq - DFP Subtract 19071 case 0x22: // dmulq - DFP Mult 19072 case 0x222: // ddivq - DFP Divide 19073 if (!allow_DFP) goto decode_noDFP; 19074 if (dis_dfp_arithq( theInstr )) 19075 goto decode_success; 19076 goto decode_failure; 19077 case 0x162: // dxexq - DFP Extract exponent 19078 case 0x362: // diexq - DFP Insert exponent 19079 if (!allow_DFP) 19080 goto decode_failure; 19081 if (dis_dfp_extract_insertq( theInstr )) 19082 goto decode_success; 19083 goto decode_failure; 19084 19085 case 0x82: // dcmpoq, DFP comparison ordered instruction 19086 case 0x282: // dcmpuq, DFP comparison unordered instruction 19087 if (!allow_DFP) 19088 goto decode_failure; 19089 if (dis_dfp_compare( theInstr ) ) 19090 goto decode_success; 19091 goto decode_failure; 19092 19093 case 0x102: // dctqpq - DFP convert to DFP extended 19094 case 0x302: // drdpq - DFP round to dfp Long 19095 case 0x122: // dctfixq - DFP convert to fixed quad 19096 case 0x322: // dcffixq - DFP convert from fixed quad 19097 if (!allow_DFP) 19098 goto decode_failure; 19099 if (dis_dfp_fmt_convq( theInstr )) 19100 goto decode_success; 19101 goto decode_failure; 19102 19103 case 0x2A2: // dtstsfq - DFP number of significant digits 19104 if (!allow_DFP) 19105 goto decode_failure; 19106 if (dis_dfp_significant_digits(theInstr)) 19107 goto decode_success; 19108 goto decode_failure; 19109 19110 case 0x142: // ddedpdq DFP Decode DPD to BCD 19111 case 0x342: // denbcdq DFP Encode BCD to DPD 19112 if (!allow_DFP) 19113 goto decode_failure; 19114 if (dis_dfp_bcdq(theInstr)) 19115 goto decode_success; 19116 goto decode_failure; 19117 19118 /* Floating Point Compare Instructions */ 19119 case 0x000: // fcmpu 19120 case 0x020: // fcmpo 19121 if (dis_fp_cmp(theInstr)) goto decode_success; 19122 goto decode_failure; 19123 19124 case 0x080: // ftdiv 19125 case 0x0A0: // ftsqrt 19126 if (dis_fp_tests(theInstr)) goto decode_success; 19127 goto decode_failure; 19128 19129 /* Floating Point Rounding/Conversion Instructions */ 19130 case 0x00C: // frsp 19131 case 0x00E: // fctiw 19132 case 0x00F: // fctiwz 19133 case 0x32E: // fctid 19134 case 0x32F: // fctidz 19135 case 0x34E: // fcfid 19136 if (dis_fp_round(theInstr)) goto decode_success; 19137 goto decode_failure; 19138 case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns) 19139 case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns) 19140 if (!allow_VX) goto decode_noVX; 19141 if (dis_fp_round(theInstr)) goto decode_success; 19142 goto decode_failure; 19143 19144 /* Power6 rounding stuff */ 19145 case 0x1E8: // frim 19146 case 0x1C8: // frip 19147 case 0x188: // frin 19148 case 0x1A8: // friz 19149 /* A hack to check for P6 capability . . . */ 19150 if ((allow_F && allow_V && allow_FX && allow_GX) && 19151 (dis_fp_round(theInstr))) 19152 goto decode_success; 19153 goto decode_failure; 19154 19155 /* Floating Point Move Instructions */ 19156 case 0x008: // fcpsgn 19157 case 0x028: // fneg 19158 case 0x048: // fmr 19159 case 0x088: // fnabs 19160 case 0x108: // fabs 19161 if (dis_fp_move( theInstr )) goto decode_success; 19162 goto decode_failure; 19163 19164 case 0x3c6: case 0x346: // fmrgew, fmrgow 19165 if (dis_fp_merge( theInstr )) goto decode_success; 19166 goto decode_failure; 19167 19168 /* Floating Point Status/Control Register Instructions */ 19169 case 0x026: // mtfsb1 19170 case 0x040: // mcrfs 19171 case 0x046: // mtfsb0 19172 case 0x086: // mtfsfi 19173 case 0x247: // mffs 19174 case 0x2C7: // mtfsf 19175 // Some of the above instructions need to know more about the 19176 // ISA level supported by the host. 19177 if (dis_fp_scr( theInstr, allow_GX )) goto decode_success; 19178 goto decode_failure; 19179 19180 default: 19181 break; // Fall through... 19182 } 19183 19184 opc2 = ifieldOPClo9( theInstr ); 19185 switch (opc2) { 19186 case 0x42: // dscli, DFP shift left 19187 case 0x62: // dscri, DFP shift right 19188 if (!allow_DFP) 19189 goto decode_failure; 19190 if (dis_dfp_shiftq( theInstr )) 19191 goto decode_success; 19192 goto decode_failure; 19193 case 0xc2: // dtstdc, DFP test data class 19194 case 0xe2: // dtstdg, DFP test data group 19195 if (!allow_DFP) 19196 goto decode_failure; 19197 if (dis_dfp_class_test( theInstr )) 19198 goto decode_success; 19199 goto decode_failure; 19200 default: 19201 break; 19202 } 19203 19204 opc2 = ifieldOPClo8( theInstr ); 19205 switch (opc2) { 19206 case 0x3: // dquaq - DFP Quantize Quad 19207 case 0x23: // drrndq - DFP Reround Quad 19208 case 0x43: // dquaiq - DFP Quantize immediate Quad 19209 if (!allow_DFP) 19210 goto decode_failure; 19211 if (dis_dfp_quantize_sig_rrndq( theInstr )) 19212 goto decode_success; 19213 goto decode_failure; 19214 case 0xA2: // dtstexq - DFP Test exponent Quad 19215 if (dis_dfp_exponent_test( theInstr ) ) 19216 goto decode_success; 19217 goto decode_failure; 19218 case 0x63: // drintxq - DFP Round to an integer value 19219 case 0xE3: // drintnq - DFP Round to an integer value 19220 if (!allow_DFP) 19221 goto decode_failure; 19222 if (dis_dfp_roundq( theInstr )) 19223 goto decode_success; 19224 goto decode_failure; 19225 19226 default: 19227 goto decode_failure; 19228 } 19229 break; 19230 19231 case 0x13: 19232 switch (opc2) { 19233 19234 /* Condition Register Logical Instructions */ 19235 case 0x101: case 0x081: case 0x121: // crand, crandc, creqv 19236 case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror 19237 case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf 19238 if (dis_cond_logic( theInstr )) goto decode_success; 19239 goto decode_failure; 19240 19241 /* Branch Instructions */ 19242 case 0x210: case 0x010: // bcctr, bclr 19243 if (dis_branch(theInstr, abiinfo, &dres, 19244 resteerOkFn, callback_opaque)) 19245 goto decode_success; 19246 goto decode_failure; 19247 19248 /* Memory Synchronization Instructions */ 19249 case 0x096: // isync 19250 if (dis_memsync( theInstr )) goto decode_success; 19251 goto decode_failure; 19252 19253 default: 19254 goto decode_failure; 19255 } 19256 break; 19257 19258 19259 case 0x1F: 19260 19261 /* For arith instns, bit10 is the OE flag (overflow enable) */ 19262 19263 opc2 = IFIELD(theInstr, 1, 9); 19264 switch (opc2) { 19265 /* Integer Arithmetic Instructions */ 19266 case 0x10A: case 0x00A: case 0x08A: // add, addc, adde 19267 case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw 19268 case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu 19269 case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf 19270 case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme 19271 case 0x0C8: // subfze 19272 if (dis_int_arith( theInstr )) goto decode_success; 19273 goto decode_failure; 19274 19275 case 0x18B: // divweu (implemented as native insn) 19276 case 0x1AB: // divwe (implemented as native insn) 19277 if (!allow_VX) goto decode_noVX; 19278 if (dis_int_arith( theInstr )) goto decode_success; 19279 goto decode_failure; 19280 19281 /* 64bit Integer Arithmetic */ 19282 case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld 19283 case 0x1C9: case 0x1E9: // divdu, divd 19284 if (!mode64) goto decode_failure; 19285 if (dis_int_arith( theInstr )) goto decode_success; 19286 goto decode_failure; 19287 19288 case 0x1A9: // divde (implemented as native insn) 19289 case 0x189: // divdeuo (implemented as native insn) 19290 if (!allow_VX) goto decode_noVX; 19291 if (!mode64) goto decode_failure; 19292 if (dis_int_arith( theInstr )) goto decode_success; 19293 goto decode_failure; 19294 19295 case 0x1FC: // cmpb 19296 if (dis_int_logic( theInstr )) goto decode_success; 19297 goto decode_failure; 19298 19299 default: 19300 break; // Fall through... 19301 } 19302 19303 /* All remaining opcodes use full 10 bits. */ 19304 19305 opc2 = IFIELD(theInstr, 1, 10); 19306 switch (opc2) { 19307 /* Integer Compare Instructions */ 19308 case 0x000: case 0x020: // cmp, cmpl 19309 if (dis_int_cmp( theInstr )) goto decode_success; 19310 goto decode_failure; 19311 19312 /* Integer Logical Instructions */ 19313 case 0x01C: case 0x03C: case 0x01A: // and, andc, cntlzw 19314 case 0x11C: case 0x3BA: case 0x39A: // eqv, extsb, extsh 19315 case 0x1DC: case 0x07C: case 0x1BC: // nand, nor, or 19316 case 0x19C: case 0x13C: // orc, xor 19317 case 0x2DF: case 0x25F: // mftgpr, mffgpr 19318 if (dis_int_logic( theInstr )) goto decode_success; 19319 goto decode_failure; 19320 19321 case 0x28E: case 0x2AE: // tbegin., tend. 19322 case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc. 19323 case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci. 19324 case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt. 19325 if (dis_transactional_memory( theInstr, 19326 getUIntBigendianly( (UChar*)(&guest_code[delta + 4])), 19327 abiinfo, &dres, 19328 resteerOkFn, callback_opaque)) 19329 goto decode_success; 19330 goto decode_failure; 19331 19332 /* 64bit Integer Logical Instructions */ 19333 case 0x3DA: case 0x03A: // extsw, cntlzd 19334 if (!mode64) goto decode_failure; 19335 if (dis_int_logic( theInstr )) goto decode_success; 19336 goto decode_failure; 19337 19338 /* 64bit Integer Parity Instructions */ 19339 case 0xba: // prtyd 19340 if (!mode64) goto decode_failure; 19341 if (dis_int_parity( theInstr )) goto decode_success; 19342 goto decode_failure; 19343 19344 case 0x9a: // prtyw 19345 if (dis_int_parity( theInstr )) goto decode_success; 19346 goto decode_failure; 19347 19348 /* Integer Shift Instructions */ 19349 case 0x018: case 0x318: case 0x338: // slw, sraw, srawi 19350 case 0x218: // srw 19351 if (dis_int_shift( theInstr )) goto decode_success; 19352 goto decode_failure; 19353 19354 /* 64bit Integer Shift Instructions */ 19355 case 0x01B: case 0x31A: // sld, srad 19356 case 0x33A: case 0x33B: // sradi 19357 case 0x21B: // srd 19358 if (!mode64) goto decode_failure; 19359 if (dis_int_shift( theInstr )) goto decode_success; 19360 goto decode_failure; 19361 19362 /* Integer Load Instructions */ 19363 case 0x057: case 0x077: case 0x157: // lbzx, lbzux, lhax 19364 case 0x177: case 0x117: case 0x137: // lhaux, lhzx, lhzux 19365 case 0x017: case 0x037: // lwzx, lwzux 19366 if (dis_int_load( theInstr )) goto decode_success; 19367 goto decode_failure; 19368 19369 /* 64bit Integer Load Instructions */ 19370 case 0x035: case 0x015: // ldux, ldx 19371 case 0x175: case 0x155: // lwaux, lwax 19372 if (!mode64) goto decode_failure; 19373 if (dis_int_load( theInstr )) goto decode_success; 19374 goto decode_failure; 19375 19376 /* Integer Store Instructions */ 19377 case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux 19378 case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx 19379 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 19380 goto decode_failure; 19381 19382 /* 64bit Integer Store Instructions */ 19383 case 0x0B5: case 0x095: // stdux, stdx 19384 if (!mode64) goto decode_failure; 19385 if (dis_int_store( theInstr, abiinfo )) goto decode_success; 19386 goto decode_failure; 19387 19388 /* Integer Load and Store with Byte Reverse Instructions */ 19389 case 0x214: case 0x294: // ldbrx, stdbrx 19390 if (!mode64) goto decode_failure; 19391 if (dis_int_ldst_rev( theInstr )) goto decode_success; 19392 goto decode_failure; 19393 19394 case 0x216: case 0x316: case 0x296: // lwbrx, lhbrx, stwbrx 19395 case 0x396: // sthbrx 19396 if (dis_int_ldst_rev( theInstr )) goto decode_success; 19397 goto decode_failure; 19398 19399 /* Integer Load and Store String Instructions */ 19400 case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi 19401 case 0x295: { // stswx 19402 Bool stopHere = False; 19403 Bool ok = dis_int_ldst_str( theInstr, &stopHere ); 19404 if (!ok) goto decode_failure; 19405 if (stopHere) { 19406 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) ); 19407 dres.jk_StopHere = Ijk_Boring; 19408 dres.whatNext = Dis_StopHere; 19409 } 19410 goto decode_success; 19411 } 19412 19413 /* Memory Synchronization Instructions */ 19414 case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx. 19415 case 0x256: // sync 19416 if (dis_memsync( theInstr )) goto decode_success; 19417 goto decode_failure; 19418 19419 /* 64bit Memory Synchronization Instructions */ 19420 case 0x054: case 0x0D6: // ldarx, stdcx. 19421 if (!mode64) goto decode_failure; 19422 if (dis_memsync( theInstr )) goto decode_success; 19423 goto decode_failure; 19424 19425 case 0x114: case 0x0B6: // lqarx, stqcx. 19426 if (dis_memsync( theInstr )) goto decode_success; 19427 goto decode_failure; 19428 19429 /* Processor Control Instructions */ 19430 case 0x33: case 0x73: // mfvsrd, mfvsrwz 19431 case 0xB3: case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz 19432 case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr 19433 case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr 19434 case 0x220: // mcrxrt 19435 if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success; 19436 goto decode_failure; 19437 19438 /* Cache Management Instructions */ 19439 case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst 19440 case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz 19441 case 0x3D6: // icbi 19442 if (dis_cache_manage( theInstr, &dres, archinfo )) 19443 goto decode_success; 19444 goto decode_failure; 19445 19446 //zz /* External Control Instructions */ 19447 //zz case 0x136: case 0x1B6: // eciwx, ecowx 19448 //zz DIP("external control op => not implemented\n"); 19449 //zz goto decode_failure; 19450 19451 /* Trap Instructions */ 19452 case 0x004: // tw 19453 if (dis_trap(theInstr, &dres)) goto decode_success; 19454 goto decode_failure; 19455 19456 case 0x044: // td 19457 if (!mode64) goto decode_failure; 19458 if (dis_trap(theInstr, &dres)) goto decode_success; 19459 goto decode_failure; 19460 19461 /* Floating Point Load Instructions */ 19462 case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx 19463 case 0x277: // lfdux 19464 if (!allow_F) goto decode_noF; 19465 if (dis_fp_load( theInstr )) goto decode_success; 19466 goto decode_failure; 19467 19468 /* Floating Point Store Instructions */ 19469 case 0x297: case 0x2B7: case 0x2D7: // stfs, stfsu, stfd 19470 case 0x2F7: // stfdu, stfiwx 19471 if (!allow_F) goto decode_noF; 19472 if (dis_fp_store( theInstr )) goto decode_success; 19473 goto decode_failure; 19474 case 0x3D7: // stfiwx 19475 if (!allow_F) goto decode_noF; 19476 if (!allow_GX) goto decode_noGX; 19477 if (dis_fp_store( theInstr )) goto decode_success; 19478 goto decode_failure; 19479 19480 /* Floating Point Double Pair Indexed Instructions */ 19481 case 0x317: // lfdpx (Power6) 19482 case 0x397: // stfdpx (Power6) 19483 if (!allow_F) goto decode_noF; 19484 if (dis_fp_pair(theInstr)) goto decode_success; 19485 goto decode_failure; 19486 19487 case 0x357: // lfiwax 19488 if (!allow_F) goto decode_noF; 19489 if (dis_fp_load( theInstr )) goto decode_success; 19490 goto decode_failure; 19491 19492 case 0x377: // lfiwzx 19493 if (!allow_F) goto decode_noF; 19494 if (dis_fp_load( theInstr )) goto decode_success; 19495 goto decode_failure; 19496 19497 /* AltiVec instructions */ 19498 19499 /* AV Cache Control - Data streams */ 19500 case 0x156: case 0x176: case 0x336: // dst, dstst, dss 19501 if (!allow_V) goto decode_noV; 19502 if (dis_av_datastream( theInstr )) goto decode_success; 19503 goto decode_failure; 19504 19505 /* AV Load */ 19506 case 0x006: case 0x026: // lvsl, lvsr 19507 case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx 19508 case 0x067: case 0x167: // lvx, lvxl 19509 if (!allow_V) goto decode_noV; 19510 if (dis_av_load( abiinfo, theInstr )) goto decode_success; 19511 goto decode_failure; 19512 19513 /* AV Store */ 19514 case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx 19515 case 0x0E7: case 0x1E7: // stvx, stvxl 19516 if (!allow_V) goto decode_noV; 19517 if (dis_av_store( theInstr )) goto decode_success; 19518 goto decode_failure; 19519 19520 /* VSX Load */ 19521 case 0x00C: // lxsiwzx 19522 case 0x04C: // lxsiwax 19523 case 0x20C: // lxsspx 19524 case 0x24C: // lxsdx 19525 case 0x34C: // lxvd2x 19526 case 0x14C: // lxvdsx 19527 case 0x30C: // lxvw4x 19528 // All of these VSX load instructions use some VMX facilities, so 19529 // if allow_V is not set, we'll skip trying to decode. 19530 if (!allow_V) goto decode_noV; 19531 19532 if (dis_vx_load( theInstr )) goto decode_success; 19533 goto decode_failure; 19534 19535 /* VSX Store */ 19536 case 0x08C: // stxsiwx 19537 case 0x28C: // stxsspx 19538 case 0x2CC: // stxsdx 19539 case 0x3CC: // stxvd2x 19540 case 0x38C: // stxvw4x 19541 // All of these VSX store instructions use some VMX facilities, so 19542 // if allow_V is not set, we'll skip trying to decode. 19543 if (!allow_V) goto decode_noV; 19544 19545 if (dis_vx_store( theInstr )) goto decode_success; 19546 goto decode_failure; 19547 19548 /* Miscellaneous ISA 2.06 instructions */ 19549 case 0x1FA: // popcntd 19550 case 0x17A: // popcntw 19551 case 0x7A: // popcntb 19552 if (dis_int_logic( theInstr )) goto decode_success; 19553 goto decode_failure; 19554 19555 case 0x0FC: // bpermd 19556 if (!mode64) goto decode_failure; 19557 if (dis_int_logic( theInstr )) goto decode_success; 19558 goto decode_failure; 19559 19560 default: 19561 /* Deal with some other cases that we would otherwise have 19562 punted on. */ 19563 /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */ 19564 /* only decode this insn when reserved bit 0 (31 in IBM's 19565 notation) is zero */ 19566 if (IFIELD(theInstr, 0, 6) == (15<<1)) { 19567 UInt rT = ifieldRegDS( theInstr ); 19568 UInt rA = ifieldRegA( theInstr ); 19569 UInt rB = ifieldRegB( theInstr ); 19570 UInt bi = ifieldRegC( theInstr ); 19571 putIReg( 19572 rT, 19573 IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)), 19574 rA == 0 ? (mode64 ? mkU64(0) : mkU32(0)) 19575 : getIReg(rA), 19576 getIReg(rB)) 19577 19578 ); 19579 DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi); 19580 goto decode_success; 19581 } 19582 goto decode_failure; 19583 } 19584 break; 19585 19586 19587 case 0x04: 19588 /* AltiVec instructions */ 19589 19590 opc2 = IFIELD(theInstr, 0, 6); 19591 switch (opc2) { 19592 /* AV Mult-Add, Mult-Sum */ 19593 case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm 19594 case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm 19595 case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs 19596 if (!allow_V) goto decode_noV; 19597 if (dis_av_multarith( theInstr )) goto decode_success; 19598 goto decode_failure; 19599 19600 /* AV Permutations */ 19601 case 0x2A: // vsel 19602 case 0x2B: // vperm 19603 case 0x2C: // vsldoi 19604 if (!allow_V) goto decode_noV; 19605 if (dis_av_permute( theInstr )) goto decode_success; 19606 goto decode_failure; 19607 19608 case 0x2D: // vpermxor 19609 if (!allow_isa_2_07) goto decode_noP8; 19610 if (dis_av_permute( theInstr )) goto decode_success; 19611 goto decode_failure; 19612 19613 /* AV Floating Point Mult-Add/Sub */ 19614 case 0x2E: case 0x2F: // vmaddfp, vnmsubfp 19615 if (!allow_V) goto decode_noV; 19616 if (dis_av_fp_arith( theInstr )) goto decode_success; 19617 goto decode_failure; 19618 19619 case 0x3D: case 0x3C: // vaddecuq, vaddeuqm 19620 case 0x3F: case 0x3E: // vsubecuq, vsubeuqm 19621 if (!allow_V) goto decode_noV; 19622 if (dis_av_quad( theInstr)) goto decode_success; 19623 goto decode_failure; 19624 19625 default: 19626 break; // Fall through... 19627 } 19628 19629 opc2 = IFIELD(theInstr, 0, 9); 19630 switch (opc2) { 19631 /* BCD arithmetic */ 19632 case 0x1: case 0x41: // bcdadd, bcdsub 19633 if (!allow_isa_2_07) goto decode_noP8; 19634 if (dis_av_bcd( theInstr )) goto decode_success; 19635 goto decode_failure; 19636 19637 default: 19638 break; // Fall through... 19639 } 19640 19641 opc2 = IFIELD(theInstr, 0, 11); 19642 switch (opc2) { 19643 /* AV Arithmetic */ 19644 case 0x180: // vaddcuw 19645 case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm 19646 case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws 19647 case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws 19648 case 0x580: // vsubcuw 19649 case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm 19650 case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws 19651 case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws 19652 case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw 19653 case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw 19654 case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw 19655 case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw 19656 case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw 19657 case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw 19658 case 0x008: case 0x048: // vmuloub, vmulouh 19659 case 0x108: case 0x148: // vmulosb, vmulosh 19660 case 0x208: case 0x248: // vmuleub, vmuleuh 19661 case 0x308: case 0x348: // vmulesb, vmulesh 19662 case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs 19663 case 0x688: case 0x788: // vsum2sws, vsumsws 19664 if (!allow_V) goto decode_noV; 19665 if (dis_av_arith( theInstr )) goto decode_success; 19666 goto decode_failure; 19667 19668 case 0x088: case 0x089: // vmulouw, vmuluwm 19669 case 0x0C0: case 0x0C2: // vaddudm, vmaxud 19670 case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd 19671 case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw 19672 case 0x4C0: // vsubudm 19673 if (!allow_isa_2_07) goto decode_noP8; 19674 if (dis_av_arith( theInstr )) goto decode_success; 19675 goto decode_failure; 19676 19677 /* AV Polynomial Vector Multiply Add */ 19678 case 0x408: case 0x448: // vpmsumb, vpmsumd 19679 case 0x488: case 0x4C8: // vpmsumw, vpmsumh 19680 if (!allow_isa_2_07) goto decode_noP8; 19681 if (dis_av_polymultarith( theInstr )) goto decode_success; 19682 goto decode_failure; 19683 19684 /* AV Rotate, Shift */ 19685 case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw 19686 case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw 19687 case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw 19688 case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw 19689 case 0x1C4: case 0x2C4: // vsl, vsr 19690 case 0x40C: case 0x44C: // vslo, vsro 19691 if (!allow_V) goto decode_noV; 19692 if (dis_av_shift( theInstr )) goto decode_success; 19693 goto decode_failure; 19694 19695 case 0x0C4: // vrld 19696 case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd 19697 if (!allow_isa_2_07) goto decode_noP8; 19698 if (dis_av_shift( theInstr )) goto decode_success; 19699 goto decode_failure; 19700 19701 /* AV Logic */ 19702 case 0x404: case 0x444: case 0x484: // vand, vandc, vor 19703 case 0x4C4: case 0x504: // vxor, vnor 19704 if (!allow_V) goto decode_noV; 19705 if (dis_av_logic( theInstr )) goto decode_success; 19706 goto decode_failure; 19707 19708 case 0x544: // vorc 19709 case 0x584: case 0x684: // vnand, veqv 19710 if (!allow_isa_2_07) goto decode_noP8; 19711 if (dis_av_logic( theInstr )) goto decode_success; 19712 goto decode_failure; 19713 19714 /* AV Processor Control */ 19715 case 0x604: case 0x644: // mfvscr, mtvscr 19716 if (!allow_V) goto decode_noV; 19717 if (dis_av_procctl( theInstr )) goto decode_success; 19718 goto decode_failure; 19719 19720 /* AV Floating Point Arithmetic */ 19721 case 0x00A: case 0x04A: // vaddfp, vsubfp 19722 case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp 19723 case 0x1CA: // vlogefp 19724 case 0x40A: case 0x44A: // vmaxfp, vminfp 19725 if (!allow_V) goto decode_noV; 19726 if (dis_av_fp_arith( theInstr )) goto decode_success; 19727 goto decode_failure; 19728 19729 /* AV Floating Point Round/Convert */ 19730 case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip 19731 case 0x2CA: // vrfim 19732 case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs 19733 case 0x3CA: // vctsxs 19734 if (!allow_V) goto decode_noV; 19735 if (dis_av_fp_convert( theInstr )) goto decode_success; 19736 goto decode_failure; 19737 19738 /* AV Merge, Splat */ 19739 case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw 19740 case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw 19741 case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw 19742 case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw 19743 if (!allow_V) goto decode_noV; 19744 if (dis_av_permute( theInstr )) goto decode_success; 19745 goto decode_failure; 19746 19747 case 0x68C: case 0x78C: // vmrgow, vmrgew 19748 if (!allow_isa_2_07) goto decode_noP8; 19749 if (dis_av_permute( theInstr )) goto decode_success; 19750 goto decode_failure; 19751 19752 /* AV Pack, Unpack */ 19753 case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus 19754 case 0x0CE: // vpkuwus 19755 case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss 19756 case 0x1CE: // vpkswss 19757 case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb 19758 case 0x2CE: // vupklsh 19759 case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx 19760 if (!allow_V) goto decode_noV; 19761 if (dis_av_pack( theInstr )) goto decode_success; 19762 goto decode_failure; 19763 19764 case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus 19765 case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw 19766 if (!allow_isa_2_07) goto decode_noP8; 19767 if (dis_av_pack( theInstr )) goto decode_success; 19768 goto decode_failure; 19769 19770 case 0x508: case 0x509: // vcipher, vcipherlast 19771 case 0x548: case 0x549: // vncipher, vncipherlast 19772 case 0x5C8: // vsbox 19773 if (!allow_isa_2_07) goto decode_noP8; 19774 if (dis_av_cipher( theInstr )) goto decode_success; 19775 goto decode_failure; 19776 19777 case 0x6C2: case 0x682: // vshasigmaw, vshasigmad 19778 if (!allow_isa_2_07) goto decode_noP8; 19779 if (dis_av_hash( theInstr )) goto decode_success; 19780 goto decode_failure; 19781 19782 case 0x702: case 0x742: // vclzb, vclzh 19783 case 0x782: case 0x7c2: // vclzw, vclzd 19784 if (!allow_isa_2_07) goto decode_noP8; 19785 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 19786 goto decode_failure; 19787 19788 case 0x703: case 0x743: // vpopcntb, vpopcnth 19789 case 0x783: case 0x7c3: // vpopcntw, vpopcntd 19790 if (!allow_isa_2_07) goto decode_noP8; 19791 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 19792 goto decode_failure; 19793 19794 case 0x50c: // vgbbd 19795 if (!allow_isa_2_07) goto decode_noP8; 19796 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success; 19797 goto decode_failure; 19798 19799 case 0x140: case 0x100: // vaddcuq, vadduqm 19800 case 0x540: case 0x500: // vsubcuq, vsubuqm 19801 case 0x54C: // vbpermq 19802 if (!allow_V) goto decode_noV; 19803 if (dis_av_quad( theInstr)) goto decode_success; 19804 goto decode_failure; 19805 19806 default: 19807 break; // Fall through... 19808 } 19809 19810 opc2 = IFIELD(theInstr, 0, 10); 19811 switch (opc2) { 19812 19813 /* AV Compare */ 19814 case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw 19815 case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw 19816 case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw 19817 if (!allow_V) goto decode_noV; 19818 if (dis_av_cmp( theInstr )) goto decode_success; 19819 goto decode_failure; 19820 19821 case 0x0C7: // vcmpequd 19822 case 0x2C7: // vcmpgtud 19823 case 0x3C7: // vcmpgtsd 19824 if (!allow_isa_2_07) goto decode_noP8; 19825 if (dis_av_cmp( theInstr )) goto decode_success; 19826 goto decode_failure; 19827 19828 /* AV Floating Point Compare */ 19829 case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp 19830 case 0x3C6: // vcmpbfp 19831 if (!allow_V) goto decode_noV; 19832 if (dis_av_fp_cmp( theInstr )) goto decode_success; 19833 goto decode_failure; 19834 19835 default: 19836 goto decode_failure; 19837 } 19838 break; 19839 19840 default: 19841 goto decode_failure; 19842 19843 decode_noF: 19844 vassert(!allow_F); 19845 vex_printf("disInstr(ppc): declined to decode an FP insn.\n"); 19846 goto decode_failure; 19847 decode_noV: 19848 vassert(!allow_V); 19849 vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n"); 19850 goto decode_failure; 19851 decode_noVX: 19852 vassert(!allow_VX); 19853 vex_printf("disInstr(ppc): declined to decode a Power ISA 2.06 insn.\n"); 19854 goto decode_failure; 19855 decode_noFX: 19856 vassert(!allow_FX); 19857 vex_printf("disInstr(ppc): " 19858 "declined to decode a GeneralPurpose-Optional insn.\n"); 19859 goto decode_failure; 19860 decode_noGX: 19861 vassert(!allow_GX); 19862 vex_printf("disInstr(ppc): " 19863 "declined to decode a Graphics-Optional insn.\n"); 19864 goto decode_failure; 19865 decode_noDFP: 19866 vassert(!allow_DFP); 19867 vex_printf("disInstr(ppc): " 19868 "declined to decode a Decimal Floating Point insn.\n"); 19869 goto decode_failure; 19870 decode_noP8: 19871 vassert(!allow_isa_2_07); 19872 vex_printf("disInstr(ppc): " 19873 "declined to decode a Power 8 insn.\n"); 19874 goto decode_failure; 19875 19876 19877 decode_failure: 19878 /* All decode failures end up here. */ 19879 opc2 = (theInstr) & 0x7FF; 19880 if (sigill_diag) { 19881 vex_printf("disInstr(ppc): unhandled instruction: " 19882 "0x%x\n", theInstr); 19883 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n", 19884 opc1, opc1, opc2, opc2); 19885 } 19886 19887 /* Tell the dispatcher that this insn cannot be decoded, and so has 19888 not been executed, and (is currently) the next to be executed. 19889 CIA should be up-to-date since it made so at the start of each 19890 insn, but nevertheless be paranoid and update it again right 19891 now. */ 19892 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) ); 19893 dres.whatNext = Dis_StopHere; 19894 dres.jk_StopHere = Ijk_NoDecode; 19895 dres.len = 0; 19896 return dres; 19897 19898 } /* switch (opc) for the main (primary) opcode switch. */ 19899 19900 decode_success: 19901 /* All decode successes end up here. */ 19902 switch (dres.whatNext) { 19903 case Dis_Continue: 19904 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4)); 19905 break; 19906 case Dis_ResteerU: 19907 case Dis_ResteerC: 19908 putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt)); 19909 break; 19910 case Dis_StopHere: 19911 break; 19912 default: 19913 vassert(0); 19914 } 19915 DIP("\n"); 19916 19917 if (dres.len == 0) { 19918 dres.len = 4; 19919 } else { 19920 vassert(dres.len == 20); 19921 } 19922 return dres; 19923 } 19924 19925 #undef DIP 19926 #undef DIS 19927 19928 19929 /*------------------------------------------------------------*/ 19930 /*--- Top-level fn ---*/ 19931 /*------------------------------------------------------------*/ 19932 19933 /* Disassemble a single instruction into IR. The instruction 19934 is located in host memory at &guest_code[delta]. */ 19935 19936 DisResult disInstr_PPC ( IRSB* irsb_IN, 19937 Bool (*resteerOkFn) ( void*, Addr64 ), 19938 Bool resteerCisOk, 19939 void* callback_opaque, 19940 UChar* guest_code_IN, 19941 Long delta, 19942 Addr64 guest_IP, 19943 VexArch guest_arch, 19944 VexArchInfo* archinfo, 19945 VexAbiInfo* abiinfo, 19946 Bool host_bigendian_IN, 19947 Bool sigill_diag_IN ) 19948 { 19949 IRType ty; 19950 DisResult dres; 19951 UInt mask32, mask64; 19952 UInt hwcaps_guest = archinfo->hwcaps; 19953 19954 vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64); 19955 19956 /* global -- ick */ 19957 mode64 = guest_arch == VexArchPPC64; 19958 ty = mode64 ? Ity_I64 : Ity_I32; 19959 19960 /* do some sanity checks */ 19961 mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V 19962 | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX 19963 | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07; 19964 19965 mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX 19966 | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP 19967 | VEX_HWCAPS_PPC64_ISA2_07; 19968 19969 if (mode64) { 19970 vassert((hwcaps_guest & mask32) == 0); 19971 } else { 19972 vassert((hwcaps_guest & mask64) == 0); 19973 } 19974 19975 /* Set globals (see top of this file) */ 19976 guest_code = guest_code_IN; 19977 irsb = irsb_IN; 19978 host_is_bigendian = host_bigendian_IN; 19979 19980 guest_CIA_curr_instr = mkSzAddr(ty, guest_IP); 19981 guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta); 19982 19983 dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque, 19984 delta, archinfo, abiinfo, sigill_diag_IN ); 19985 19986 return dres; 19987 } 19988 19989 19990 /*------------------------------------------------------------*/ 19991 /*--- Unused stuff ---*/ 19992 /*------------------------------------------------------------*/ 19993 19994 ///* A potentially more memcheck-friendly implementation of Clz32, with 19995 // the boundary case Clz32(0) = 32, which is what ppc requires. */ 19996 // 19997 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg ) 19998 //{ 19999 // /* Welcome ... to SSA R Us. */ 20000 // IRTemp n1 = newTemp(Ity_I32); 20001 // IRTemp n2 = newTemp(Ity_I32); 20002 // IRTemp n3 = newTemp(Ity_I32); 20003 // IRTemp n4 = newTemp(Ity_I32); 20004 // IRTemp n5 = newTemp(Ity_I32); 20005 // IRTemp n6 = newTemp(Ity_I32); 20006 // IRTemp n7 = newTemp(Ity_I32); 20007 // IRTemp n8 = newTemp(Ity_I32); 20008 // IRTemp n9 = newTemp(Ity_I32); 20009 // IRTemp n10 = newTemp(Ity_I32); 20010 // IRTemp n11 = newTemp(Ity_I32); 20011 // IRTemp n12 = newTemp(Ity_I32); 20012 // 20013 // /* First, propagate the most significant 1-bit into all lower 20014 // positions in the word. */ 20015 // /* unsigned int clz ( unsigned int n ) 20016 // { 20017 // n |= (n >> 1); 20018 // n |= (n >> 2); 20019 // n |= (n >> 4); 20020 // n |= (n >> 8); 20021 // n |= (n >> 16); 20022 // return bitcount(~n); 20023 // } 20024 // */ 20025 // assign(n1, mkexpr(arg)); 20026 // assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1)))); 20027 // assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2)))); 20028 // assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4)))); 20029 // assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8)))); 20030 // assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16)))); 20031 // /* This gives a word of the form 0---01---1. Now invert it, giving 20032 // a word of the form 1---10---0, then do a population-count idiom 20033 // (to count the 1s, which is the number of leading zeroes, or 32 20034 // if the original word was 0. */ 20035 // assign(n7, unop(Iop_Not32, mkexpr(n6))); 20036 // 20037 // /* unsigned int bitcount ( unsigned int n ) 20038 // { 20039 // n = n - ((n >> 1) & 0x55555555); 20040 // n = (n & 0x33333333) + ((n >> 2) & 0x33333333); 20041 // n = (n + (n >> 4)) & 0x0F0F0F0F; 20042 // n = n + (n >> 8); 20043 // n = (n + (n >> 16)) & 0x3F; 20044 // return n; 20045 // } 20046 // */ 20047 // assign(n8, 20048 // binop(Iop_Sub32, 20049 // mkexpr(n7), 20050 // binop(Iop_And32, 20051 // binop(Iop_Shr32, mkexpr(n7), mkU8(1)), 20052 // mkU32(0x55555555)))); 20053 // assign(n9, 20054 // binop(Iop_Add32, 20055 // binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)), 20056 // binop(Iop_And32, 20057 // binop(Iop_Shr32, mkexpr(n8), mkU8(2)), 20058 // mkU32(0x33333333)))); 20059 // assign(n10, 20060 // binop(Iop_And32, 20061 // binop(Iop_Add32, 20062 // mkexpr(n9), 20063 // binop(Iop_Shr32, mkexpr(n9), mkU8(4))), 20064 // mkU32(0x0F0F0F0F))); 20065 // assign(n11, 20066 // binop(Iop_Add32, 20067 // mkexpr(n10), 20068 // binop(Iop_Shr32, mkexpr(n10), mkU8(8)))); 20069 // assign(n12, 20070 // binop(Iop_Add32, 20071 // mkexpr(n11), 20072 // binop(Iop_Shr32, mkexpr(n11), mkU8(16)))); 20073 // return 20074 // binop(Iop_And32, mkexpr(n12), mkU32(0x3F)); 20075 //} 20076 20077 /*--------------------------------------------------------------------*/ 20078 /*--- end guest_ppc_toIR.c ---*/ 20079 /*--------------------------------------------------------------------*/ 20080